[Freeswitch-svn] [commit] r13086 - in freeswitch/trunk/libs/spandsp: . debian doc src src/msvc src/spandsp src/spandsp/private test-data/etsi/fax tests

FreeSWITCH SVN mikej at freeswitch.org
Mon Apr 20 11:33:33 PDT 2009


Author: mikej
Date: Mon Apr 20 13:33:33 2009
New Revision: 13086

Log:
update to snapshot spandsp-20090421

Added:
   freeswitch/trunk/libs/spandsp/debian/libspandsp6.install
   freeswitch/trunk/libs/spandsp/src/spandsp/private/silence_gen.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/v18.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v18.h
   freeswitch/trunk/libs/spandsp/src/v18.c
   freeswitch/trunk/libs/spandsp/tests/fax_utils.h
   freeswitch/trunk/libs/spandsp/tests/v18_tests.c
Removed:
   freeswitch/trunk/libs/spandsp/debian/libspandsp5.install
Modified:
   freeswitch/trunk/libs/spandsp/Makefile.am
   freeswitch/trunk/libs/spandsp/configure.ac
   freeswitch/trunk/libs/spandsp/debian/changelog
   freeswitch/trunk/libs/spandsp/debian/control
   freeswitch/trunk/libs/spandsp/doc/doxygen.in
   freeswitch/trunk/libs/spandsp/src/Makefile.am
   freeswitch/trunk/libs/spandsp/src/adsi.c
   freeswitch/trunk/libs/spandsp/src/at_interpreter.c
   freeswitch/trunk/libs/spandsp/src/bell_r2_mf.c
   freeswitch/trunk/libs/spandsp/src/bert.c
   freeswitch/trunk/libs/spandsp/src/dtmf.c
   freeswitch/trunk/libs/spandsp/src/fax.c
   freeswitch/trunk/libs/spandsp/src/fax_modems.c
   freeswitch/trunk/libs/spandsp/src/fsk.c
   freeswitch/trunk/libs/spandsp/src/gsm0610_local.h
   freeswitch/trunk/libs/spandsp/src/gsm0610_long_term.c
   freeswitch/trunk/libs/spandsp/src/ima_adpcm.c
   freeswitch/trunk/libs/spandsp/src/libspandsp.2005.vcproj
   freeswitch/trunk/libs/spandsp/src/libspandsp.2008.vcproj
   freeswitch/trunk/libs/spandsp/src/libspandsp.dsp
   freeswitch/trunk/libs/spandsp/src/msvc/spandsp.h
   freeswitch/trunk/libs/spandsp/src/queue.c
   freeswitch/trunk/libs/spandsp/src/sig_tone.c
   freeswitch/trunk/libs/spandsp/src/silence_gen.c
   freeswitch/trunk/libs/spandsp/src/spandsp.h.in
   freeswitch/trunk/libs/spandsp/src/spandsp/adsi.h
   freeswitch/trunk/libs/spandsp/src/spandsp/expose.h
   freeswitch/trunk/libs/spandsp/src/spandsp/fast_convert.h
   freeswitch/trunk/libs/spandsp/src/spandsp/fax.h
   freeswitch/trunk/libs/spandsp/src/spandsp/fsk.h
   freeswitch/trunk/libs/spandsp/src/spandsp/g711.h
   freeswitch/trunk/libs/spandsp/src/spandsp/g722.h
   freeswitch/trunk/libs/spandsp/src/spandsp/g726.h
   freeswitch/trunk/libs/spandsp/src/spandsp/ima_adpcm.h
   freeswitch/trunk/libs/spandsp/src/spandsp/lpc10.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/adsi.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/bert.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/fax_modems.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/fsk.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/g711.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/g722.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/g726.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/lpc10.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/sig_tone.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/t30.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_core.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_gateway.h
   freeswitch/trunk/libs/spandsp/src/spandsp/private/v22bis.h
   freeswitch/trunk/libs/spandsp/src/spandsp/sig_tone.h
   freeswitch/trunk/libs/spandsp/src/spandsp/silence_gen.h
   freeswitch/trunk/libs/spandsp/src/spandsp/t30.h
   freeswitch/trunk/libs/spandsp/src/spandsp/t30_api.h
   freeswitch/trunk/libs/spandsp/src/spandsp/t31.h
   freeswitch/trunk/libs/spandsp/src/spandsp/t38_core.h
   freeswitch/trunk/libs/spandsp/src/spandsp/t38_gateway.h
   freeswitch/trunk/libs/spandsp/src/spandsp/t4.h
   freeswitch/trunk/libs/spandsp/src/spandsp/telephony.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v17rx.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v17tx.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v22bis.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_rx.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_tx.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v29rx.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v29tx.h
   freeswitch/trunk/libs/spandsp/src/spandsp/v42bis.h
   freeswitch/trunk/libs/spandsp/src/spandsp/version.h
   freeswitch/trunk/libs/spandsp/src/t30.c
   freeswitch/trunk/libs/spandsp/src/t30_logging.c
   freeswitch/trunk/libs/spandsp/src/t31.c
   freeswitch/trunk/libs/spandsp/src/t35.c
   freeswitch/trunk/libs/spandsp/src/t38_gateway.c
   freeswitch/trunk/libs/spandsp/src/t38_terminal.c
   freeswitch/trunk/libs/spandsp/src/t4.c
   freeswitch/trunk/libs/spandsp/src/tone_detect.c
   freeswitch/trunk/libs/spandsp/src/tone_generate.c
   freeswitch/trunk/libs/spandsp/src/v17rx.c
   freeswitch/trunk/libs/spandsp/src/v17tx.c
   freeswitch/trunk/libs/spandsp/src/v22bis_rx.c
   freeswitch/trunk/libs/spandsp/src/v22bis_tx.c
   freeswitch/trunk/libs/spandsp/src/v27ter_rx.c
   freeswitch/trunk/libs/spandsp/src/v27ter_tx.c
   freeswitch/trunk/libs/spandsp/src/v29rx.c
   freeswitch/trunk/libs/spandsp/src/v29tx.c
   freeswitch/trunk/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c
   freeswitch/trunk/libs/spandsp/tests/Makefile.am
   freeswitch/trunk/libs/spandsp/tests/adsi_tests.c
   freeswitch/trunk/libs/spandsp/tests/bell_mf_rx_tests.c
   freeswitch/trunk/libs/spandsp/tests/bert_tests.c
   freeswitch/trunk/libs/spandsp/tests/fsk_tests.c
   freeswitch/trunk/libs/spandsp/tests/queue_tests.c
   freeswitch/trunk/libs/spandsp/tests/r2_mf_rx_tests.c
   freeswitch/trunk/libs/spandsp/tests/regression_tests.sh
   freeswitch/trunk/libs/spandsp/tests/v17_tests.c
   freeswitch/trunk/libs/spandsp/tests/v22bis_tests.c
   freeswitch/trunk/libs/spandsp/tests/v27ter_tests.c
   freeswitch/trunk/libs/spandsp/tests/v29_tests.c

Modified: freeswitch/trunk/libs/spandsp/Makefile.am
==============================================================================
--- freeswitch/trunk/libs/spandsp/Makefile.am	(original)
+++ freeswitch/trunk/libs/spandsp/Makefile.am	Mon Apr 20 13:33:33 2009
@@ -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.45 2008/11/28 12:41:25 steveu Exp $
+## $Id: Makefile.am,v 1.46 2009/03/19 14:13:12 steveu Exp $
 
 AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
 AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@@ -42,7 +42,7 @@
              debian/compat \
              debian/control \
              debian/copyright \
-             debian/libspandsp5.install \
+             debian/libspandsp6.install \
              debian/libspandsp-dev.install \
              debian/libspandsp-doc.install \
              debian/rules \

Modified: freeswitch/trunk/libs/spandsp/configure.ac
==============================================================================
--- freeswitch/trunk/libs/spandsp/configure.ac	(original)
+++ freeswitch/trunk/libs/spandsp/configure.ac	Mon Apr 20 13:33:33 2009
@@ -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.66 2009/02/10 17:20:31 steveu Exp $
+# $Id: configure.ac,v 1.67 2009/03/28 17:14:53 steveu Exp $
 
 # @start 1
 
@@ -271,7 +271,7 @@
 if test -n "$enable_tests" ; then
     AC_LANG([C])
     AC_CHECK_LIB([audiofile], [afOpenFile], TESTLIBS="$TESTLIBS -laudiofile", AC_MSG_ERROR("Can't make tests without libaudiofile (does your system require a libaudiofile-devel package?)"))
-    AC_CHECK_LIB([fftw3], [fftw_plan_dft_1d], TESTLIBS="$TESTLIBS -lfftw3", [AC_CHECK_LIB([fftw], [fftw_create_plan], TESTLIBS="$TESTLIBS -lfftw")])
+    AC_CHECK_LIB([fftw3], [fftw_plan_dft_1d], TESTLIBS="$TESTLIBS -lfftw3", [AC_CHECK_LIB([fftw], [fftw_create_plan], TESTLIBS="$TESTLIBS -lfftw", AC_MSG_ERROR("Can't make tests without FFTW 2 or 3 (does your system require an fftw?-devel package?)"))])
     AC_CHECK_LIB([pthread], [pthread_attr_init], TESTLIBS="$TESTLIBS -lpthread")
     AC_CHECK_LIB([dl], [dlopen], TESTLIBS="$TESTLIBS -ldl")
     AC_CHECK_LIB([Xft], [XftFontOpen], TESTLIBS="$TESTLIBS -lXft",, $TESTLIBS)

Modified: freeswitch/trunk/libs/spandsp/debian/changelog
==============================================================================
--- freeswitch/trunk/libs/spandsp/debian/changelog	(original)
+++ freeswitch/trunk/libs/spandsp/debian/changelog	Mon Apr 20 13:33:33 2009
@@ -1,3 +1,13 @@
+spandsp (0.0.6~pre7-1) unstable; urgency=low
+
+  [ Steve Underwood ]
+  * New upstream release.
+  * Fixed upstream file name for get-orig-source.
+  * Updates to 64bit archs support
+  * Removal of obsoleted files
+
+ -- Steve Underwood <steveu at coppice.org>  Sat, 14 Mar 2009 09:23:36 +0100
+
 spandsp (0.0.5~pre2-1) unstable; urgency=low
 
   [ Massimo Cetra ]

Modified: freeswitch/trunk/libs/spandsp/debian/control
==============================================================================
--- freeswitch/trunk/libs/spandsp/debian/control	(original)
+++ freeswitch/trunk/libs/spandsp/debian/control	Mon Apr 20 13:33:33 2009
@@ -8,7 +8,7 @@
 XS-Vcs-Svn: svn://svn.debian.org/pkg-voip/
 XS-Vcs-Browser: http://svn.debian.org/wsvn/pkg-voip/
 
-Package: libspandsp5
+Package: libspandsp6
 Architecture: any
 Depends: ${shlibs:Depends}
 Conflicts: libspandsp0, libspandsp1, libspandsp2
@@ -22,7 +22,7 @@
 Package: libspandsp-dev
 Section: libdevel
 Architecture: any
-Depends: libspandsp5 (= ${Source-Version}), libtiff4-dev, libjpeg62-dev
+Depends: libspandsp6 (= ${Source-Version}), libtiff4-dev, libjpeg62-dev
 Description: Telephony signal processing library
  This is a low-level signal processing library that modulate and demodulate
  signals commonly used in telephony, such as the "noise" generated by a

Added: freeswitch/trunk/libs/spandsp/debian/libspandsp6.install
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/debian/libspandsp6.install	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,2 @@
+debian/tmp/usr/lib*/libspandsp.so.2.*
+debian/tmp/usr/lib*/libspandsp.so.2

Modified: freeswitch/trunk/libs/spandsp/doc/doxygen.in
==============================================================================
--- freeswitch/trunk/libs/spandsp/doc/doxygen.in	(original)
+++ freeswitch/trunk/libs/spandsp/doc/doxygen.in	Mon Apr 20 13:33:33 2009
@@ -53,16 +53,6 @@
 
 OUTPUT_LANGUAGE        = English
 
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING   = YES
-
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
 # include brief member descriptions after the members that are listed in 
 # the file and class documentation (similar to JavaDoc). 
@@ -148,13 +138,6 @@
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
-# documentation.
-
-DETAILS_AT_TOP         = NO
-
 # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
 # member inherits the documentation from any documented member that it 
 # re-implements.
@@ -963,7 +946,7 @@
 # compilation will be performed. Macro expansion can be done in a controlled 
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
-MACRO_EXPANSION        = NO
+MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
 # then the macro expansion is limited to the macros specified with the 
@@ -997,7 +980,7 @@
 # undefined via #undef or recursively expanded use the := operator 
 # instead of the = operator.
 
-PREDEFINED             = 
+PREDEFINED             = SPAN_DECLARE(x)=x
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
@@ -1164,22 +1147,6 @@
 
 DOTFILE_DIRS           = 
 
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
-
 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
 # graphs generated by dot. A depth value of 3 means that only nodes reachable 
 # from the root by following a path via at most 3 edges will be shown. Nodes 

Modified: freeswitch/trunk/libs/spandsp/src/Makefile.am
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/Makefile.am	(original)
+++ freeswitch/trunk/libs/spandsp/src/Makefile.am	Mon Apr 20 13:33:33 2009
@@ -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.128 2009/03/01 12:49:28 steveu Exp $
+## $Id: Makefile.am,v 1.130 2009/04/16 13:09:40 steveu Exp $
 
 AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
 AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@@ -126,6 +126,7 @@
                         tone_generate.c \
                         v17rx.c \
                         v17tx.c \
+                        v18.c \
                         v22bis_rx.c \
                         v22bis_tx.c \
                         v27ter_rx.c \
@@ -205,6 +206,7 @@
                          spandsp/tone_generate.h \
                          spandsp/v17rx.h \
                          spandsp/v17tx.h \
+                         spandsp/v18.h \
                          spandsp/v22bis.h \
                          spandsp/v27ter_rx.h \
                          spandsp/v27ter_tx.h \
@@ -241,6 +243,7 @@
                          spandsp/private/queue.h \
                          spandsp/private/schedule.h \
                          spandsp/private/sig_tone.h \
+                         spandsp/private/silence_gen.h \
                          spandsp/private/super_tone_rx.h \
                          spandsp/private/super_tone_tx.h \
                          spandsp/private/t30.h \
@@ -255,6 +258,7 @@
                          spandsp/private/tone_generate.h \
                          spandsp/private/v17rx.h \
                          spandsp/private/v17tx.h \
+                         spandsp/private/v18.h \
                          spandsp/private/v22bis.h \
                          spandsp/private/v27ter_rx.h \
                          spandsp/private/v27ter_tx.h \

Modified: freeswitch/trunk/libs/spandsp/src/adsi.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/adsi.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/adsi.c	Mon Apr 20 13:33:33 2009
@@ -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: adsi.c,v 1.70 2009/02/10 13:06:46 steveu Exp $
+ * $Id: adsi.c,v 1.76 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -69,14 +69,19 @@
 #include "spandsp/private/dtmf.h"
 #include "spandsp/private/adsi.h"
 
+/*! The baudot code to shift from alpha to digits and symbols */
 #define BAUDOT_FIGURE_SHIFT     0x1B
+/*! The baudot code to shift from digits and symbols to alpha */
 #define BAUDOT_LETTER_SHIFT     0x1F
 
-#define SOH 0x01
-#define STX 0x02
-#define ETX 0x03
-#define DLE 0x10
-#define SUB 0x1A
+enum
+{
+    SOH = 0x01,
+    STX = 0x02,
+    ETX = 0x03,
+    DLE = 0x10,
+    SUB = 0x1A
+};
 
 static uint16_t adsi_encode_baudot(adsi_tx_state_t *s, uint8_t ch);
 static uint8_t adsi_decode_baudot(adsi_rx_state_t *s, uint8_t ch);
@@ -183,18 +188,16 @@
     if (bit < 0)
     {
         /* Special conditions */
+        span_log(&s->logging, SPAN_LOG_FLOW, "ADSI signal status is %s (%d)\n", signal_status_to_str(bit), bit);
         switch (bit)
         {
         case SIG_STATUS_CARRIER_UP:
-            span_log(&s->logging, SPAN_LOG_FLOW, "Carrier up.\n");
             s->consecutive_ones = 0;
             s->bit_pos = 0;
             s->in_progress = 0;
             s->msg_len = 0;
-            s->baudot_shift = 0;
             break;
         case SIG_STATUS_CARRIER_DOWN:
-            span_log(&s->logging, SPAN_LOG_FLOW, "Carrier down.\n");
             break;
         default:
             span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put bit value - %d!\n", bit);
@@ -303,10 +306,11 @@
     uint8_t octet;
     
     s = (adsi_rx_state_t *) user_data;
+    //printf("Rx bit %x\n", bit);
     if (byte < 0)
     {
         /* Special conditions */
-        printf("Status is %s (%d)\n", signal_status_to_str(byte), byte);
+        span_log(&s->logging, SPAN_LOG_FLOW, "ADSI signal status is %s (%d)\n", signal_status_to_str(byte), byte);
         switch (byte)
         {
         case SIG_STATUS_CARRIER_UP:
@@ -314,7 +318,6 @@
             s->bit_pos = 0;
             s->in_progress = 0;
             s->msg_len = 0;
-            s->baudot_shift = 0;
             break;
         case SIG_STATUS_CARRIER_DOWN:
             if (s->msg_len > 0)
@@ -330,7 +333,7 @@
         }
         return;
     }
-    if ((octet = adsi_decode_baudot(s, (uint8_t) byte)))
+    if ((octet = adsi_decode_baudot(s, (uint8_t) (byte & 0x1F))))
         s->msg[s->msg_len++] = octet;
     if (s->msg_len >= 256)
     {
@@ -393,7 +396,7 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t *amp, int len)
+SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len)
 {
     switch (s->standard)
     {
@@ -439,8 +442,9 @@
         dtmf_rx_init(&(s->dtmfrx), adsi_rx_dtmf, s);
         break;
     case ADSI_STANDARD_TDD:
-        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FALSE, async_rx_put_bit, &(s->asyncrx));
-        async_rx_init(&(s->asyncrx), 5, ASYNC_PARITY_NONE, 2, TRUE, adsi_tdd_put_async_byte, s);
+        /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
+           ride over the fraction. */
+        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], 7, adsi_tdd_put_async_byte, s);
         break;
     }
     s->standard = standard;
@@ -462,7 +466,7 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t *amp, int max_len)
+SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
 {
     int len;
     int lenx;

Modified: freeswitch/trunk/libs/spandsp/src/at_interpreter.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/at_interpreter.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/at_interpreter.c	Mon Apr 20 13:33:33 2009
@@ -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.36 2009/02/10 13:06:46 steveu Exp $
+ * $Id: at_interpreter.c,v 1.37 2009/03/23 14:17:42 steveu Exp $
  */
 
 /*! \file */
@@ -52,6 +52,8 @@
 #include "spandsp/async.h"
 #include "spandsp/hdlc.h"
 #include "spandsp/fsk.h"
+#include "spandsp/super_tone_rx.h"
+#include "spandsp/fax_modems.h"
 
 #include "spandsp/at_interpreter.h"
 
@@ -111,18 +113,6 @@
 #define DLE 0x10
 #define SUB 0x1A
 
-/* BEWARE: right now this must match up with a list in the T.31 code. */
-enum
-{
-    T31_NONE = -1,
-    T31_FLUSH = 0,
-    T31_SILENCE_TX,
-    T31_SILENCE_RX,
-    T31_CED_TONE,
-    T31_CNG_TONE,
-    T31_NOCNG_TONE,
-};
-
 static const char *at_response_codes[] =
 {
     "OK",
@@ -239,7 +229,7 @@
         {
             /* FAX modem connection */
             at_set_at_rx_mode(s, AT_MODE_DELIVERY);
-            at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_CED_TONE);
+            at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_CED_TONE);
         }
         break;
     case AT_CALL_EVENT_CONNECTED:
@@ -256,9 +246,9 @@
             /* FAX modem connection */
             at_set_at_rx_mode(s, AT_MODE_DELIVERY);
             if (s->silent_dial)
-                at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_NOCNG_TONE);
+                at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_NOCNG_TONE);
             else
-                at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_CNG_TONE);
+                at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_CNG_TONE);
             s->dte_is_waiting = TRUE;
         }
         break;
@@ -931,7 +921,7 @@
     if (s->at_rx_mode != AT_MODE_ONHOOK_COMMAND  &&  s->at_rx_mode != AT_MODE_OFFHOOK_COMMAND)
     {
         /* Push out the last of the audio (probably by sending a short silence). */
-        at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_FLUSH);
+        at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_FLUSH);
         s->do_hangup = TRUE;
         at_set_at_rx_mode(s, AT_MODE_CONNECTED);
         return (const char *) -1;

Modified: freeswitch/trunk/libs/spandsp/src/bell_r2_mf.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/bell_r2_mf.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/bell_r2_mf.c	Mon Apr 20 13:33:33 2009
@@ -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: bell_r2_mf.c,v 1.38 2009/02/10 13:06:46 steveu Exp $
+ * $Id: bell_r2_mf.c,v 1.39 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -67,6 +67,9 @@
 
 #define ms_to_samples(t)            (((t)*SAMPLE_RATE)/1000)
 
+/*!
+    MF tone descriptor.
+*/
 typedef struct
 {
     int         f1;         /* First freq */

Modified: freeswitch/trunk/libs/spandsp/src/bert.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/bert.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/bert.c	Mon Apr 20 13:33:33 2009
@@ -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: bert.c,v 1.32 2009/02/10 13:06:46 steveu Exp $
+ * $Id: bert.c,v 1.33 2009/04/14 16:04:53 steveu Exp $
  */
 
 #if defined(HAVE_CONFIG_H)
@@ -44,6 +44,8 @@
 #include "spandsp/private/logging.h"
 #include "spandsp/private/bert.h"
 
+#define MEASUREMENT_STEP    100
+
 static const char *qbf = "VoyeZ Le BricK GeanT QuE J'ExaminE PreS Du WharF 123 456 7890 + - * : = $ % ( )"
                          "ThE QuicK BrowN FoX JumpS OveR ThE LazY DoG 123 456 7890 + - * : = $ % ( )";
 
@@ -80,53 +82,53 @@
 {
     int bit;
 
-    if (s->limit  &&  s->tx_bits >= s->limit)
+    if (s->limit  &&  s->tx.bits >= s->limit)
         return SIG_STATUS_END_OF_DATA;
     bit = 0;
     switch (s->pattern_class)
     {
     case 0:
-        bit = s->tx_reg & 1;
-        s->tx_reg = (s->tx_reg >> 1) | ((s->tx_reg & 1) << s->shift2);
+        bit = s->tx.reg & 1;
+        s->tx.reg = (s->tx.reg >> 1) | ((s->tx.reg & 1) << s->shift2);
         break;
     case 1:
-        bit = s->tx_reg & 1;
-        s->tx_reg = (s->tx_reg >> 1) | (((s->tx_reg ^ (s->tx_reg >> s->shift)) & 1) << s->shift2);
+        bit = s->tx.reg & 1;
+        s->tx.reg = (s->tx.reg >> 1) | (((s->tx.reg ^ (s->tx.reg >> s->shift)) & 1) << s->shift2);
         if (s->max_zeros)
         {
             /* This generator suppresses runs >s->max_zeros */
             if (bit)
             {
-                if (++s->tx_zeros > s->max_zeros)
+                if (++s->tx.zeros > s->max_zeros)
                 {
-                    s->tx_zeros = 0;
+                    s->tx.zeros = 0;
                     bit ^= 1;
                 }
             }
             else
             {
-                s->tx_zeros = 0;
+                s->tx.zeros = 0;
             }
         }
         bit ^= s->invert;
         break;
     case 2:
-        if (s->tx_step_bit == 0)
+        if (s->tx.step_bit == 0)
         {
-            s->tx_step_bit = 7;
-            s->tx_reg = qbf[s->tx_step++];
-            if (s->tx_reg == 0)
+            s->tx.step_bit = 7;
+            s->tx.reg = qbf[s->tx.step++];
+            if (s->tx.reg == 0)
             {
-                s->tx_reg = 'V';
-                s->tx_step = 1;
+                s->tx.reg = 'V';
+                s->tx.step = 1;
             }
         }
-        bit = s->tx_reg & 1;
-        s->tx_reg >>= 1;
-        s->tx_step_bit--;
+        bit = s->tx.reg & 1;
+        s->tx.reg >>= 1;
+        s->tx.step_bit--;
         break;
     }
-    s->tx_bits++;
+    s->tx.bits++;
     return bit;
 }
 /*- End of function --------------------------------------------------------*/
@@ -192,58 +194,58 @@
         return;
     }
     bit = (bit & 1) ^ s->invert;
-    s->rx_bits++;
+    s->rx.bits++;
     switch (s->pattern_class)
     {
     case 0:
-        if (s->resync)
+        if (s->rx.resync)
         {
-            s->rx_reg = (s->rx_reg >> 1) | (bit << s->shift2);
-            s->ref_reg = (s->ref_reg >> 1) | ((s->ref_reg & 1) << s->shift2);
-            if (s->rx_reg == s->ref_reg)
+            s->rx.reg = (s->rx.reg >> 1) | (bit << s->shift2);
+            s->rx.ref_reg = (s->rx.ref_reg >> 1) | ((s->rx.ref_reg & 1) << s->shift2);
+            if (s->rx.reg == s->rx.ref_reg)
             {
-                if (++s->resync > s->resync_time)
+                if (++s->rx.resync > s->resync_time)
                 {
-                    s->resync = 0;
+                    s->rx.resync = 0;
                     if (s->reporter)
                         s->reporter(s->user_data, BERT_REPORT_SYNCED, &s->results);
                 }
             }
             else
             {
-                s->resync = 2;
-                s->ref_reg = s->master_reg;
+                s->rx.resync = 2;
+                s->rx.ref_reg = s->rx.master_reg;
             }
         }
         else
         {
             s->results.total_bits++;
-            if ((bit ^ s->ref_reg) & 1)
+            if ((bit ^ s->rx.ref_reg) & 1)
                 s->results.bad_bits++;
-            s->ref_reg = (s->ref_reg >> 1) | ((s->ref_reg & 1) << s->shift2);
+            s->rx.ref_reg = (s->rx.ref_reg >> 1) | ((s->rx.ref_reg & 1) << s->shift2);
         }
         break;
     case 1:
-        if (s->resync)
+        if (s->rx.resync)
         {
             /* If we get a reasonable period for which we correctly predict the
                next bit, we must be in sync. */
             /* Don't worry about max. zeros tests when resyncing.
                It might just extend the resync time a little. Trying
                to include the test might affect robustness. */
-            if (bit == (int) ((s->rx_reg >> s->shift) & 1))
+            if (bit == (int) ((s->rx.reg >> s->shift) & 1))
             {
-                if (++s->resync > s->resync_time)
+                if (++s->rx.resync > s->resync_time)
                 {
-                    s->resync = 0;
+                    s->rx.resync = 0;
                     if (s->reporter)
                         s->reporter(s->user_data, BERT_REPORT_SYNCED, &s->results);
                 }
             }
             else
             {
-                s->resync = 2;
-                s->rx_reg ^= s->mask;
+                s->rx.resync = 2;
+                s->rx.reg ^= s->mask;
             }
         }
         else
@@ -252,73 +254,73 @@
             if (s->max_zeros)
             {
                 /* This generator suppresses runs >s->max_zeros */
-                if ((s->rx_reg & s->mask))
+                if ((s->rx.reg & s->mask))
                 {
-                    if (++s->rx_zeros > s->max_zeros)
+                    if (++s->rx.zeros > s->max_zeros)
                     {
-                        s->rx_zeros = 0;
+                        s->rx.zeros = 0;
                         bit ^= 1;
                     }
                 }
                 else
                 {
-                    s->rx_zeros = 0;
+                    s->rx.zeros = 0;
                 }
             }
-            if (bit != (int) ((s->rx_reg >> s->shift) & 1))
+            if (bit != (int) ((s->rx.reg >> s->shift) & 1))
             {
                 s->results.bad_bits++;
-                s->resync_bad_bits++;
+                s->rx.resync_bad_bits++;
                 s->decade_bad[2][s->decade_ptr[2]]++;
             }
-            if (--s->step <= 0)
+            if (--s->rx.measurement_step <= 0)
             {
                 /* Every hundred bits we need to do the error rate measurement */
-                s->step = 100;
+                s->rx.measurement_step = MEASUREMENT_STEP;
                 assess_error_rate(s);
             }
-            if (--s->resync_cnt <= 0)
+            if (--s->rx.resync_cnt <= 0)
             {
                 /* Check if there were enough bad bits during this period to
                    justify a resync. */
-                if (s->resync_bad_bits >= (s->resync_len*s->resync_percent)/100)
+                if (s->rx.resync_bad_bits >= (s->rx.resync_len*s->rx.resync_percent)/100)
                 {
-                    s->resync = 1;
+                    s->rx.resync = 1;
                     s->results.resyncs++;
                     if (s->reporter)
                         s->reporter(s->user_data, BERT_REPORT_UNSYNCED, &s->results);
                 }
-                s->resync_cnt = s->resync_len;
-                s->resync_bad_bits = 0;
+                s->rx.resync_cnt = s->rx.resync_len;
+                s->rx.resync_bad_bits = 0;
             }
         }
-        s->rx_reg = (s->rx_reg >> 1) | (((s->rx_reg ^ (s->rx_reg >> s->shift)) & 1) << s->shift2);
+        s->rx.reg = (s->rx.reg >> 1) | (((s->rx.reg ^ (s->rx.reg >> s->shift)) & 1) << s->shift2);
         break;
     case 2:
-        s->rx_reg = (s->rx_reg >> 1) | (bit << 6);
+        s->rx.reg = (s->rx.reg >> 1) | (bit << 6);
         /* TODO: There is no mechanism for synching yet. This only works if things start in sync. */
-        if (++s->rx_step_bit == 7)
+        if (++s->rx.step_bit == 7)
         {
-            s->rx_step_bit = 0;
-            if ((int) s->rx_reg != qbf[s->rx_step])
+            s->rx.step_bit = 0;
+            if ((int) s->rx.reg != qbf[s->rx.step])
             {
                 /* We need to work out the number of actual bad bits here. We need to look at the
                    error rate, and see it a resync is needed. etc. */
                 s->results.bad_bits++;
             }
-            if (qbf[++s->rx_step] == '\0')
-                s->rx_step = 0;
+            if (qbf[++s->rx.step] == '\0')
+                s->rx.step = 0;
         }
         s->results.total_bits++;
         break;
     }
     if (s->report_frequency > 0)
     {
-        if (--s->report_countdown <= 0)
+        if (--s->rx.report_countdown <= 0)
         {
             if (s->reporter)
                 s->reporter(s->user_data, BERT_REPORT_REGULAR, &s->results);
-            s->report_countdown = s->report_frequency;
+            s->rx.report_countdown = s->report_frequency;
         }
     }
 }
@@ -339,7 +341,7 @@
     s->reporter = reporter;
     s->user_data = user_data;
     
-    s->report_countdown = s->report_frequency;
+    s->rx.report_countdown = s->report_frequency;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -366,47 +368,47 @@
     switch (s->pattern)
     {
     case BERT_PATTERN_ZEROS:
-        s->tx_reg = 0;
+        s->tx.reg = 0;
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_ONES:
-        s->tx_reg = ~((uint32_t) 0);
+        s->tx.reg = ~((uint32_t) 0);
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_7_TO_1:
-        s->tx_reg = 0xFEFEFEFE;
+        s->tx.reg = 0xFEFEFEFE;
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_3_TO_1:
-        s->tx_reg = 0xEEEEEEEE;
+        s->tx.reg = 0xEEEEEEEE;
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_1_TO_1:
-        s->tx_reg = 0xAAAAAAAA;
+        s->tx.reg = 0xAAAAAAAA;
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_1_TO_3:
-        s->tx_reg = 0x11111111;
+        s->tx.reg = 0x11111111;
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_1_TO_7:
-        s->tx_reg = 0x01010101;
+        s->tx.reg = 0x01010101;
         s->shift2 = 31;
         s->pattern_class = 0;
         break;
     case BERT_PATTERN_QBF:
-        s->tx_reg = 0;
+        s->tx.reg = 0;
         s->pattern_class = 2;
         break;
     case BERT_PATTERN_ITU_O151_23:
         s->pattern_class = 1;
-        s->tx_reg = 0x7FFFFF;
+        s->tx.reg = 0x7FFFFF;
         s->mask = 0x20;
         s->shift = 5;
         s->shift2 = 22;
@@ -416,7 +418,7 @@
         break;
     case BERT_PATTERN_ITU_O151_20:
         s->pattern_class = 1;
-        s->tx_reg = 0xFFFFF;
+        s->tx.reg = 0xFFFFF;
         s->mask = 0x8;
         s->shift = 3;
         s->shift2 = 19;
@@ -426,7 +428,7 @@
         break;
     case BERT_PATTERN_ITU_O151_15:
         s->pattern_class = 1;
-        s->tx_reg = 0x7FFF;
+        s->tx.reg = 0x7FFF;
         s->mask = 0x2;
         s->shift = 1;
         s->shift2 = 14;
@@ -436,7 +438,7 @@
         break;
     case BERT_PATTERN_ITU_O152_11:
         s->pattern_class = 1;
-        s->tx_reg = 0x7FF;
+        s->tx.reg = 0x7FF;
         s->mask = 0x4;
         s->shift = 2;
         s->shift2 = 10;
@@ -446,7 +448,7 @@
         break;
     case BERT_PATTERN_ITU_O153_9:
         s->pattern_class = 1;
-        s->tx_reg = 0x1FF;
+        s->tx.reg = 0x1FF;
         s->mask = 0x10;
         s->shift = 4;
         s->shift2 = 8;
@@ -455,28 +457,29 @@
         s->max_zeros = 0;
         break;
     }
-    s->tx_bits = 0;
-    s->tx_step = 0;
-    s->tx_step_bit = 0;
-    s->tx_zeros = 0;
-
-    s->rx_reg = s->tx_reg;
-    s->ref_reg = s->rx_reg;
-    s->master_reg = s->ref_reg;
-    s->rx_bits = 0;
-    s->rx_step = 0;
-    s->rx_step_bit = 0;
-
-    s->resync = 1;
-    s->resync_cnt = resync_len;
-    s->resync_bad_bits = 0;
-    s->resync_len = resync_len;
-    s->resync_percent = resync_percent;
+    s->tx.bits = 0;
+    s->tx.step = 0;
+    s->tx.step_bit = 0;
+    s->tx.zeros = 0;
+
+    s->rx.reg = s->tx.reg;
+    s->rx.ref_reg = s->rx.reg;
+    s->rx.master_reg = s->rx.ref_reg;
+    s->rx.bits = 0;
+    s->rx.step = 0;
+    s->rx.step_bit = 0;
+
+    s->rx.resync = 1;
+    s->rx.resync_cnt = resync_len;
+    s->rx.resync_bad_bits = 0;
+    s->rx.resync_len = resync_len;
+    s->rx.resync_percent = resync_percent;
+
     s->results.total_bits = 0;
     s->results.bad_bits = 0;
     s->results.resyncs = 0;
 
-    s->report_countdown = 0;
+    s->rx.report_countdown = 0;
 
     for (i = 0;  i < 8;  i++)
     {
@@ -485,7 +488,7 @@
         s->decade_ptr[i] = 0;
     }
     s->error_rate = 8;
-    s->step = 100;
+    s->rx.measurement_step = MEASUREMENT_STEP;
     
     span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
     span_log_set_protocol(&s->logging, "BERT");

Modified: freeswitch/trunk/libs/spandsp/src/dtmf.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/dtmf.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/dtmf.c	Mon Apr 20 13:33:33 2009
@@ -22,10 +22,10 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: dtmf.c,v 1.51 2009/02/10 13:06:46 steveu Exp $
+ * $Id: dtmf.c,v 1.53 2009/04/12 09:12:10 steveu Exp $
  */
  
-/*! \file dtmf.h */
+/*! \file */
 
 #if defined(HAVE_CONFIG_H)
 #include "config.h"

Modified: freeswitch/trunk/libs/spandsp/src/fax.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/fax.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/fax.c	Mon Apr 20 13:33:33 2009
@@ -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.88 2009/02/16 09:57:22 steveu Exp $
+ * $Id: fax.c,v 1.91 2009/04/12 03:29:58 steveu Exp $
  */
 
 /*! \file */
@@ -83,6 +83,7 @@
 #include "spandsp/fax.h"
 
 #include "spandsp/private/logging.h"
+#include "spandsp/private/silence_gen.h"
 #include "spandsp/private/fsk.h"
 #include "spandsp/private/v17tx.h"
 #include "spandsp/private/v17rx.h"
@@ -127,6 +128,27 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+static void set_rx_handler(fax_state_t *s, span_rx_handler_t *handler, void *user_data)
+{
+    s->modems.rx_handler = handler;
+    s->modems.rx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
+{
+    s->modems.tx_handler = handler;
+    s->modems.tx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
+{
+    s->modems.next_tx_handler = handler;
+    s->modems.next_tx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
 static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
 {
     fax_state_t *t;
@@ -140,8 +162,7 @@
         /* 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));
-        s->rx_handler = (span_rx_handler_t *) &v17_rx;
-        s->rx_user_data = &s->v17_rx;
+        set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
     }
     else
     {
@@ -151,8 +172,7 @@
             /* 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));
-            s->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            s->rx_user_data = &s->v21_rx;
+            set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
         }
     }
     return 0;
@@ -172,8 +192,7 @@
         /* 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));
-        s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
-        s->rx_user_data = &s->v27ter_rx;
+        set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
     }
     else
     {
@@ -183,8 +202,7 @@
             /* 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));
-            s->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            s->rx_user_data = &s->v21_rx;
+            set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
         }
     }
     return 0;
@@ -204,8 +222,7 @@
         /* 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));
-        s->rx_handler = (span_rx_handler_t *) &v29_rx;
-        s->rx_user_data = &s->v29_rx;
+        set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
     }
     else
     {
@@ -215,8 +232,7 @@
             /* 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));
-            s->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            s->rx_user_data = &s->v21_rx;
+            set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
         }
     }
     return 0;
@@ -239,6 +255,51 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len)
+{
+    /* To mitigate the effect of lost packets on a packet network we should
+       try to sustain the status quo. If there is no receive modem running, keep
+       things that way. If there is a receive modem running, try to sustain its
+       operation, without causing a phase hop, or letting its adaptive functions
+       diverge. */
+#if defined(LOG_FAX_AUDIO)
+    if (s->modems.audio_rx_log >= 0)
+    {
+        int i;
+#if defined(_MSC_VER)
+        int16_t *amp = (int16_t *) _alloca(sizeof(int16_t)*len);
+#else
+        int16_t amp[len];
+#endif
+
+        vec_zeroi16(amp, 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;
+    }
+    return len;
+}
+/*- End of function --------------------------------------------------------*/
+
 static int set_next_tx_type(fax_state_t *s)
 {
     fax_modems_state_t *t;
@@ -246,16 +307,14 @@
     t = &s->modems;
     if (t->next_tx_handler)
     {
-        t->tx_handler = t->next_tx_handler;
-        t->tx_user_data = t->next_tx_user_data;
+        set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
         t->next_tx_handler = NULL;
         return 0;
     }
     /* If there is nothing else to change to, so use zero length silence */
     silence_gen_alter(&t->silence_gen, 0);
-    t->tx_handler = (span_tx_handler_t *) &silence_gen;
-    t->tx_user_data = &t->silence_gen;
-    t->next_tx_handler = NULL;
+    set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+    set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
     t->transmit = FALSE;
     return -1;
 }
@@ -340,32 +399,27 @@
     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);
-        t->rx_handler = (span_rx_handler_t *) &fsk_rx;
-        t->rx_user_data = &t->v21_rx;
+        set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &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);
-        t->rx_handler = (span_rx_handler_t *) &v27ter_v21_rx;
-        t->rx_user_data = s;
+        set_rx_handler(s, &v27ter_v21_rx, 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);
-        t->rx_handler = (span_rx_handler_t *) &v29_v21_rx;
-        t->rx_user_data = s;
+        set_rx_handler(s, &v29_v21_rx, 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);
-        t->rx_handler = (span_rx_handler_t *) &v17_v21_rx;
-        t->rx_user_data = s;
+        set_rx_handler(s, &v17_v21_rx, s);
         break;
     case T30_MODEM_DONE:
         span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
     default:
-        t->rx_handler = (span_rx_handler_t *) &span_dummy_rx;
-        t->rx_user_data = s;
+        set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, s);
         break;
     }
 }
@@ -398,9 +452,8 @@
     {
     case T30_MODEM_PAUSE:
         silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
-        t->tx_handler = (span_tx_handler_t *) &silence_gen;
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = NULL;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         t->transmit = TRUE;
         break;
     case T30_MODEM_CED:
@@ -410,9 +463,8 @@
         else
             tone = MODEM_CONNECT_TONES_FAX_CNG;
         modem_connect_tones_tx_init(&t->connect_tx, tone);
-        t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
-        t->tx_user_data = &t->connect_tx;
-        t->next_tx_handler = NULL;
+        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);
         t->transmit = TRUE;
         break;
     case T30_MODEM_V21:
@@ -424,10 +476,8 @@
            a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
            a call, and ensures the receiving end is ready. */
         silence_gen_alter(&t->silence_gen, ms_to_samples(75));
-        t->tx_handler = (span_tx_handler_t *) &silence_gen;
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &fsk_tx;
-        t->next_tx_user_data = &t->v21_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
         t->transmit = TRUE;
         break;
     case T30_MODEM_V27TER:
@@ -436,10 +486,8 @@
         hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
         v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep);
         v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
-        t->tx_handler = (span_tx_handler_t *) &silence_gen;
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &v27ter_tx;
-        t->next_tx_user_data = &t->v27ter_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
         t->transmit = TRUE;
         break;
     case T30_MODEM_V29:
@@ -448,10 +496,8 @@
         hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
         v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep);
         v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
-        t->tx_handler = (span_tx_handler_t *) &silence_gen;
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &v29_tx;
-        t->next_tx_user_data = &t->v29_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
         t->transmit = TRUE;
         break;
     case T30_MODEM_V17:
@@ -460,10 +506,8 @@
         hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
         v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train);
         v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
-        t->tx_handler = (span_tx_handler_t *) &silence_gen;
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &v17_tx;
-        t->next_tx_user_data = &t->v17_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
         t->transmit = TRUE;
         break;
     case T30_MODEM_DONE:
@@ -471,9 +515,8 @@
         /* Fall through */
     default:
         silence_gen_alter(&t->silence_gen, 0);
-        t->tx_handler = (span_tx_handler_t *) &silence_gen;
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = NULL;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         t->transmit = FALSE;
         break;
     }

Modified: freeswitch/trunk/libs/spandsp/src/fax_modems.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/fax_modems.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/fax_modems.c	Mon Apr 20 13:33:33 2009
@@ -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.3 2009/02/21 04:27:46 steveu Exp $
+ * $Id: fax_modems.c,v 1.5 2009/04/12 03:29:58 steveu Exp $
  */
 
 /*! \file */
@@ -74,6 +74,7 @@
 #include "spandsp/fax_modems.h"
 
 #include "spandsp/private/logging.h"
+#include "spandsp/private/silence_gen.h"
 #include "spandsp/private/fsk.h"
 #include "spandsp/private/v17tx.h"
 #include "spandsp/private/v17rx.h"
@@ -106,6 +107,17 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len)
+{
+    fax_modems_state_t *s;
+
+    s = (fax_modems_state_t *) user_data;
+    v17_rx_fillin(&s->v17_rx, len);
+    fsk_rx_fillin(&s->v21_rx, len);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
 {
     fax_modems_state_t *s;
@@ -125,6 +137,17 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len)
+{
+    fax_modems_state_t *s;
+
+    s = (fax_modems_state_t *) user_data;
+    v27ter_rx_fillin(&s->v27ter_rx, len);
+    fsk_rx_fillin(&s->v21_rx, len);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len)
 {
     fax_modems_state_t *s;
@@ -144,6 +167,17 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len)
+{
+    fax_modems_state_t *s;
+
+    s = (fax_modems_state_t *) user_data;
+    v29_rx_fillin(&s->v29_rx, len);
+    fsk_rx_fillin(&s->v21_rx, len);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 static void v21_rx_status_handler(void *user_data, int status)
 {
     fax_modems_state_t *s;
@@ -200,7 +234,7 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(void) start_fax_modems_rx_modem(fax_modems_state_t *s, int which)
+SPAN_DECLARE(void) fax_modems_start_rx_modem(fax_modems_state_t *s, int which)
 {
     switch (which)
     {

Modified: freeswitch/trunk/libs/spandsp/src/fsk.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/fsk.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/fsk.c	Mon Apr 20 13:33:33 2009
@@ -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: fsk.c,v 1.52 2009/02/10 13:06:46 steveu Exp $
+ * $Id: fsk.c,v 1.58 2009/04/01 13:22:40 steveu Exp $
  */
 
 /*! \file */
@@ -111,12 +111,20 @@
         1200*100
     },
     {
-        "Weitbrecht",   /* Used for TDD (Telecoms Device for the Deaf) */
+        "Weitbrecht 45.45", /* Used for TDD (Telecoms Device for the Deaf) */
         1800,
         1400,
         -14,
         -30,
          4545
+    },
+    {
+        "Weitbrecht 50",    /* Used for TDD (Telecoms Device for the Deaf) */
+        1800,
+        1400,
+        -14,
+        -30,
+         5000
     }
 };
 
@@ -140,7 +148,6 @@
     s->scaling = dds_scaling_dbm0((float) spec->tx_level);
     /* Initialise fractional sample baud generation. */
     s->phase_acc = 0;
-    s->baud_inc = s->baud_rate;
     s->baud_frac = 0;
     s->current_phase_rate = s->phase_rates[1];
     
@@ -175,7 +182,7 @@
        with them, if they care about accurate transition timing. */
     for (sample = 0;  sample < len;  sample++)
     {
-        if ((s->baud_frac += s->baud_inc) >= SAMPLE_RATE*100)
+        if ((s->baud_frac += s->baud_rate) >= SAMPLE_RATE*100)
         {
             s->baud_frac -= SAMPLE_RATE*100;
             if ((bit = s->get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
@@ -245,7 +252,7 @@
 
 SPAN_DECLARE(fsk_rx_state_t *) fsk_rx_init(fsk_rx_state_t *s,
                                            const fsk_spec_t *spec,
-                                           int sync_mode,
+                                           int framing_mode,
                                            put_bit_func_t put_bit,
                                            void *user_data)
 {
@@ -259,7 +266,7 @@
 
     memset(s, 0, sizeof(*s));
     s->baud_rate = spec->baud_rate;
-    s->sync_mode = sync_mode;
+    s->framing_mode = framing_mode;
     fsk_rx_signal_cutoff(s, (float) spec->min_level);
     s->put_bit = put_bit;
     s->put_bit_user_data = user_data;
@@ -292,8 +299,10 @@
     }
 
     /* Initialise the baud/bit rate tracking. */
-    s->baud_inc = s->baud_rate;
-    s->baud_pll = 0;
+    s->baud_phase = 0;
+    s->frame_state = 0;
+    s->frame_bits = 0;
+    s->last_bit = 0;
     
     /* Initialise a power detector, so sense when a signal is present. */
     power_meter_init(&(s->power), 4);
@@ -340,6 +349,26 @@
 
     for (i = 0;  i < len;  i++)
     {
+        /* The *totally* asynchronous character to character behaviour of these
+           modems, when carrying async. data, seems to force a sample by sample
+           approach. */
+        for (j = 0;  j < 2;  j++)
+        {
+            s->dot[j].re -= s->window[j][buf_ptr].re;
+            s->dot[j].im -= s->window[j][buf_ptr].im;
+
+            ph = dds_complexi(&(s->phase_acc[j]), s->phase_rate[j]);
+            s->window[j][buf_ptr].re = (ph.re*amp[i]) >> s->scaling_shift;
+            s->window[j][buf_ptr].im = (ph.im*amp[i]) >> s->scaling_shift;
+
+            s->dot[j].re += s->window[j][buf_ptr].re;
+            s->dot[j].im += s->window[j][buf_ptr].im;
+
+            dot = s->dot[j].re >> 15;
+            sum[j] = dot*dot;
+            dot = s->dot[j].im >> 15;
+            sum[j] += dot*dot;
+        }
         /* If there isn't much signal, don't demodulate - it will only produce
            useless junk results. */
         /* There should be no DC in the signal, but sometimes there is.
@@ -358,6 +387,7 @@
                     /* Count down a short delay, to ensure we push the last
                        few bits through the filters before stopping. */
                     report_status_change(s, SIG_STATUS_CARRIER_DOWN);
+                    s->baud_phase = 0;
                     continue;
                 }
             }
@@ -366,66 +396,153 @@
         {
             /* Look for power exceeding turn-on threshold to turn the carrier on */
             if (power < s->carrier_on_power)
+            {
+                s->baud_phase = 0;
+                continue;
+            }
+            if (s->baud_phase < (s->correlation_span >> 1) - 30)
+            {
+                s->baud_phase++;
                 continue;
+            }
             s->signal_present = 1;
+            /* Initialise the baud/bit rate tracking. */
+            s->baud_phase = 0;
+            s->frame_state = 0;
+            s->frame_bits = 0;
+            s->last_bit = 0;
             report_status_change(s, SIG_STATUS_CARRIER_UP);
         }
         /* Non-coherent FSK demodulation by correlation with the target tones
            over a one baud interval. The slow V.xx specs. are too open ended
            to allow anything fancier to be used. The dot products are calculated
            using a sliding window approach, so the compute load is not that great. */
-        /* The *totally* asynchronous character to character behaviour of these
-           modems, when carrying async. data, seems to force a sample by sample
-           approach. */
-        for (j = 0;  j < 2;  j++)
-        {
-            s->dot[j].re -= s->window[j][buf_ptr].re;
-            s->dot[j].im -= s->window[j][buf_ptr].im;
-
-            ph = dds_complexi(&(s->phase_acc[j]), s->phase_rate[j]);
-            s->window[j][buf_ptr].re = (ph.re*amp[i]) >> s->scaling_shift;
-            s->window[j][buf_ptr].im = (ph.im*amp[i]) >> s->scaling_shift;
-
-            s->dot[j].re += s->window[j][buf_ptr].re;
-            s->dot[j].im += s->window[j][buf_ptr].im;
 
-            dot = s->dot[j].re >> 15;
-            sum[j] = dot*dot;
-            dot = s->dot[j].im >> 15;
-            sum[j] += dot*dot;
-        }
         baudstate = (sum[0] < sum[1]);
-
-        if (s->lastbit != baudstate)
+        switch (s->framing_mode)
         {
-            s->lastbit = baudstate;
-            if (s->sync_mode)
+        case 1:
+            /* Synchronous serial operation - e.g. for HDLC */
+            if (s->last_bit != baudstate)
             {
+                /* On a transition we check our timing */
+                s->last_bit = baudstate;
                 /* For synchronous use (e.g. HDLC channels in FAX modems), nudge
                    the baud phase gently, trying to keep it centred on the bauds. */
-                if (s->baud_pll < (SAMPLE_RATE*50))
-                    s->baud_pll += (s->baud_inc >> 3);
+                if (s->baud_phase < (SAMPLE_RATE*50))
+                    s->baud_phase += (s->baud_rate >> 3);
                 else
-                    s->baud_pll -= (s->baud_inc >> 3);
+                    s->baud_phase -= (s->baud_rate >> 3);
             }
-            else
+            if ((s->baud_phase += s->baud_rate) >= (SAMPLE_RATE*100))
             {
+                /* We should be in the middle of a baud now, so report the current
+                   state as the next bit */
+                s->baud_phase -= (SAMPLE_RATE*100);
+                s->put_bit(s->put_bit_user_data, baudstate);
+            }
+            break;
+        case 0:
+            /* Fully asynchronous mode */
+            if (s->last_bit != baudstate)
+            {
+                /* On a transition we check our timing */
+                s->last_bit = baudstate;
                 /* For async. operation, believe transitions completely, and
                    sample appropriately. This allows instant start on the first
                    transition. */
                 /* We must now be about half way to a sampling point. We do not do
                    any fractional sample estimation of the transitions, so this is
                    the most accurate baud alignment we can do. */
-                s->baud_pll = SAMPLE_RATE*50;
+                s->baud_phase = SAMPLE_RATE*50;
             }
-
-        }
-        if ((s->baud_pll += s->baud_inc) >= (SAMPLE_RATE*100))
-        {
-            /* We should be in the middle of a baud now, so report the current
-               state as the next bit */
-            s->baud_pll -= (SAMPLE_RATE*100);
-            s->put_bit(s->put_bit_user_data, baudstate);
+            if ((s->baud_phase += s->baud_rate) >= (SAMPLE_RATE*100))
+            {
+                /* We should be in the middle of a baud now, so report the current
+                   state as the next bit */
+                s->baud_phase -= (SAMPLE_RATE*100);
+                s->put_bit(s->put_bit_user_data, baudstate);
+            }
+            break;
+        default:
+            /* Gather the specified number of bits, with robust checking to ensure reasonable voice immunity.
+               The first bit should be a start bit (0), and the last bit should be a stop bit (1) */
+            if (s->frame_state == 0)
+            {
+                /* Looking for the start of a zero bit, which hopefully the start of a start bit */
+                if (baudstate == 0)
+                {
+                    s->baud_phase = SAMPLE_RATE*(100 - 40)/2;
+                    s->frame_state = -1;
+                    s->frame_bits = 0;
+                    s->last_bit = -1;
+                }
+            }
+            else if (s->frame_state == -1)
+            {
+                /* Look for a continuous zero from the start of the start bit until
+                   beyond the middle */
+                if (baudstate != 0)
+                {
+                    /* If we aren't looking at a stable start bit, restart */
+                    s->frame_state = 0;
+                }
+                else
+                {
+                    s->baud_phase += s->baud_rate;
+                    if (s->baud_phase >= SAMPLE_RATE*100)
+                    {
+                        s->frame_state = 1;
+                        s->last_bit = baudstate;
+                    }
+                }
+            }
+            else
+            {
+                s->baud_phase += s->baud_rate;
+                if (s->baud_phase >= SAMPLE_RATE*(100 - 40))
+                {
+                    if (s->last_bit < 0)
+                        s->last_bit = baudstate;
+                    /* Look for the bit being consistent over the central 20% of the bit time. */
+                    if (s->last_bit != baudstate)
+                    {
+                        s->frame_state = 0;
+                    }
+                    else if (s->baud_phase >= SAMPLE_RATE*100)
+                    {
+                        /* We should be in the middle of a baud now, so report the current
+                           state as the next bit */
+                        if (s->last_bit == baudstate)
+                        {
+                            s->frame_bits |= (baudstate << s->framing_mode);
+                            s->frame_bits >>= 1;
+                            s->baud_phase -= (SAMPLE_RATE*100);
+                            if (++s->frame_state > s->framing_mode)
+                            {
+                                /* Check we have a stop bit */
+                                if (baudstate == 1)
+                                {
+                                    /* Check we have a start bit */
+                                    if ((s->frame_bits & 1) == 0)
+                                    {
+                                        /* Drop the start bit, and pass the rest back */
+                                        s->frame_bits >>= 1;
+                                        s->put_bit(s->put_bit_user_data, s->frame_bits);
+                                    }
+                                }
+                                s->frame_state = 0;
+                            }
+                        }
+                        else
+                        {
+                            s->frame_state = 0;
+                        }
+                        s->last_bit = -1;
+                    }
+                }
+            }
+            break;
         }
         if (++buf_ptr >= s->correlation_span)
             buf_ptr = 0;
@@ -434,4 +551,14 @@
     return 0;
 }
 /*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) fsk_rx_fillin(fsk_rx_state_t *s, int len)
+{
+    /* The valid choice here is probably to do nothing. We don't change state
+      (i.e carrier on<->carrier off), and we'll just output less bits than we
+      should. */
+    /* TODO: Advance the symbol phase the appropriate amount */
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
 /*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/gsm0610_local.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/gsm0610_local.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/gsm0610_local.h	Mon Apr 20 13:33:33 2009
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_local.h,v 1.14 2009/03/07 16:47:30 steveu Exp $
+ * $Id: gsm0610_local.h,v 1.15 2009/03/13 15:57:29 steveu Exp $
  */
 
 #if !defined(_GSM0610_LOCAL_H_)
@@ -39,7 +39,7 @@
 
 static __inline__ int16_t gsm_add(int16_t a, int16_t b)
 {
-#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)
+#if defined(__GNUC__)  &&  (defined(__i386__)  ||  defined(__x86_64__))
     __asm__ __volatile__(
         " addw %2,%0;\n"
         " jno 0f;\n"
@@ -62,7 +62,7 @@
 
 static __inline__ int32_t gsm_l_add(int32_t a, int32_t b)
 {
-#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)
+#if defined(__GNUC__)  &&  (defined(__i386__)  ||  defined(__x86_64__))
     __asm__ __volatile__(
         " addl %2,%0;\n"
         " jno 0f;\n"
@@ -214,16 +214,6 @@
 
 extern int16_t gsm0610_norm(int32_t a);
 
-#if defined(__GNUC__)  &&  defined(__i386__)
-
-int32_t gsm0610_vec_iprod(const int16_t *p, const int16_t *q, int n);
-
-int32_t gsm0610_vec_maxmin(const int16_t *p, int n, int16_t *out);
-
-int32_t gsm0610_max_cross_corr(const int16_t *wt, const int16_t *dp, int16_t *Nc_out);
-
-#endif
-
 #endif
 
 /*- End of include ---------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/gsm0610_long_term.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/gsm0610_long_term.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/gsm0610_long_term.c	Mon Apr 20 13:33:33 2009
@@ -25,7 +25,7 @@
  * This code is based on the widely used GSM 06.10 code available from
  * http://kbs.cs.tu-berlin.de/~jutta/toast.html
  *
- * $Id: gsm0610_long_term.c,v 1.21 2009/02/03 16:28:39 steveu Exp $
+ * $Id: gsm0610_long_term.c,v 1.24 2009/04/20 16:36:36 steveu Exp $
  */
 
 /*! \file */
@@ -67,156 +67,174 @@
 
 /* 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION */
 
-#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)
-int32_t gsm0610_max_cross_corr(const int16_t *wt, const int16_t *dp, int16_t *Nc_out)
+static int32_t gsm0610_max_cross_corr(const int16_t *wt, const int16_t *dp, int16_t *index_out)
 {
-    int32_t lmax;
-    int32_t out;
+    int32_t max;
+    int32_t index;
+    int32_t res;
+    int i;
 
-#if defined(__x86_64__)
-    __asm__ __volatile__(
-        " emms;\n"
-        " pushq %%rbx;\n"
-        " movl $0,%%edx;\n"             /* Will be maximum inner-product */
-        " movl $40,%%ebx;\n"
-        " movl %%ebx,%%ecx;\n"          /* Will be index of max inner-product */
-        " subq $80,%%rsi;\n"
-        " .p2align 2;\n"
-        "1:\n"
-        " movq (%%rdi),%%mm0;\n"
-        " movq (%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm0;\n"
-        " movq 8(%%rdi),%%mm1;\n"
-        " movq 8(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 16(%%rdi),%%mm1;\n"
-        " movq 16(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 24(%%rdi),%%mm1;\n"
-        " movq 24(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 32(%%rdi),%%mm1;\n"
-        " movq 32(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 40(%%rdi),%%mm1;\n"
-        " movq 40(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 48(%%rdi),%%mm1;\n"
-        " movq 48(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 56(%%rdi),%%mm1;\n"
-        " movq 56(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 64(%%rdi),%%mm1;\n"
-        " movq 64(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 72(%%rdi),%%mm1;\n"
-        " movq 72(%%rsi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq %%mm0,%%mm1;\n"
-        " punpckhdq %%mm0,%%mm1;\n"        /* mm1 has high int32 of mm0 dup'd */
-        " paddd %%mm1,%%mm0;\n"
-        " movd %%mm0,%%eax;\n"                /* eax has result */
-        " cmpl %%edx,%%eax;\n"
-        " jle 2f;\n"
-        " movl %%eax,%%edx;\n"
-        " movl %%ebx,%%ecx;\n"
-        " .p2align 2;\n"
-        "2:\n"
-        " subq $2,%%rsi;\n"
-        " incl %%ebx;\n"
-        " cmpq $120,%%rbx;\n"
-        " jle 1b;\n"
-        " popq %%rbx;\n"
-        " emms;\n"
-        : "=d" (lmax), "=c" (out)
-        : "D" (wt), "S" (dp)
-        : "eax"
-    );
+    max = 0;
+    index = 40; /* index for the maximum cross-correlation */
+
+    for (i = 40;  i <= 120;  i++)
+    {
+#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)  &&  defined(__x86_64__)
+        __asm__ __volatile__(
+            " emms;\n"
+            " .p2align 2;\n"
+            " movq (%%rdi),%%mm0;\n"
+            " movq (%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm0;\n"
+            " movq 8(%%rdi),%%mm1;\n"
+            " movq 8(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 16(%%rdi),%%mm1;\n"
+            " movq 16(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 24(%%rdi),%%mm1;\n"
+            " movq 24(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 32(%%rdi),%%mm1;\n"
+            " movq 32(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 40(%%rdi),%%mm1;\n"
+            " movq 40(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 48(%%rdi),%%mm1;\n"
+            " movq 48(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 56(%%rdi),%%mm1;\n"
+            " movq 56(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 64(%%rdi),%%mm1;\n"
+            " movq 64(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 72(%%rdi),%%mm1;\n"
+            " movq 72(%%rsi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq %%mm0,%%mm1;\n"
+            " punpckhdq %%mm0,%%mm1;\n"         /* mm1 has high int32 of mm0 dup'd */
+            " paddd %%mm1,%%mm0;\n"
+            " movd %%mm0,%[res];\n"
+            " emms;\n"
+            : [res] "=r" (res)
+            : "D" (wt), "S" (&dp[-i])
+        );
+#elif defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)  &&  defined(__i386__)
+        __asm__ __volatile__(
+            " emms;\n"
+            " .p2align 2;\n"
+            " movq (%%edi),%%mm0;\n"
+            " movq (%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm0;\n"
+            " movq 8(%%edi),%%mm1;\n"
+            " movq 8(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 16(%%edi),%%mm1;\n"
+            " movq 16(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 24(%%edi),%%mm1;\n"
+            " movq 24(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 32(%%edi),%%mm1;\n"
+            " movq 32(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 40(%%edi),%%mm1;\n"
+            " movq 40(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 48(%%edi),%%mm1;\n"
+            " movq 48(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 56(%%edi),%%mm1;\n"
+            " movq 56(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 64(%%edi),%%mm1;\n"
+            " movq 64(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq 72(%%edi),%%mm1;\n"
+            " movq 72(%%esi),%%mm2;\n"
+            " pmaddwd %%mm2,%%mm1;\n"
+            " paddd %%mm1,%%mm0;\n"
+            " movq %%mm0,%%mm1;\n"
+            " punpckhdq %%mm0,%%mm1;\n"         /* mm1 has high int32 of mm0 dup'd */
+            " paddd %%mm1,%%mm0;\n"
+            " movd %%mm0,%[res];\n"
+            " emms;\n"
+            : [res] "=r" (res)
+            : "D" (wt), "S" (&dp[-i])
+        );
 #else
-    __asm__ __volatile__(
-        " emms;\n"
-        " pushl %%ebx;\n"
-        " movl $0,%%edx;\n"             /* Will be maximum inner-product */
-        " movl $40,%%ebx;\n"
-        " movl %%ebx,%%ecx;\n"          /* Will be index of max inner-product */
-        " subl $80,%%esi;\n"
-        " .p2align 2;\n"
-        "1:\n"
-        " movq (%%edi),%%mm0;\n"
-        " movq (%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm0;\n"
-        " movq 8(%%edi),%%mm1;\n"
-        " movq 8(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 16(%%edi),%%mm1;\n"
-        " movq 16(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 24(%%edi),%%mm1;\n"
-        " movq 24(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 32(%%edi),%%mm1;\n"
-        " movq 32(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 40(%%edi),%%mm1;\n"
-        " movq 40(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 48(%%edi),%%mm1;\n"
-        " movq 48(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 56(%%edi),%%mm1;\n"
-        " movq 56(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 64(%%edi),%%mm1;\n"
-        " movq 64(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq 72(%%edi),%%mm1;\n"
-        " movq 72(%%esi),%%mm2;\n"
-        " pmaddwd %%mm2,%%mm1;\n"
-        " paddd %%mm1,%%mm0;\n"
-        " movq %%mm0,%%mm1;\n"
-        " punpckhdq %%mm0,%%mm1;\n"        /* mm1 has high int32 of mm0 dup'd */
-        " paddd %%mm1,%%mm0;\n"
-        " movd %%mm0,%%eax;\n"                /* eax has result */
-        " cmpl %%edx,%%eax;\n"
-        " jle 2f;\n"
-        " movl %%eax,%%edx;\n"
-        " movl %%ebx,%%ecx;\n"
-        " .p2align 2;\n"
-        "2:\n"
-        " subl $2,%%esi;\n"
-        " incl %%ebx;\n"
-        " cmpl $120,%%ebx;\n"
-        " jle 1b;\n"
-        " popl %%ebx;\n"
-        " emms;\n"
-        : "=d" (lmax), "=c" (out)
-        : "D" (wt), "S" (dp)
-        : "eax"
-    );
+        res  = (wt[0]*dp[0 - i])
+             + (wt[1]*dp[1 - i])
+             + (wt[2]*dp[2 - i])
+             + (wt[3]*dp[3 - i])
+             + (wt[4]*dp[4 - i])
+             + (wt[5]*dp[5 - i])
+             + (wt[6]*dp[6 - i])
+             + (wt[7]*dp[7 - i])
+             + (wt[8]*dp[8 - i])
+             + (wt[9]*dp[9 - i])
+             + (wt[10]*dp[10 - i])
+             + (wt[11]*dp[11 - i])
+             + (wt[12]*dp[12 - i])
+             + (wt[13]*dp[13 - i])
+             + (wt[14]*dp[14 - i])
+             + (wt[15]*dp[15 - i])
+             + (wt[16]*dp[16 - i])
+             + (wt[17]*dp[17 - i])
+             + (wt[18]*dp[18 - i])
+             + (wt[19]*dp[19 - i])
+             + (wt[20]*dp[20 - i])
+             + (wt[21]*dp[21 - i])
+             + (wt[22]*dp[22 - i])
+             + (wt[23]*dp[23 - i])
+             + (wt[24]*dp[24 - i])
+             + (wt[25]*dp[25 - i])
+             + (wt[26]*dp[26 - i])
+             + (wt[27]*dp[27 - i])
+             + (wt[28]*dp[28 - i])
+             + (wt[29]*dp[29 - i])
+             + (wt[30]*dp[30 - i])
+             + (wt[31]*dp[31 - i])
+             + (wt[32]*dp[32 - i])
+             + (wt[33]*dp[33 - i])
+             + (wt[34]*dp[34 - i])
+             + (wt[35]*dp[35 - i])
+             + (wt[36]*dp[36 - i])
+             + (wt[37]*dp[37 - i])
+             + (wt[38]*dp[38 - i])
+             + (wt[39]*dp[39 - i]);
 #endif
-    *Nc_out = out;
-    return  lmax;
+        if (res > max)
+        {
+            max = res;
+            index = i;
+        }
+        /*endif*/
+    }
+    /*endfor*/
+    *index_out = index;
+    return max;
 }
 /*- End of function --------------------------------------------------------*/
-#endif
 
 /* This procedure computes the LTP gain (bc) and the LTP lag (Nc)
    for the long term analysis filter.   This is done by calculating a
@@ -237,7 +255,6 @@
                                        int16_t *Nc_out)
 {
     int k;
-    int16_t Nc;
     int16_t bc;
     int16_t wt[40];
     int32_t L_max;
@@ -248,9 +265,6 @@
     int16_t scale;
     int16_t temp;
     int32_t L_temp;
-#if !(defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX))
-    int16_t lambda;
-#endif
 
     /* Search of the optimum scaling of d[0..39]. */
     dmax = 0;
@@ -288,81 +302,20 @@
     /*endfor*/
 
     /* Search for the maximum cross-correlation and coding of the LTP lag */
-#if defined(__GNUC__)  &&  defined(SPANDSP_USE_MMX)
-    L_max = gsm0610_max_cross_corr(wt, dp, &Nc);
-#else
-    L_max = 0;
-    Nc = 40; /* index for the maximum cross-correlation */
-
-    for (lambda = 40;  lambda <= 120;  lambda++)
-    {
-        int32_t L_result;
-
-        L_result  = (wt[0]*dp[0 - lambda])
-                  + (wt[1]*dp[1 - lambda])
-                  + (wt[2]*dp[2 - lambda])
-                  + (wt[3]*dp[3 - lambda])
-                  + (wt[4]*dp[4 - lambda])
-                  + (wt[5]*dp[5 - lambda])
-                  + (wt[6]*dp[6 - lambda])
-                  + (wt[7]*dp[7 - lambda])
-                  + (wt[8]*dp[8 - lambda])
-                  + (wt[9]*dp[9 - lambda])
-                  + (wt[10]*dp[10 - lambda])
-                  + (wt[11]*dp[11 - lambda])
-                  + (wt[12]*dp[12 - lambda])
-                  + (wt[13]*dp[13 - lambda])
-                  + (wt[14]*dp[14 - lambda])
-                  + (wt[15]*dp[15 - lambda])
-                  + (wt[16]*dp[16 - lambda])
-                  + (wt[17]*dp[17 - lambda])
-                  + (wt[18]*dp[18 - lambda])
-                  + (wt[19]*dp[19 - lambda])
-                  + (wt[20]*dp[20 - lambda])
-                  + (wt[21]*dp[21 - lambda])
-                  + (wt[22]*dp[22 - lambda])
-                  + (wt[23]*dp[23 - lambda])
-                  + (wt[24]*dp[24 - lambda])
-                  + (wt[25]*dp[25 - lambda])
-                  + (wt[26]*dp[26 - lambda])
-                  + (wt[27]*dp[27 - lambda])
-                  + (wt[28]*dp[28 - lambda])
-                  + (wt[29]*dp[29 - lambda])
-                  + (wt[30]*dp[30 - lambda])
-                  + (wt[31]*dp[31 - lambda])
-                  + (wt[32]*dp[32 - lambda])
-                  + (wt[33]*dp[33 - lambda])
-                  + (wt[34]*dp[34 - lambda])
-                  + (wt[35]*dp[35 - lambda])
-                  + (wt[36]*dp[36 - lambda])
-                  + (wt[37]*dp[37 - lambda])
-                  + (wt[38]*dp[38 - lambda])
-                  + (wt[39]*dp[39 - lambda]);
-
-        if (L_result > L_max)
-        {
-            Nc = lambda;
-            L_max = L_result;
-        }
-        /*endif*/
-    }
-    /*endfor*/
-#endif
-    *Nc_out = Nc;
-
+    L_max = gsm0610_max_cross_corr(wt, dp, Nc_out);
     L_max <<= 1;
 
     /* Rescaling of L_max */
     assert(scale <= 100  &&  scale >=  -100);
     L_max = L_max >> (6 - scale);
 
-    assert(Nc <= 120  &&  Nc >= 40);
+    assert(*Nc_out <= 120  &&  *Nc_out >= 40);
 
     /* Compute the power of the reconstructed short term residual signal dp[..] */
     L_power = 0;
     for (k = 0;  k < 40;  k++)
     {
-        L_temp = dp[k - Nc] >> 3;
+        L_temp = dp[k - *Nc_out] >> 3;
         L_power += L_temp*L_temp;
     }
     /*endfor*/
@@ -453,7 +406,7 @@
     int16_t drpp;
     int16_t Nr;
 
-    /* This procedure uses the bcr and Ncr parameter to realize the
+    /* This procedure uses the bcr and Ncr parameters to realize the
        long term synthesis filter.  The decoding of bcr needs
        table 4.3b. */
 

Modified: freeswitch/trunk/libs/spandsp/src/ima_adpcm.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/ima_adpcm.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/ima_adpcm.c	Mon Apr 20 13:33:33 2009
@@ -23,7 +23,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: ima_adpcm.c,v 1.35 2009/02/10 13:06:46 steveu Exp $
+ * $Id: ima_adpcm.c,v 1.36 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -115,6 +115,7 @@
    to indicate a partially filled last octet.
 */
 
+/*! The number of ADPCM step sizes */
 #define STEP_MAX 88
 
 /* Intel ADPCM step variation table */
@@ -277,7 +278,9 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-SPAN_DECLARE(ima_adpcm_state_t *) ima_adpcm_init(ima_adpcm_state_t *s, int variant, int chunk_size)
+SPAN_DECLARE(ima_adpcm_state_t *) ima_adpcm_init(ima_adpcm_state_t *s,
+                                                 int variant,
+                                                 int chunk_size)
 {
     if (s == NULL)
     {

Modified: freeswitch/trunk/libs/spandsp/src/libspandsp.2005.vcproj
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/libspandsp.2005.vcproj	(original)
+++ freeswitch/trunk/libs/spandsp/src/libspandsp.2005.vcproj	Mon Apr 20 13:33:33 2009
@@ -158,6 +158,7 @@
 <File RelativePath="tone_generate.c"></File>
 <File RelativePath="v17rx.c"></File>
 <File RelativePath="v17tx.c"></File>
+<File RelativePath="v18.c"></File>
 <File RelativePath="v22bis_rx.c"></File>
 <File RelativePath="v22bis_tx.c"></File>
 <File RelativePath="v27ter_rx.c"></File>
@@ -236,6 +237,7 @@
 <File RelativePath="spandsp/tone_generate.h"></File>
 <File RelativePath="spandsp/v17rx.h"></File>
 <File RelativePath="spandsp/v17tx.h"></File>
+<File RelativePath="spandsp/v18.h"></File>
 <File RelativePath="spandsp/v22bis.h"></File>
 <File RelativePath="spandsp/v27ter_rx.h"></File>
 <File RelativePath="spandsp/v27ter_tx.h"></File>
@@ -272,6 +274,7 @@
 <File RelativePath="spandsp/private/queue.h"></File>
 <File RelativePath="spandsp/private/schedule.h"></File>
 <File RelativePath="spandsp/private/sig_tone.h"></File>
+<File RelativePath="spandsp/private/silence_gen.h"></File>
 <File RelativePath="spandsp/private/super_tone_rx.h"></File>
 <File RelativePath="spandsp/private/super_tone_tx.h"></File>
 <File RelativePath="spandsp/private/t30.h"></File>
@@ -286,6 +289,7 @@
 <File RelativePath="spandsp/private/tone_generate.h"></File>
 <File RelativePath="spandsp/private/v17rx.h"></File>
 <File RelativePath="spandsp/private/v17tx.h"></File>
+<File RelativePath="spandsp/private/v18.h"></File>
 <File RelativePath="spandsp/private/v22bis.h"></File>
 <File RelativePath="spandsp/private/v27ter_rx.h"></File>
 <File RelativePath="spandsp/private/v27ter_tx.h"></File>

Modified: freeswitch/trunk/libs/spandsp/src/libspandsp.2008.vcproj
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/libspandsp.2008.vcproj	(original)
+++ freeswitch/trunk/libs/spandsp/src/libspandsp.2008.vcproj	Mon Apr 20 13:33:33 2009
@@ -228,6 +228,7 @@
 <File RelativePath="tone_generate.c"></File>
 <File RelativePath="v17rx.c"></File>
 <File RelativePath="v17tx.c"></File>
+<File RelativePath="v18.c"></File>
 <File RelativePath="v22bis_rx.c"></File>
 <File RelativePath="v22bis_tx.c"></File>
 <File RelativePath="v27ter_rx.c"></File>
@@ -306,6 +307,7 @@
 <File RelativePath="spandsp/tone_generate.h"></File>
 <File RelativePath="spandsp/v17rx.h"></File>
 <File RelativePath="spandsp/v17tx.h"></File>
+<File RelativePath="spandsp/v18.h"></File>
 <File RelativePath="spandsp/v22bis.h"></File>
 <File RelativePath="spandsp/v27ter_rx.h"></File>
 <File RelativePath="spandsp/v27ter_tx.h"></File>
@@ -342,6 +344,7 @@
 <File RelativePath="spandsp/private/queue.h"></File>
 <File RelativePath="spandsp/private/schedule.h"></File>
 <File RelativePath="spandsp/private/sig_tone.h"></File>
+<File RelativePath="spandsp/private/silence_gen.h"></File>
 <File RelativePath="spandsp/private/super_tone_rx.h"></File>
 <File RelativePath="spandsp/private/super_tone_tx.h"></File>
 <File RelativePath="spandsp/private/t30.h"></File>
@@ -356,6 +359,7 @@
 <File RelativePath="spandsp/private/tone_generate.h"></File>
 <File RelativePath="spandsp/private/v17rx.h"></File>
 <File RelativePath="spandsp/private/v17tx.h"></File>
+<File RelativePath="spandsp/private/v18.h"></File>
 <File RelativePath="spandsp/private/v22bis.h"></File>
 <File RelativePath="spandsp/private/v27ter_rx.h"></File>
 <File RelativePath="spandsp/private/v27ter_tx.h"></File>

Modified: freeswitch/trunk/libs/spandsp/src/libspandsp.dsp
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/libspandsp.dsp	(original)
+++ freeswitch/trunk/libs/spandsp/src/libspandsp.dsp	Mon Apr 20 13:33:33 2009
@@ -357,6 +357,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\v18.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\v22bis_rx.c
 # End Source File
 # Begin Source File
@@ -667,6 +671,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\spandsp/v18.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\spandsp/v22bis.h
 # End Source File
 # Begin Source File
@@ -811,6 +819,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\spandsp/private/silence_gen.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\spandsp/private/super_tone_rx.h
 # End Source File
 # Begin Source File
@@ -867,6 +879,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\spandsp/private/v18.h
+# End Source File
+# Begin Source File
+
 SOURCE=.\spandsp/private/v22bis.h
 # End Source File
 # Begin Source File

Modified: freeswitch/trunk/libs/spandsp/src/msvc/spandsp.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/msvc/spandsp.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/msvc/spandsp.h	Mon Apr 20 13:33:33 2009
@@ -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.17 2009/02/12 12:38:39 steveu Exp $
+ * $Id: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $
  */
 
 /*! \file */
@@ -95,6 +95,7 @@
 #include <spandsp/v27ter_rx.h>
 #include <spandsp/v27ter_tx.h>
 #include <spandsp/v8.h>
+#include <spandsp/v18.h>
 #include <spandsp/v42.h>
 #include <spandsp/v42bis.h>
 #include <spandsp/t4.h>

Modified: freeswitch/trunk/libs/spandsp/src/queue.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/queue.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/queue.c	Mon Apr 20 13:33:33 2009
@@ -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: queue.c,v 1.29 2009/02/10 13:06:46 steveu Exp $
+ * $Id: queue.c,v 1.31 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -176,7 +176,7 @@
             memcpy(buf, s->data + optr, real_len);
         /*endif*/
         new_optr = optr + real_len;
-        if (new_optr > s->len)
+        if (new_optr >= s->len)
             new_optr = 0;
         /*endif*/
     }
@@ -250,7 +250,7 @@
         /* A one step process */
         memcpy(s->data + iptr, buf, real_len);
         new_iptr = iptr + real_len;
-        if (new_iptr > s->len)
+        if (new_iptr >= s->len)
             new_iptr = 0;
         /*endif*/
     }
@@ -365,7 +365,7 @@
         memcpy(s->data + iptr, &lenx, sizeof(uint16_t));
         memcpy(s->data + iptr + sizeof(uint16_t), buf, len);
         new_iptr = iptr + real_len;
-        if (new_iptr > s->len)
+        if (new_iptr >= s->len)
             new_iptr = 0;
         /*endif*/
     }

Modified: freeswitch/trunk/libs/spandsp/src/sig_tone.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/sig_tone.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/sig_tone.c	Mon Apr 20 13:33:33 2009
@@ -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.31 2009/02/10 13:06:46 steveu Exp $
+ * $Id: sig_tone.c,v 1.32 2009/04/12 14:18:02 steveu Exp $
  */
 
 /*! \file */
@@ -56,6 +56,7 @@
 
 #include "spandsp/private/sig_tone.h"
 
+/*! PI */
 #define PI 3.14159265358979323
 
 /* The coefficients for the data notch filter. This filter is also the

Modified: freeswitch/trunk/libs/spandsp/src/silence_gen.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/silence_gen.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/silence_gen.c	Mon Apr 20 13:33:33 2009
@@ -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.20 2009/02/10 13:06:46 steveu Exp $
+ * $Id: silence_gen.c,v 1.21 2009/04/12 03:29:58 steveu Exp $
  */
 
 /*! \file */
@@ -51,6 +51,8 @@
 #include "spandsp/async.h"
 #include "spandsp/silence_gen.h"
 
+#include "spandsp/private/silence_gen.h"
+
 SPAN_DECLARE(int) silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len)
 {
     if (s->remaining_samples != INT_MAX)

Modified: freeswitch/trunk/libs/spandsp/src/spandsp.h.in
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp.h.in	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp.h.in	Mon Apr 20 13:33:33 2009
@@ -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.17 2009/02/12 12:38:39 steveu Exp $
+ * $Id: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $
  */
 
 /*! \file */
@@ -92,6 +92,7 @@
 #include <spandsp/v27ter_rx.h>
 #include <spandsp/v27ter_tx.h>
 #include <spandsp/v8.h>
+#include <spandsp/v18.h>
 #include <spandsp/v42.h>
 #include <spandsp/v42bis.h>
 #include <spandsp/t4.h>

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/adsi.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/adsi.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/adsi.h	Mon Apr 20 13:33:33 2009
@@ -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: adsi.h,v 1.37 2009/03/04 12:15:15 steveu Exp $
+ * $Id: adsi.h,v 1.39 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -354,9 +354,11 @@
     JCLIP_ABSENCE =                     0x04
 };
 
-/*! Definitions for CLIP-DTMF and its variants */
+/* Definitions for CLIP-DTMF and its variants */
 
+/*! Caller number is '#' terminated DTMF. */
 #define CLIP_DTMF_HASH_TERMINATED       '#'
+/*! Caller number is 'C' terminated DTMF. */
 #define CLIP_DTMF_C_TERMINATED          'C'
 
 /*! Caller number */
@@ -398,10 +400,21 @@
     \param user_data An opaque pointer for the callback routine.
     \return A pointer to the initialised context, or NULL if there was a problem.
 */
-SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s, int standard, put_msg_func_t put_msg, void *user_data);
+SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s,
+                                             int standard,
+                                             put_msg_func_t put_msg,
+                                             void *user_data);
 
+/*! \brief Release an ADSI receive context.
+    \param s The ADSI receive context.
+    \return 0 for OK.
+*/
 SPAN_DECLARE(int) adsi_rx_release(adsi_rx_state_t *s);
 
+/*! \brief Free the resources of an ADSI receive context.
+    \param s The ADSI receive context.
+    \return 0 for OK.
+*/
 SPAN_DECLARE(int) adsi_rx_free(adsi_rx_state_t *s);
 
 /*! \brief Receive a chunk of ADSI audio.
@@ -410,7 +423,7 @@
     \param len The number of samples in the buffer.
     \return The number of samples unprocessed.
 */
-SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t *amp, int len);
+SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len);
 
 /*! \brief Initialise an ADSI transmit context.
     \param s The ADSI transmit context.
@@ -419,8 +432,16 @@
 */
 SPAN_DECLARE(adsi_tx_state_t *) adsi_tx_init(adsi_tx_state_t *s, int standard);
 
+/*! \brief Release an ADSI transmit context.
+    \param s The ADSI transmit context.
+    \return 0 for OK.
+*/
 SPAN_DECLARE(int) adsi_tx_release(adsi_tx_state_t *s);
 
+/*! \brief Free the resources of an ADSI transmit context.
+    \param s The ADSI transmit context.
+    \return 0 for OK.
+*/
 SPAN_DECLARE(int) adsi_tx_free(adsi_tx_state_t *s);
 
 /*! \brief Adjust the preamble associated with an ADSI transmit context.
@@ -442,7 +463,7 @@
     \param max_len The number of samples to be generated.
     \return The number of samples actually generated.
 */
-SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t *amp, int max_len);
+SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len);
 
 /*! \brief Request generation of an ADSI alert tone.
     \param s The ADSI transmit context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/expose.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/expose.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/expose.h	Mon Apr 20 13:33:33 2009
@@ -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.11 2008/11/30 13:44:35 steveu Exp $
+ * $Id: expose.h,v 1.12 2009/04/12 03:29:58 steveu Exp $
  */
 
 /*! \file */
@@ -55,6 +55,7 @@
 #include <spandsp/private/time_scale.h>
 #include <spandsp/private/super_tone_tx.h>
 #include <spandsp/private/super_tone_rx.h>
+#include <spandsp/private/silence_gen.h>
 #include <spandsp/private/async.h>
 #include <spandsp/private/fsk.h>
 #include <spandsp/private/v29rx.h>

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/fast_convert.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/fast_convert.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/fast_convert.h	Mon Apr 20 13:33:33 2009
@@ -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.6 2009/02/26 16:08:51 steveu Exp $
+ * $Id: fast_convert.h,v 1.7 2009/04/18 03:18:41 steveu Exp $
  */
 
 #if !defined(_SPANDSP_FAST_CONVERT_H_)
@@ -229,6 +229,17 @@
 
         return res[1];
     }
+#else
+    /* Fallback routines, for unrecognised platforms */
+    static __inline__ long int lfastrint(double x)
+    {
+        return (long int) x;
+    }
+
+    static __inline__ long int lfastrintf(float x)
+    {
+        return (long int) x;
+    }
 #endif
 
 #elif defined(_M_IX86)

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/fax.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/fax.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/fax.h	Mon Apr 20 13:33:33 2009
@@ -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.h,v 1.38 2009/02/03 16:28:41 steveu Exp $
+ * $Id: fax.h,v 1.39 2009/03/13 12:59:26 steveu Exp $
  */
 
 /*! \file */
@@ -54,6 +54,16 @@
 */
 SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len);
 
+/*! Apply fake T.30 receive processing when a block of audio samples is missing (e.g due
+    to packet loss).
+    \brief Apply fake T.30 receive processing.
+    \param s The FAX context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed. This should only be non-zero if
+            the software has reached the end of the FAX call.
+*/
+SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len);
+
 /*! Apply T.30 transmit processing to generate a block of audio samples.
     \brief Apply T.30 transmit processing to generate a block of audio samples.
     \param s The FAX context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/fsk.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/fsk.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/fsk.h	Mon Apr 20 13:33:33 2009
@@ -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: fsk.h,v 1.36 2009/02/10 13:06:47 steveu Exp $
+ * $Id: fsk.h,v 1.39 2009/04/01 13:22:40 steveu Exp $
  */
 
 /*! \file */
@@ -111,7 +111,8 @@
     FSK_BELL103CH1,
     FSK_BELL103CH2,
     FSK_BELL202,
-    FSK_WEITBRECHT      /* Used for TDD (Telecom Device for the Deaf) */
+    FSK_WEITBRECHT,     /* 45.45 baud version, used for TDD (Telecom Device for the Deaf) */
+    FSK_WEITBRECHT50    /* 50 baud version, used for TDD (Telecom Device for the Deaf) */
 };
 
 SPAN_DECLARE_DATA extern const fsk_spec_t preset_fsk_specs[];
@@ -191,13 +192,14 @@
     \brief Initialise an FSK modem receive context.
     \param s The modem context.
     \param spec The specification of the modem tones and rate.
-    \param sync_mode TRUE for synchronous modem. FALSE for asynchronous mode.
+    \param framing_mode 0 for fully asynchronous mode. 1 for synchronous mode. >1 for
+           this many bits per asynchronous character frame.
     \param put_bit The callback routine used to put the received data.
     \param user_data An opaque pointer.
     \return A pointer to the modem context, or NULL if there was a problem. */
 SPAN_DECLARE(fsk_rx_state_t *) fsk_rx_init(fsk_rx_state_t *s,
                                            const fsk_spec_t *spec,
-                                           int sync_mode,
+                                           int framing_mode,
                                            put_bit_func_t put_bit,
                                            void *user_data);
 
@@ -214,6 +216,15 @@
 */
 SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len);
 
+/*! Fake processing of a missing block of received FSK modem audio samples
+    (e.g due to packet loss).
+    \brief Fake processing of a missing block of received FSK modem audio samples.
+    \param s The modem context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed.
+*/
+SPAN_DECLARE(int) fsk_rx_fillin(fsk_rx_state_t *s, int len);
+
 SPAN_DECLARE(void) fsk_rx_set_put_bit(fsk_rx_state_t *s, put_bit_func_t put_bit, void *user_data);
 
 /*! Change the modem status report function associated with an FSK modem receive context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/g711.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/g711.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/g711.h	Mon Apr 20 13:33:33 2009
@@ -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: g711.h,v 1.18 2009/02/10 13:06:47 steveu Exp $
+ * $Id: g711.h,v 1.19 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -53,7 +53,9 @@
 #define _SPANDSP_G711_H_
 
 /* The usual values to use on idle channels, to emulate silence */
+/*! Idle value for A-law channels */
 #define G711_ALAW_IDLE_OCTET        0x5D
+/*! Idle value for u-law channels */
 #define G711_ULAW_IDLE_OCTET        0xFF
 
 enum
@@ -62,6 +64,9 @@
     G711_ULAW
 };
 
+/*!
+    G.711 state
+ */
 typedef struct g711_state_s g711_state_t;
 
 #if defined(__cplusplus)
@@ -106,8 +111,10 @@
  * John Wiley & Sons, pps 98-111 and 472-476.
  */
 
-//#define ULAW_ZEROTRAP                 /* turn on the trap as per the MIL-STD */
-#define ULAW_BIAS        0x84           /* Bias for linear code. */
+/* Enable the trap as per the MIL-STD */
+//#define ULAW_ZEROTRAP
+/*! Bias for u-law encoding from linear. */
+#define ULAW_BIAS        0x84
 
 /*! \brief Encode a linear sample to u-law
     \param linear The sample to encode.
@@ -187,6 +194,7 @@
  * John Wiley & Sons, pps 98-111 and 472-476.
  */
 
+/*! The A-law alternate mark inversion mask */
 #define ALAW_AMI_MASK       0x55
 
 /*! \brief Encode a linear sample to A-law
@@ -259,16 +267,37 @@
 */
 SPAN_DECLARE(uint8_t) ulaw_to_alaw(uint8_t ulaw);
 
+/*! \brief Decode from u-law or A-law to linear.
+    \param s The G.711 context.
+    \param amp The linear audio buffer.
+    \param g711_data The G.711 data.
+    \param g711_bytes The number of G.711 samples to decode.
+    \return The number of samples of linear audio produced.
+*/
 SPAN_DECLARE(int) g711_decode(g711_state_t *s,
                               int16_t amp[],
                               const uint8_t g711_data[],
                               int g711_bytes);
 
+/*! \brief Encode from linear to u-law or A-law.
+    \param s The G.711 context.
+    \param g711_data The G.711 data.
+    \param amp The linear audio buffer.
+    \param len The number of samples to encode.
+    \return The number of G.711 samples produced.
+*/
 SPAN_DECLARE(int) g711_encode(g711_state_t *s,
                               uint8_t g711_data[],
                               const int16_t amp[],
                               int len);
 
+/*! \brief Transcode between u-law and A-law.
+    \param s The G.711 context.
+    \param g711_out The resulting G.711 data.
+    \param g711_in The original G.711 data.
+    \param g711_bytes The number of G.711 samples to transcode.
+    \return The number of G.711 samples produced.
+*/
 SPAN_DECLARE(int) g711_transcode(g711_state_t *s,
                                  uint8_t g711_out[],
                                  const uint8_t g711_in[],

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/g722.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/g722.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/g722.h	Mon Apr 20 13:33:33 2009
@@ -28,7 +28,7 @@
  * Computer Science, Speech Group
  * Chengxiang Lu and Alex Hauptmann
  *
- * $Id: g722.h,v 1.25 2009/02/10 13:06:47 steveu Exp $
+ * $Id: g722.h,v 1.26 2009/04/12 09:12:10 steveu Exp $
  */
 
 
@@ -56,8 +56,14 @@
     G722_PACKED = 0x0002
 };
 
+/*!
+    G.722 encode state
+ */
 typedef struct g722_encode_state_s g722_encode_state_t;
 
+/*!
+    G.722 decode state
+ */
 typedef struct g722_decode_state_s g722_decode_state_t;
 
 #if defined(__cplusplus)
@@ -73,8 +79,14 @@
     \return A pointer to the G.722 encode context, or NULL for error. */
 SPAN_DECLARE(g722_encode_state_t *) g722_encode_init(g722_encode_state_t *s, int rate, int options);
 
+/*! Release a G.722 encode context.
+    \param s The G.722 encode context.
+    \return 0 for OK. */
 SPAN_DECLARE(int) g722_encode_release(g722_encode_state_t *s);
 
+/*! Free a G.722 encode context.
+    \param s The G.722 encode context.
+    \return 0 for OK. */
 SPAN_DECLARE(int) g722_encode_free(g722_encode_state_t *s);
 
 /*! Encode a buffer of linear PCM data to G.722
@@ -93,8 +105,14 @@
     \return A pointer to the G.722 decode context, or NULL for error. */
 SPAN_DECLARE(g722_decode_state_t *) g722_decode_init(g722_decode_state_t *s, int rate, int options);
 
+/*! Release a G.722 decode context.
+    \param s The G.722 decode context.
+    \return 0 for OK. */
 SPAN_DECLARE(int) g722_decode_release(g722_decode_state_t *s);
 
+/*! Free a G.722 decode context.
+    \param s The G.722 decode context.
+    \return 0 for OK. */
 SPAN_DECLARE(int) g722_decode_free(g722_decode_state_t *s);
 
 /*! Decode a buffer of G.722 data to linear PCM.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/g726.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/g726.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/g726.h	Mon Apr 20 13:33:33 2009
@@ -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: g726.h,v 1.25 2009/02/10 13:06:47 steveu Exp $
+ * $Id: g726.h,v 1.26 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -59,6 +59,9 @@
     G726_PACKING_RIGHT = 2
 };
 
+/*!
+    G.726 state
+ */
 typedef struct g726_state_s g726_state_t;
 
 typedef int16_t (*g726_decoder_func_t)(g726_state_t *s, uint8_t code);

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/ima_adpcm.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/ima_adpcm.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/ima_adpcm.h	Mon Apr 20 13:33:33 2009
@@ -26,7 +26,7 @@
  * Based on a bit from here, a bit from there, eye of toad,
  * ear of bat, etc - plus, of course, my own 2 cents.
  *
- * $Id: ima_adpcm.h,v 1.24 2009/02/10 13:06:47 steveu Exp $
+ * $Id: ima_adpcm.h,v 1.25 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -67,8 +67,8 @@
 #endif
 
 /*! Initialise an IMA ADPCM encode or decode context.
-    \param s The IMA ADPCM context
-    \param variant ???
+    \param s The IMA ADPCM context.
+    \param variant IMA_ADPCM_IMA4, IMA_ADPCM_DVI4, or IMA_ADPCM_VDVI.
     \param chunk_size The size of a chunk, in samples. A chunk size of
            zero sample samples means treat each encode or decode operation
            as a chunk.
@@ -101,8 +101,8 @@
 /*! Decode a buffer of IMA ADPCM data to linear PCM.
     \param s The IMA ADPCM context.
     \param amp The audio sample buffer.
-    \param ima_data
-    \param ima_bytes
+    \param ima_data The IMA ADPCM data
+    \param ima_bytes The number of bytes of IMA ADPCM data
     \return The number of samples returned. */
 SPAN_DECLARE(int) ima_adpcm_decode(ima_adpcm_state_t *s,
                                    int16_t amp[],

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/lpc10.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/lpc10.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/lpc10.h	Mon Apr 20 13:33:33 2009
@@ -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: lpc10.h,v 1.21 2009/02/10 13:06:47 steveu Exp $
+ * $Id: lpc10.h,v 1.22 2009/04/11 18:11:19 steveu Exp $
  */
 
 #if !defined(_SPANDSP_LPC10_H_)
@@ -48,8 +48,11 @@
 */
 typedef struct
 {
+    /*! Pitch */
     int32_t ipitch;
+    /*! Energy */
     int32_t irms;
+    /*! Reflection coefficients */
     int32_t irc[10];
 } lpc10_frame_t;
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/adsi.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/adsi.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/adsi.h	Mon Apr 20 13:33:33 2009
@@ -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: adsi.h,v 1.1 2008/10/13 13:14:01 steveu Exp $
+ * $Id: adsi.h,v 1.4 2009/04/12 04:20:01 steveu Exp $
  */
 
 /*! \file */
@@ -36,27 +36,45 @@
  */
 struct adsi_tx_state_s
 {
+    /*! */
     int standard;
 
+    /*! */
     tone_gen_descriptor_t alert_tone_desc;
+    /*! */
     tone_gen_state_t alert_tone_gen;
+    /*! */
     fsk_tx_state_t fsktx;
+    /*! */
     dtmf_tx_state_t dtmftx;
+    /*! */
     async_tx_state_t asynctx;
-    
+
+    /*! */
     int tx_signal_on;
-    
+
+    /*! */
     int byte_no;
+    /*! */
     int bit_pos;
+    /*! */
     int bit_no;
+    /*! */
     uint8_t msg[256];
+    /*! */
     int msg_len;
+    /*! */
     int preamble_len;
+    /*! */
     int preamble_ones_len;
+    /*! */
     int postamble_ones_len;
+    /*! */
     int stop_bits;
+    /*! */
     int baudot_shift;
     
+    /*! */
     logging_state_t logging;
 };
 
@@ -66,24 +84,35 @@
  */
 struct adsi_rx_state_s
 {
+    /*! */
     int standard;
+    /*! */
     put_msg_func_t put_msg;
+    /*! */
     void *user_data;
 
+    /*! */
     fsk_rx_state_t fskrx;
+    /*! */
     dtmf_rx_state_t dtmfrx;
-    async_rx_state_t asyncrx;
-    
+
+    /*! */
     int consecutive_ones;
+    /*! */
     int bit_pos;
+    /*! */
     int in_progress;
+    /*! */
     uint8_t msg[256];
+    /*! */
     int msg_len;
+    /*! */
     int baudot_shift;
     
     /*! A count of the framing errors. */
     int framing_errors;
 
+    /*! */
     logging_state_t logging;
 };
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/bert.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/bert.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/bert.h	Mon Apr 20 13:33:33 2009
@@ -22,12 +22,39 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: bert.h,v 1.1 2008/11/30 12:38:27 steveu Exp $
+ * $Id: bert.h,v 1.2 2009/04/14 16:04:54 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_BERT_H_)
 #define _SPANDSP_PRIVATE_BERT_H_
 
+typedef struct
+{
+    uint32_t reg;
+    int step;
+    int step_bit;
+    int bits;
+    int zeros;
+} bert_tx_state_t;
+
+typedef struct
+{
+    uint32_t reg;
+    uint32_t ref_reg;
+    uint32_t master_reg;
+    int step;
+    int step_bit;
+    int resync;
+    int bits;
+    int zeros;
+    int resync_len;
+    int resync_percent;
+    int resync_bad_bits;
+    int resync_cnt;
+    int report_countdown;
+    int measurement_step;
+} bert_rx_state_t;
+
 /*!
     Bit error rate tester (BERT) descriptor. This defines the working state for a
     single instance of the BERT.
@@ -41,25 +68,6 @@
     int report_frequency;
     int limit;
 
-    uint32_t tx_reg;
-    int tx_step;
-    int tx_step_bit;
-    int tx_bits;
-    int tx_zeros;
-
-    uint32_t rx_reg;
-    uint32_t ref_reg;
-    uint32_t master_reg;
-    int rx_step;
-    int rx_step_bit;
-    int resync;
-    int rx_bits;
-    int rx_zeros;
-    int resync_len;
-    int resync_percent;
-    int resync_bad_bits;
-    int resync_cnt;
-    
     uint32_t mask;
     int shift;
     int shift2;
@@ -69,11 +77,10 @@
 
     int decade_ptr[9];
     int decade_bad[9][10];
-    int step;
     int error_rate;
 
-    int bit_error_status;
-    int report_countdown;
+    bert_tx_state_t tx;
+    bert_rx_state_t rx;
 
     bert_results_t results;
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/fax_modems.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/fax_modems.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/fax_modems.h	Mon Apr 20 13:33:33 2009
@@ -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.2 2009/02/14 15:21:14 steveu Exp $
+ * $Id: fax_modems.h,v 1.3 2009/03/23 14:17:42 steveu Exp $
  */
 
 /*! \file */
@@ -97,6 +97,10 @@
     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;
+
     /*! The current transmit signal handler */
     span_tx_handler_t *tx_handler;
     void *tx_user_data;

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/fsk.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/fsk.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/fsk.h	Mon Apr 20 13:33:33 2009
@@ -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: fsk.h,v 1.2 2009/01/29 18:30:14 steveu Exp $
+ * $Id: fsk.h,v 1.5 2009/04/01 13:22:40 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_FSK_H_)
@@ -50,7 +50,6 @@
     int32_t current_phase_rate;
     uint32_t phase_acc;
     int baud_frac;
-    int baud_inc;
     int shutdown;
 };
 
@@ -61,7 +60,8 @@
 struct fsk_rx_state_s
 {
     int baud_rate;
-    int sync_mode;
+    /*! \brief Synchronous/asynchronous framing control */
+    int framing_mode;
     /*! \brief The callback function used to put each bit received. */
     put_bit_func_t put_bit;
     /*! \brief A user specified opaque pointer passed to the put_bit routine. */
@@ -89,9 +89,10 @@
     complexi32_t dot[2];
     int buf_ptr;
 
-    int baud_inc;
-    int baud_pll;
-    int lastbit;
+    int frame_state;
+    int frame_bits;
+    int baud_phase;
+    int last_bit;
     int scaling_shift;
 };
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/g711.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/g711.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/g711.h	Mon Apr 20 13:33:33 2009
@@ -22,12 +22,15 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: g711.h,v 1.1 2008/11/30 10:17:31 steveu Exp $
+ * $Id: g711.h,v 1.2 2009/04/12 09:12:11 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_G711_H_)
 #define _SPANDSP_PRIVATE_G711_H_
 
+/*!
+    G.711 state
+ */
 struct g711_state_s
 {
     /*! One of the G.711_xxx options */

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/g722.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/g722.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/g722.h	Mon Apr 20 13:33:33 2009
@@ -28,7 +28,7 @@
  * Computer Science, Speech Group
  * Chengxiang Lu and Alex Hauptmann
  *
- * $Id: g722.h,v 1.1 2008/10/13 13:14:01 steveu Exp $
+ * $Id: g722.h,v 1.2 2009/04/12 09:12:11 steveu Exp $
  */
 
 
@@ -51,6 +51,9 @@
     int16_t d[7];
 } g722_band_t;
 
+/*!
+    G.722 encode state
+ */
 struct g722_encode_state_s
 {
     /*! TRUE if the operating in the special ITU test mode, with the band split filters
@@ -76,6 +79,9 @@
     int out_bits;
 };
 
+/*!
+    G.722 decode state
+ */
 struct g722_decode_state_s
 {
     /*! TRUE if the operating in the special ITU test mode, with the band split filters

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/g726.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/g726.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/g726.h	Mon Apr 20 13:33:33 2009
@@ -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: g726.h,v 1.3 2009/01/29 18:30:14 steveu Exp $
+ * $Id: g726.h,v 1.4 2009/04/12 09:12:11 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_G726_H_)
@@ -33,7 +33,7 @@
  * used by the G.726 encoder and decoder to preserve their internal
  * state between successive calls.  The meanings of the majority
  * of the state structure fields are explained in detail in the
- * CCITT Recommendation G.726.  The field names are essentially indentical
+ * ITU Recommendation G.726.  The field names are essentially indentical
  * to variable names in the bit level description of the coding algorithm
  * included in this recommendation.
  */

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/lpc10.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/lpc10.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/lpc10.h	Mon Apr 20 13:33:33 2009
@@ -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: lpc10.h,v 1.1 2008/11/30 05:43:37 steveu Exp $
+ * $Id: lpc10.h,v 1.3 2009/04/12 09:12:11 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_LPC10_H_)
@@ -34,62 +34,107 @@
 */
 struct lpc10_encode_state_s
 {
+    /*! \brief ??? */
     int error_correction;
 
     /* State used only by function high_pass_100hz */
+    /*! \brief ??? */
     float z11;
+    /*! \brief ??? */
     float z21;
+    /*! \brief ??? */
     float z12;
+    /*! \brief ??? */
     float z22;
     
     /* State used by function lpc10_analyse */
+    /*! \brief ??? */
     float inbuf[LPC10_SAMPLES_PER_FRAME*3];
+    /*! \brief ??? */
     float pebuf[LPC10_SAMPLES_PER_FRAME*3];
+    /*! \brief ??? */
     float lpbuf[696];
+    /*! \brief ??? */
     float ivbuf[312];
+    /*! \brief ??? */
     float bias;
-    int32_t osbuf[10];      /* No initial value necessary */
-    int32_t osptr;          /* Initial value 1 */
+    /*! \brief No initial value necessary */
+    int32_t osbuf[10];
+    /*! \brief Initial value 1 */
+    int32_t osptr;
+    /*! \brief ??? */
     int32_t obound[3];
-    int32_t vwin[3][2];     /* Initial value vwin[2][0] = 307; vwin[2][1] = 462; */
-    int32_t awin[3][2];     /* Initial value awin[2][0] = 307; awin[2][1] = 462; */
+    /*! \brief Initial value vwin[2][0] = 307; vwin[2][1] = 462; */
+    int32_t vwin[3][2];
+    /*! \brief Initial value awin[2][0] = 307; awin[2][1] = 462; */
+    int32_t awin[3][2];
+    /*! \brief ??? */
     int32_t voibuf[4][2];
+    /*! \brief ??? */
     float rmsbuf[3];
+    /*! \brief ??? */
     float rcbuf[3][10];
+    /*! \brief ??? */
     float zpre;
 
     /* State used by function onset */
+    /*! \brief ??? */
     float n;
-    float d__;          /* Initial value 1.0f */
-    float fpc;          /* No initial value necessary */
+    /*! \brief Initial value 1.0f */
+    float d__;
+    /*! \brief No initial value necessary */
+    float fpc;
+    /*! \brief ??? */
     float l2buf[16];
+    /*! \brief ??? */
     float l2sum1;
-    int32_t l2ptr1;     /* Initial value 1 */
-    int32_t l2ptr2;     /* Initial value 9 */
-    int32_t lasti;      /* No initial value necessary */
-    int hyst;           /* Initial value FALSE */
+    /*! \brief Initial value 1 */
+    int32_t l2ptr1;
+    /*! \brief Initial value 9 */
+    int32_t l2ptr2;
+    /*! \brief No initial value necessary */
+    int32_t lasti;
+    /*! \brief Initial value FALSE */
+    int hyst;
 
     /* State used by function lpc10_voicing */
-    float dither;       /* Initial value 20.0f */
+    /*! \brief Initial value 20.0f */
+    float dither;
+    /*! \brief ??? */
     float snr;
+    /*! \brief ??? */
     float maxmin;
-    float voice[3][2];  /* Initial value is probably unnecessary */
+    /*! \brief Initial value is probably unnecessary */
+    float voice[3][2];
+    /*! \brief ??? */
     int32_t lbve;
+    /*! \brief ??? */
     int32_t lbue;
+    /*! \brief ??? */
     int32_t fbve;
+    /*! \brief ??? */
     int32_t fbue;
+    /*! \brief ??? */
     int32_t ofbue;
+    /*! \brief ??? */
     int32_t sfbue;
+    /*! \brief ??? */
     int32_t olbue;
+    /*! \brief ??? */
     int32_t slbue;
 
     /* State used by function dynamic_pitch_tracking */
+    /*! \brief ??? */
     float s[60];
+    /*! \brief ??? */
     int32_t p[2][60];
+    /*! \brief ??? */
     int32_t ipoint;
+    /*! \brief ??? */
     float alphax;
 
     /* State used by function lpc10_pack */
+    /*! \brief ??? */
     int32_t isync;
 };
 
@@ -99,46 +144,75 @@
 */
 struct lpc10_decode_state_s
 {
+    /*! \brief ??? */
     int error_correction;
 
     /* State used by function decode */
-    int32_t iptold;     /* Initial value 60 */
-    int first;          /* Initial value TRUE */
+    /*! \brief Initial value 60 */
+    int32_t iptold;
+    /*! \brief Initial value TRUE */
+    int first;
+    /*! \brief ??? */
     int32_t ivp2h;
+    /*! \brief ??? */
     int32_t iovoic;
-    int32_t iavgp;      /* Initial value 60 */
+    /*! \brief Initial value 60. */
+    int32_t iavgp;
+    /*! \brief ??? */
     int32_t erate;
+    /*! \brief ??? */
     int32_t drc[10][3];
+    /*! \brief ??? */
     int32_t dpit[3];
+    /*! \brief ??? */
     int32_t drms[3];
 
     /* State used by function synths */
+    /*! \brief ??? */
     float buf[LPC10_SAMPLES_PER_FRAME*2];
-    int32_t buflen;     /* Initial value LPC10_SAMPLES_PER_FRAME */
+    /*! \brief Initial value LPC10_SAMPLES_PER_FRAME */
+    int32_t buflen;
 
     /* State used by function pitsyn */
-    int32_t ivoico;     /* No initial value necessary as long as first_pitsyn is initially TRUE_ */
-    int32_t ipito;      /* No initial value necessary as long as first_pitsyn is initially TRUE_ */
-    float rmso;         /* Initial value 1.0f */
-    float rco[10];      /* No initial value necessary as long as first_pitsyn is initially TRUE_ */
-    int32_t jsamp;      /* Nno initial value necessary as long as first_pitsyn is initially TRUE_ */
-    int first_pitsyn;   /* Initial value TRUE */
+    /*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
+    int32_t ivoico;
+    /*! \brief  No initial value necessary as long as first_pitsyn is initially TRUE */
+    int32_t ipito;
+    /*! \brief Initial value 1.0f */
+    float rmso;
+    /*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
+    float rco[10];
+    /*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
+    int32_t jsamp;
+    /*! \brief Initial value TRUE */
+    int first_pitsyn;
 
     /* State used by function bsynz */
+    /*! \brief ??? */
     int32_t ipo;
+    /*! \brief ??? */
     float exc[166];
+    /*! \brief ??? */
     float exc2[166];
+    /*! \brief ??? */
     float lpi[3];
+    /*! \brief ??? */
     float hpi[3];
+    /*! \brief ??? */
     float rmso_bsynz;
 
     /* State used by function random */
+    /*! \brief ??? */
     int32_t j;
+    /*! \brief ??? */
     int32_t k;
+    /*! \brief ??? */
     int16_t y[5];
 
     /* State used by function deemp */
+    /*! \brief ??? */
     float dei[2];
+    /*! \brief ??? */
     float deo[3];
 };
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/sig_tone.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/sig_tone.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/sig_tone.h	Mon Apr 20 13:33:33 2009
@@ -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.2 2009/01/30 07:19:25 steveu Exp $
+ * $Id: sig_tone.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_SIG_TONE_H_)
@@ -53,6 +53,7 @@
     /*! \brief Parameters to control the behaviour of the notch filter, used
                to remove the tone from the voice path in some protocols. */
     int notch_lag_time;
+    /*! \brief TRUE if the notch may be used in the media flow. */
     int notch_allowed;
 
     /*! \brief The tone on persistence check, in audio samples. */
@@ -60,6 +61,7 @@
     /*! \brief The tone off persistence check, in audio samples. */
     int tone_off_check_time;
 
+    /*! \brief ??? */
     int tones;
     /*! \brief The coefficients for the cascaded bi-quads notch filter. */
     struct
@@ -79,17 +81,22 @@
     } tone[2];
 
 
-    /*! \brief Flat mode bandpass bi-quad parameters */
 #if defined(SPANDSP_USE_FIXED_POINT)
+    /*! \brief Flat mode bandpass bi-quad parameters */
     int32_t broad_a[3];
+    /*! \brief Flat mode bandpass bi-quad parameters */
     int32_t broad_b[3];
+    /*! \brief Post filter scaling */
     int broad_postscale;
 #else
+    /*! \brief Flat mode bandpass bi-quad parameters */
     float broad_a[3];
+    /*! \brief Flat mode bandpass bi-quad parameters */
     float broad_b[3];
 #endif
     /*! \brief The coefficients for the post notch leaky integrator. */
     int32_t notch_slugi;
+    /*! \brief ??? */
     int32_t notch_slugp;
 
     /*! \brief The coefficients for the post modulus leaky integrator in the
@@ -97,20 +104,27 @@
                detection ratio. This is called the guard ratio in some
                protocols. */
     int32_t unfiltered_slugi;
+    /*! \brief ??? */
     int32_t unfiltered_slugp;
 
     /*! \brief The coefficients for the post modulus leaky integrator in the
                bandpass filter data path. */
     int32_t broad_slugi;
+    /*! \brief ??? */
     int32_t broad_slugp;
 
     /*! \brief Masks which effectively threshold the notched, weighted and
                bandpassed data. */
     int32_t notch_threshold;
+    /*! \brief ??? */
     int32_t unfiltered_threshold;
+    /*! \brief ??? */
     int32_t broad_threshold;
 };
 
+/*!
+    Signaling tone transmit state
+ */
 struct sig_tone_tx_state_s
 {
     /*! \brief The callback function used to handle signaling changes. */
@@ -118,6 +132,7 @@
     /*! \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 */
@@ -130,11 +145,17 @@
     /*! The phase accumulators for the one or two tones */
     uint32_t phase_acc[2];
 
+    /*! \brief Current transmit tone */
     int current_tx_tone;
+    /*! \brief Current transmit timeout */
     int current_tx_timeout;
+    /*! \brief Time in current signaling state, in samples. */
     int signaling_state_duration;
 };
 
+/*!
+    Signaling tone receive state
+ */
 struct sig_tone_rx_state_s
 {
     /*! \brief The callback function used to handle signaling changes. */
@@ -142,19 +163,25 @@
     /*! \brief A user specified opaque pointer passed to the callback function. */
     void *user_data;
 
+    /*! \brief Tone descriptor */
     sig_tone_descriptor_t *desc;
 
+    /*! \brief The current receive tone */
     int current_rx_tone;
+    /*! \brief The timeout for switching from the high level to low level tone detector. */
     int high_low_timer;
 
     struct
     {
-        /*! \brief The z's for the notch filter */
 #if defined(SPANDSP_USE_FIXED_POINT)
+        /*! \brief The z's for the notch filter */
         int32_t notch_z1[3];
+        /*! \brief The z's for the notch filter */
         int32_t notch_z2[3];
 #else
+        /*! \brief The z's for the notch filter */
         float notch_z1[3];
+        /*! \brief The z's for the notch filter */
         float notch_z2[3];
 #endif
 
@@ -162,22 +189,30 @@
         int32_t notch_zl;
     } tone[2];
 
-    /*! \brief The z's for the weighting/bandpass filter. */
 #if defined(SPANDSP_USE_FIXED_POINT)
+    /*! \brief The z's for the weighting/bandpass filter. */
     int32_t broad_z[3];
 #else
+    /*! \brief The z's for the weighting/bandpass filter. */
     float broad_z[3];
 #endif
     /*! \brief The z for the broadband integrator. */
     int32_t broad_zl;
 
+    /*! \brief ??? */
     int flat_mode;
+    /*! \brief ??? */
     int tone_present;
+    /*! \brief ??? */
     int notch_enabled;
+    /*! \brief ??? */
     int flat_mode_timeout;
+    /*! \brief ??? */
     int notch_insertion_timeout;
+    /*! \brief ??? */
     int tone_persistence_timeout;
     
+    /*! \brief ??? */
     int signaling_state_duration;
 };
 

Added: freeswitch/trunk/libs/spandsp/src/spandsp/private/silence_gen.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/silence_gen.h	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,43 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * private/silence_gen.c - A silence generator, for inserting timed silences.
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2006 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: silence_gen.h,v 1.1 2009/04/12 03:29:58 steveu Exp $
+ */
+
+#if !defined(_SPANDSP_PRIVATE_SILENCE_GEN_H_)
+#define _SPANDSP_PRIVATE_SILENCE_GEN_H_
+
+struct silence_gen_state_s
+{
+    /*! \brief The callback function used to report status changes. */
+    modem_tx_status_func_t status_handler;
+    /*! \brief A user specified opaque pointer passed to the status function. */
+    void *status_user_data;
+
+    int remaining_samples;
+    int total_samples;
+};
+
+#endif
+/*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/t30.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/t30.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/t30.h	Mon Apr 20 13:33:33 2009
@@ -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.3 2009/01/29 18:30:14 steveu Exp $
+ * $Id: t30.h,v 1.4 2009/04/12 14:18:02 steveu Exp $
  */
 
 /*! \file */
@@ -41,6 +41,7 @@
     /*! \brief T.4 context for reading or writing image data. */
     t4_state_t t4;
     
+    /*! \brief The type of FAX operation currently in progress */
     int operation_in_progress;
 
     /*! \brief TRUE if behaving as the calling party */
@@ -235,8 +236,10 @@
     /*! \brief TRUE if we are at the end of an ECM page to se sent - i.e. there are no more
         partial pages still to come. */
     int ecm_at_page_end;
+
+    /*! \brief The transmission step queued to follow the one in progress. */
     int next_tx_step;
-    /* The FCF for the next receive step */
+    /*! \brief The FCF for the next receive step. */
     uint8_t next_rx_step;
     /*! \brief Image file name for image reception. */
     char rx_file[256];
@@ -248,6 +251,7 @@
     int tx_start_page;
     /*! \brief The last page to be sent from the image file. -1 means no restriction. */
     int tx_stop_page;
+    /*! \brief The current completion status. */
     int current_status;
     /*! \brief Internet Aware FAX mode bit mask. */
     int iaf;

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_core.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_core.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_core.h	Mon Apr 20 13:33:33 2009
@@ -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_core.h,v 1.2 2009/01/19 17:14:10 steveu Exp $
+ * $Id: t38_core.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_T38_CORE_H_)
@@ -33,18 +33,18 @@
 */
 struct t38_core_state_s
 {
-    /*! Handler routine to transmit IFP packets generated by the T.38 protocol engine */
+    /*! \brief Handler routine to transmit IFP packets generated by the T.38 protocol engine */
     t38_tx_packet_handler_t *tx_packet_handler;
-    /*! An opaque pointer passed to tx_packet_handler */
+    /*! \brief An opaque pointer passed to tx_packet_handler */
     void *tx_packet_user_data;
 
-    /*! Handler routine to process received indicator packets */
+    /*! \brief Handler routine to process received indicator packets */
     t38_rx_indicator_handler_t *rx_indicator_handler;
-    /*! Handler routine to process received data packets */
+    /*! \brief Handler routine to process received data packets */
     t38_rx_data_handler_t *rx_data_handler;
-    /*! Handler routine to process the missing packet condition */
+    /*! \brief Handler routine to process the missing packet condition */
     t38_rx_missing_handler_t *rx_missing_handler;
-    /*! An opaque pointer passed to any of the above receive handling routines */
+    /*! \brief An opaque pointer passed to any of the above receive handling routines */
     void *rx_user_data;
 
     /*! NOTE - Bandwidth reduction shall only be done on suitable Phase C data, i.e., MH, MR
@@ -52,49 +52,49 @@
         transport such as that provided by TCP. When transcoding is selected, it shall be
         applied to every suitable page in a call. */
 
-    /*! Method 1: Local generation of TCF (required for use with TCP).
-        Method 2: Transfer of TCF is required for use with UDP (UDPTL or RTP).
-        Method 2 is not recommended for use with TCP. */
+    /*! \brief Method 1: Local generation of TCF (required for use with TCP).
+               Method 2: Transfer of TCF is required for use with UDP (UDPTL or RTP).
+               Method 2 is not recommended for use with TCP. */
     int data_rate_management_method;
     
-    /*! The emitting gateway may indicate a preference for either UDP/UDPTL, or
-        UDP/RTP, or TCP for transport of T.38 IFP Packets. The receiving device
-        selects the transport protocol. */
+    /*! \brief The emitting gateway may indicate a preference for either UDP/UDPTL, or
+               UDP/RTP, or TCP for transport of T.38 IFP Packets. The receiving device
+               selects the transport protocol. */
     int data_transport_protocol;
 
-    /*! Indicates the capability to remove and insert fill bits in Phase C, non-ECM
+    /*! \brief Indicates the capability to remove and insert fill bits in Phase C, non-ECM
         data to reduce bandwidth in the packet network. */
     int fill_bit_removal;
 
-    /*! Indicates the ability to convert to/from MMR from/to the line format to
+    /*! \brief Indicates the ability to convert to/from MMR from/to the line format to
         improve the compression of the data, and reduce the bandwidth, in the
         packet network. */
     int mmr_transcoding;
 
-    /*! Indicates the ability to convert to/from JBIG to reduce bandwidth. */
+    /*! \brief Indicates the ability to convert to/from JBIG to reduce bandwidth. */
     int jbig_transcoding;
 
-    /*! For UDP (UDPTL or RTP) modes, this option indicates the maximum
-        number of octets that can be stored on the remote device before an overflow
-        condition occurs. It is the responsibility of the transmitting application to
-        limit the transfer rate to prevent an overflow. The negotiated data rate
-        should be used to determine the rate at which data is being removed from
-        the buffer. */
+    /*! \brief For UDP (UDPTL or RTP) modes, this option indicates the maximum
+               number of octets that can be stored on the remote device before an
+               overflow condition occurs. It is the responsibility of the transmitting
+               application to limit the transfer rate to prevent an overflow. The
+               negotiated data rate should be used to determine the rate at which
+               data is being removed from the buffer. */
     int max_buffer_size;
 
-    /*! This option indicates the maximum size of a UDPTL packet or the
-        maximum size of the payload within an RTP packet that can be accepted by
-        the remote device. */
+    /*! \brief This option indicates the maximum size of a UDPTL packet or the
+               maximum size of the payload within an RTP packet that can be accepted 
+               by the remote device. */
     int max_datagram_size;
 
-    /*! This is the version number of ITU-T Rec. T.38. New versions shall be
-        compatible with previous versions. */
+    /*! \brief This is the version number of ITU-T Rec. T.38. New versions shall be
+               compatible with previous versions. */
     int t38_version;
 
-    /*! Allow time for TEP playout */
+    /*! \brief Allow time for TEP playout */
     int allow_for_tep;
 
-    /*! The fastest data rate supported by the T.38 channel. */
+    /*! \brief The fastest data rate supported by the T.38 channel. */
     int fastest_image_data_rate;
 
     /*! \brief The number of times an indicator packet will be sent. Numbers greater than one
@@ -111,30 +111,31 @@
                greater than one will increase reliability for UDP transmission. Zero is not valid. */
     int data_end_tx_count;
 
-    /*! TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT
-        over TCP they are not relevent. */
+    /*! \brief TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT
+               over TCP they are not relevent. */
     int check_sequence_numbers;
 
-    /*! The sequence number for the next packet to be transmitted */
+    /*! \brief The sequence number for the next packet to be transmitted */
     int tx_seq_no;
-    /*! The sequence number expected in the next received packet */
+    /*! \brief The sequence number expected in the next received packet */
     int rx_expected_seq_no;
 
-    /*! The current receive indicator - i.e. the last indicator received */
+    /*! \brief The current receive indicator - i.e. the last indicator received */
     int current_rx_indicator;
-    /*! The current receive data type - i.e. the last data type received */
+    /*! \brief The current receive data type - i.e. the last data type received */
     int current_rx_data_type;
-    /*! The current receive field type - i.e. the last field_type received */
+    /*! \brief The current receive field type - i.e. the last field_type received */
     int current_rx_field_type;
-    /*! The current transmit indicator - i.e. the last indicator transmitted */
+    /*! \brief The current transmit indicator - i.e. the last indicator transmitted */
     int current_tx_indicator;
-    /*! The bit rate for V.34 operation */
+    /*! \brief The bit rate for V.34 operation */
     int v34_rate;
 
     /*! A count of missing receive packets. This count might not be accurate if the
         received packet numbers jump wildly. */
     int missing_packets;
 
+    /*! \brief Error and flow logging control */
     logging_state_t logging;
 };
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_gateway.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_gateway.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/t38_gateway.h	Mon Apr 20 13:33:33 2009
@@ -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_gateway.h,v 1.1 2008/10/13 13:14:01 steveu Exp $
+ * $Id: t38_gateway.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
  */
 
 /*! \file */
@@ -59,12 +59,16 @@
 */
 typedef struct
 {
+    /*! \brief The FAX modem set for the audio side fo the gateway. */
     fax_modems_state_t modems;
     /*! \brief The current receive signal handler. Actual receiving hop between this
                and a dummy receive routine. */
     span_rx_handler_t *base_rx_handler;
 } t38_gateway_audio_state_t;
 
+/*!
+    T.38 gateway T.38 side state.
+*/
 typedef struct
 {
     /*! \brief non-ECM and HDLC modem receive data buffer. */
@@ -87,10 +91,15 @@
                rate and the current specified packet interval. */
     int octets_per_data_packet;
 
+    /*! \brief Bits into the non-ECM buffer */
     int in_bits;
+    /*! \brief Octets fed out from the non-ECM buffer */
     int out_octets;
 } t38_gateway_to_t38_state_t;
 
+/*!
+    T.38 gateway HDLC buffer.
+*/
 typedef struct
 {
     /*! \brief HDLC message buffers. */
@@ -103,6 +112,9 @@
     int contents;
 } t38_gateway_hdlc_buf_t;
 
+/*!
+    T.38 gateway HDLC state.
+*/
 typedef struct
 {
     /*! \brief HDLC message buffers. */
@@ -183,8 +195,11 @@
 */
 struct t38_gateway_state_s
 {
+    /*! T.38 side state */
     t38_gateway_t38_state_t t38x;
+    /*! Audio side state */
     t38_gateway_audio_state_t audio;
+    /*! T.38 core state */
     t38_gateway_core_state_t core;
 
     /*! \brief Error and flow logging control */

Added: freeswitch/trunk/libs/spandsp/src/spandsp/private/v18.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/v18.h	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,67 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * private/v18.h - V.18 text telephony for the deaf.
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2004-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 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: v18.h,v 1.4 2009/04/11 15:16:14 steveu Exp $
+ */
+ 
+#if !defined(_SPANDSP_PRIVATE_V18_H_)
+#define _SPANDSP_PRIVATE_V18_H_
+
+struct v18_state_s
+{
+    /*! \brief TRUE if we are the calling modem */
+    int caller;
+    int mode;
+    put_msg_func_t put_msg;
+    void *user_data;
+
+    union
+    {
+        queue_state_t queue;
+        uint8_t buf[QUEUE_STATE_T_SIZE(128)];
+    } queue;
+    tone_gen_descriptor_t alert_tone_desc;
+    tone_gen_state_t alert_tone_gen;
+    fsk_tx_state_t fsktx;
+    dtmf_tx_state_t dtmftx;
+    async_tx_state_t asynctx;
+    int baudot_tx_shift;
+    int tx_signal_on;
+    int byte_no;
+
+    fsk_rx_state_t fskrx;
+    dtmf_rx_state_t dtmfrx;
+    int baudot_rx_shift;
+    int consecutive_ones;
+    uint8_t rx_msg[256 + 1];
+    int rx_msg_len;
+    int bit_pos;
+    int in_progress;
+
+    /*! \brief Error and flow logging control */
+    logging_state_t logging;
+};
+
+#endif
+/*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/private/v22bis.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/private/v22bis.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/private/v22bis.h	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v22bis.h,v 1.1 2008/11/30 03:39:58 steveu Exp $
+ * $Id: v22bis.h,v 1.4 2009/04/17 14:37:53 steveu Exp $
  */
 
 #if !defined(_SPANDSP_PRIVATE_V22BIS_H_)
@@ -44,6 +44,10 @@
     get_bit_func_t get_bit;
     /*! \brief A user specified opaque pointer passed to the callback routines. */
     void *user_data;
+    /*! \brief The callback function used to report modem status changes. */
+    modem_rx_status_func_t status_handler;
+    /*! \brief A user specified opaque pointer passed to the status function. */
+    void *status_user_data;
 
     /* RECEIVE SECTION */
     struct
@@ -79,6 +83,8 @@
         float carrier_track_p;
         /*! \brief The integral part of the carrier tracking filter. */
         float carrier_track_i;
+        
+        int scrambled_ones_to_date;
 
         /*! \brief A callback function which may be enabled to report every symbol's
                    constellation position. */
@@ -125,6 +131,10 @@
         int baud_phase;
     
         int sixteen_way_decisions;
+
+        int detected_unscrambled_ones;
+        int detected_unscrambled_zeros;
+        int detected_2400bps_markers;
     } rx;
 
     /* TRANSMIT SECTION */
@@ -167,14 +177,6 @@
         get_bit_func_t current_get_bit;
     } tx;
 
-    int detected_unscrambled_ones;
-    int detected_unscrambled_zeros;
-
-    int detected_unscrambled_ones_or_zeros;
-    int detected_unscrambled_0011_ending;
-    int detected_scrambled_ones_or_zeros_at_1200bps;
-    int detected_scrambled_ones_at_2400bps;
-
     /*! \brief Error and flow logging control */
     logging_state_t logging;
 };

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/sig_tone.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/sig_tone.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/sig_tone.h	Mon Apr 20 13:33:33 2009
@@ -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.18 2009/02/10 13:06:47 steveu Exp $
+ * $Id: sig_tone.h,v 1.19 2009/04/12 14:18:02 steveu Exp $
  */
 
 /*! \file */
@@ -115,8 +115,16 @@
     \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);
 
+/*! Release a signaling tone receiver context.
+    \brief Release a signaling tone receiver context.
+    \param s The signaling tone context.
+    \return 0 for OK */
 SPAN_DECLARE(int) sig_tone_rx_release(sig_tone_rx_state_t *s);
 
+/*! Free a signaling tone receiver context.
+    \brief Free a signaling tone receiver context.
+    \param s The signaling tone context.
+    \return 0 for OK */
 SPAN_DECLARE(int) sig_tone_rx_free(sig_tone_rx_state_t *s);
 
 /*! Generate a block of signaling tone audio samples.
@@ -142,8 +150,16 @@
     \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);
 
+/*! Release a signaling tone transmitter context.
+    \brief Release a signaling tone transmitter context.
+    \param s The signaling tone context.
+    \return 0 for OK */
 SPAN_DECLARE(int) sig_tone_tx_release(sig_tone_tx_state_t *s);
 
+/*! Free a signaling tone transmitter context.
+    \brief Free a signaling tone transmitter context.
+    \param s The signaling tone context.
+    \return 0 for OK */
 SPAN_DECLARE(int) sig_tone_tx_free(sig_tone_tx_state_t *s);
 
 #if defined(__cplusplus)

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/silence_gen.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/silence_gen.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/silence_gen.h	Mon Apr 20 13:33:33 2009
@@ -22,22 +22,13 @@
  * 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.16 2009/02/10 13:06:47 steveu Exp $
+ * $Id: silence_gen.h,v 1.17 2009/04/12 03:29:58 steveu Exp $
  */
 
 #if !defined(_SPANDSP_SILENCE_GEN_H_)
 #define _SPANDSP_SILENCE_GEN_H_
 
-typedef struct
-{
-    /*! \brief The callback function used to report status changes. */
-    modem_tx_status_func_t status_handler;
-    /*! \brief A user specified opaque pointer passed to the status function. */
-    void *status_user_data;
-
-    int remaining_samples;
-    int total_samples;
-} silence_gen_state_t;
+typedef struct silence_gen_state_s silence_gen_state_t;
 
 #if defined(__cplusplus)
 extern "C"

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/t30.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/t30.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/t30.h	Mon Apr 20 13:33:33 2009
@@ -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.124 2009/02/20 12:34:20 steveu Exp $
+ * $Id: t30.h,v 1.125 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -140,8 +140,11 @@
     - DCN usage
 */
 
+/*! The maximum length of a DIS, DTC or DCS frame */
 #define T30_MAX_DIS_DTC_DCS_LEN     22
+/*! The maximum length of the body of an ident string */
 #define T30_MAX_IDENT_LEN           20
+/*! The maximum length of the user string to insert in page headers */
 #define T30_MAX_PAGE_HEADER_INFO    50
 
 typedef struct t30_state_s t30_state_t;
@@ -190,7 +193,7 @@
 typedef void (t30_real_time_frame_handler_t)(t30_state_t *s,
                                              void *user_data,
                                              int direction,
-                                             const uint8_t *msg,
+                                             const uint8_t msg[],
                                              int len);
 
 /*!
@@ -220,7 +223,7 @@
     \param msg The HDLC message.
     \param len The length of the message.
 */
-typedef void (t30_send_hdlc_handler_t)(void *user_data, const uint8_t *msg, int len);
+typedef void (t30_send_hdlc_handler_t)(void *user_data, const uint8_t msg[], int len);
 
 /*!
     T.30 protocol completion codes, at phase E.
@@ -650,7 +653,7 @@
     \param msg The HDLC message.
     \param len The length of the message, in octets.
     \param ok TRUE if the frame was received without error. */
-SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok);
+SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t msg[], int len, int ok);
 
 /*! Report the passage of time to the T.30 engine.
     \brief Report the passage of time to the T.30 engine.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/t30_api.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/t30_api.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/t30_api.h	Mon Apr 20 13:33:33 2009
@@ -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_api.h,v 1.9 2009/02/03 16:28:41 steveu Exp $
+ * $Id: t30_api.h,v 1.10 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -60,7 +60,7 @@
 /*! Set the transmitted NSC frame to be associated with a T.30 context.
     \brief Set the transmitted NSC frame to be associated with a T.30 context.
     \param s The T.30 context.
-    \param nsf A pointer to the frame.
+    \param nsc A pointer to the frame.
     \param len The length of the frame.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_nsc(t30_state_t *s, const uint8_t *nsc, int len);
@@ -82,7 +82,7 @@
 /*! Set the transmitted NSS frame to be associated with a T.30 context.
     \brief Set the transmitted NSS frame to be associated with a T.30 context.
     \param s The T.30 context.
-    \param nsf A pointer to the frame.
+    \param nss A pointer to the frame.
     \param len The length of the frame.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_nss(t30_state_t *s, const uint8_t *nss, int len);
@@ -111,15 +111,13 @@
 /*! Get the transmitted identifier associated with a T.30 context.
     \brief Set the transmitted identifier associated with a T.30 context.
     \param s The T.30 context.
-    \param id A pointer to the identifier.
-    \return 0 for OK, else -1. */
+    \return A pointer to the identifier. */
 SPAN_DECLARE(const char *) t30_get_tx_ident(t30_state_t *s);
 
 /*! Get the transmitted identifier associated with a T.30 context.
     \brief Set the transmitted identifier associated with a T.30 context.
     \param s The T.30 context.
-    \param id A pointer to the identifier.
-    \return 0 for OK, else -1. */
+    \return A pointer to the identifier. */
 SPAN_DECLARE(const char *) t30_get_rx_ident(t30_state_t *s);
 
 /*! Set the transmitted sub-address associated with a T.30 context.
@@ -132,15 +130,13 @@
 /*! Get the received sub-address associated with a T.30 context.
     \brief Get the received sub-address associated with a T.30 context.
     \param s The T.30 context.
-    \param sub_address A pointer to the sub-address.
-    \return 0 for OK, else -1. */
+    \return A pointer to the sub-address. */
 SPAN_DECLARE(const char *) t30_get_tx_sub_address(t30_state_t *s);
 
 /*! Get the received sub-address associated with a T.30 context.
     \brief Get the received sub-address associated with a T.30 context.
     \param s The T.30 context.
-    \param sub_address A pointer to the sub-address.
-    \return 0 for OK, else -1. */
+    \return A pointer to the sub-address. */
 SPAN_DECLARE(const char *) t30_get_rx_sub_address(t30_state_t *s);
 
 /*! Set the transmitted selective polling address (i.e. the one we will send to the far
@@ -155,16 +151,14 @@
     end) associated with a T.30 context.
     \brief Get the received selective polling address associated with a T.30 context.
     \param s The T.30 context.
-    \param selective_polling_address A pointer to the selective polling address.
-    \return 0 for OK, else -1. */
+    \return A pointer to the selective polling address. */
 SPAN_DECLARE(const char *) t30_get_tx_selective_polling_address(t30_state_t *s);
 
 /*! Get the received selective polling address (i.e. the one we will send to the far
     end) associated with a T.30 context.
     \brief Get the received selective polling address associated with a T.30 context.
     \param s The T.30 context.
-    \param selective_polling_address A pointer to the selective polling address.
-    \return 0 for OK, else -1. */
+    \return A pointer to the selective polling address. */
 SPAN_DECLARE(const char *) t30_get_rx_selective_polling_address(t30_state_t *s);
 
 /*! Set the transmitted polled sub-address (i.e. the one we will send to the far
@@ -179,16 +173,14 @@
     end) associated with a T.30 context.
     \brief Get the received polled sub-address associated with a T.30 context.
     \param s The T.30 context.
-    \param polled_sub_address A pointer to the polled sub-address.
-    \return 0 for OK, else -1. */
+    \return A pointer to the polled sub-address. */
 SPAN_DECLARE(const char *) t30_get_tx_polled_sub_address(t30_state_t *s);
 
 /*! Get the received polled sub-address (i.e. the one we will send to the far
     end) associated with a T.30 context.
     \brief Get the received polled sub-address associated with a T.30 context.
     \param s The T.30 context.
-    \param polled_sub_address A pointer to the polled sub-address.
-    \return 0 for OK, else -1. */
+    \return A pointer to the polled sub-address. */
 SPAN_DECLARE(const char *) t30_get_rx_polled_sub_address(t30_state_t *s);
 
 /*! Set the transmitted sender ident (i.e. the one we will send to the far
@@ -203,16 +195,14 @@
     end) associated with a T.30 context.
     \brief Get the received sender ident associated with a T.30 context.
     \param s The T.30 context.
-    \param sender_ident A pointer to the sender ident.
-    \return 0 for OK, else -1. */
+    \return A pointer to the sender ident. */
 SPAN_DECLARE(const char *) t30_get_tx_sender_ident(t30_state_t *s);
 
 /*! Get the received sender ident (i.e. the one we will send to the far
     end) associated with a T.30 context.
     \brief Get the received sender ident associated with a T.30 context.
     \param s The T.30 context.
-    \param sender_ident A pointer to the sender ident.
-    \return 0 for OK, else -1. */
+    \return A pointer to the sender ident. */
 SPAN_DECLARE(const char *) t30_get_rx_sender_ident(t30_state_t *s);
 
 /*! Set the transmitted password (i.e. the one we will send to the far
@@ -227,16 +217,14 @@
     end) associated with a T.30 context.
     \brief Get the received password associated with a T.30 context.
     \param s The T.30 context.
-    \param password A pointer to the password.
-    \return 0 for OK, else -1. */
+    \return A pointer to the password. */
 SPAN_DECLARE(const char *) t30_get_tx_password(t30_state_t *s);
 
 /*! Get the received password (i.e. the one we will send to the far
     end) associated with a T.30 context.
     \brief Get the received password associated with a T.30 context.
     \param s The T.30 context.
-    \param password A pointer to the password.
-    \return 0 for OK, else -1. */
+    \return A pointer to the password. */
 SPAN_DECLARE(const char *) t30_get_rx_password(t30_state_t *s);
 
 /*! Set the transmitted ??? (i.e. the one we will send to the far
@@ -244,7 +232,7 @@
     \brief Set the transmitted ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \param len The length of the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_tsa(t30_state_t *s, int type, const char *address, int len);
@@ -254,9 +242,8 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
-    \return 0 for OK, else -1. */
+    \param address A pointer to the address.
+    \return The length of the address. */
 SPAN_DECLARE(size_t) t30_get_tx_tsa(t30_state_t *s, int *type, const char *address[]);
 
 /*! Get the received ??? (i.e. the one we will send to the far
@@ -264,9 +251,8 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
-    \return 0 for OK, else -1. */
+    \param address A pointer to the address.
+    \return The length of the address. */
 SPAN_DECLARE(size_t) t30_get_rx_tsa(t30_state_t *s, int *type, const char *address[]);
 
 /*! Set the transmitted ??? (i.e. the one we will send to the far
@@ -274,7 +260,7 @@
     \brief Set the transmitted ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \param len The length of the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_ira(t30_state_t *s, int type, const char *address, int len);
@@ -284,9 +270,8 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
-    \return 0 for OK, else -1. */
+    \param address A pointer to the address.
+    \return The length of the address. */
 SPAN_DECLARE(size_t) t30_get_tx_ira(t30_state_t *s, int *type, const char *address[]);
 
 /*! Get the received ??? (i.e. the one we will send to the far
@@ -294,9 +279,8 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
-    \return 0 for OK, else -1. */
+    \param address A pointer to the address.
+    \return The length of the address. */
 SPAN_DECLARE(size_t) t30_get_rx_ira(t30_state_t *s, int *type, const char *address[]);
 
 /*! Set the transmitted ??? (i.e. the one we will send to the far
@@ -304,7 +288,7 @@
     \brief Set the transmitted ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \param len The length of the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_cia(t30_state_t *s, int type, const char *address, int len);
@@ -314,9 +298,8 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
-    \return 0 for OK, else -1. */
+    \param address A pointer to the address.
+    \return The length of the address. */
 SPAN_DECLARE(size_t) t30_get_tx_cia(t30_state_t *s, int *type, const char *address[]);
 
 /*! Get the received ??? (i.e. the one we will send to the far
@@ -324,8 +307,7 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
+    \param address A pointer to the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(size_t) t30_get_rx_cia(t30_state_t *s, int *type, const char *address[]);
 
@@ -334,7 +316,7 @@
     \brief Set the transmitted ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \param len The length of the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_isp(t30_state_t *s, int type, const char *address, int len);
@@ -344,7 +326,7 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(size_t) t30_get_tx_isp(t30_state_t *s, int *type, const char *address[]);
 
@@ -353,7 +335,7 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(size_t) t30_get_rx_isp(t30_state_t *s, int *type, const char *address[]);
 
@@ -362,7 +344,7 @@
     \brief Set the transmitted ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
+    \param address A pointer to the address.
     \param len The length of the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(int) t30_set_tx_csa(t30_state_t *s, int type, const char *address, int len);
@@ -372,9 +354,8 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
-    \return 0 for OK, else -1. */
+    \param address A pointer to the address.
+    \return The length of the address. */
 SPAN_DECLARE(size_t) t30_get_tx_csa(t30_state_t *s, int *type, const char *address[]);
 
 /*! Get the received ??? (i.e. the one we will send to the far
@@ -382,8 +363,7 @@
     \brief Get the received ??? associated with a T.30 context.
     \param s The T.30 context.
     \param type The type of address.
-    \param type A pointer to the address.
-    \param len The length of the address.
+    \param address A pointer to the address.
     \return 0 for OK, else -1. */
 SPAN_DECLARE(size_t) t30_get_rx_csa(t30_state_t *s, int *type, const char *address[]);
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/t31.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/t31.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/t31.h	Mon Apr 20 13:33:33 2009
@@ -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: t31.h,v 1.58 2009/02/10 13:06:47 steveu Exp $
+ * $Id: t31.h,v 1.59 2009/03/13 12:59:26 steveu Exp $
  */
 
 /*! \file */
@@ -69,6 +69,14 @@
     \return The number of samples unprocessed. */
 SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len);
 
+/*! Fake processing of a missing block of received T.31 modem audio samples
+    (e.g due to packet loss).
+    \brief Fake processing of a missing block of received T.31 modem audio samples.
+    \param s The T.31 modem context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed. */
+SPAN_DECLARE(int) t31_rx_fillin(t31_state_t *s, int len);
+
 /*! Generate a block of T.31 modem audio samples.
     \brief Generate a block of T.31 modem audio samples.
     \param s The T.31 modem context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/t38_core.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/t38_core.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/t38_core.h	Mon Apr 20 13:33:33 2009
@@ -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_core.h,v 1.37 2009/02/10 13:06:47 steveu Exp $
+ * $Id: t38_core.h,v 1.38 2009/04/12 14:18:02 steveu Exp $
  */
 
 /*! \file */
@@ -173,8 +173,11 @@
 /*! T.38 data field */
 typedef struct
 {
+    /*! Field type */
     int field_type;
+    /*! Field contents */
     const uint8_t *field;
+    /*! Field length */
     int field_len;
 } t38_data_field_t;
 
@@ -328,6 +331,16 @@
 */
 SPAN_DECLARE(logging_state_t *) t38_core_get_logging_state(t38_core_state_t *s);
 
+/*! Initialise a T.38 core context.
+    \brief Initialise a T.38 core context.
+    \param s The T.38 context.
+    \param rx_indicator_handler Receive indicator handling routine.
+    \param rx_data_handler Receive data packet handling routine.
+    \param rx_rx_missing_handler Missing receive packet handling routine.
+    \param rx_packet_user_data An opaque pointer passed to the rx packet handling routines.
+    \param tx_packet_handler Packet transmit handling routine.
+    \param tx_packet_user_data An opaque pointer passed to the tx_packet_handler.
+    \return A pointer to the T.38 context, or NULL if there was a problem. */
 SPAN_DECLARE(t38_core_state_t *) t38_core_init(t38_core_state_t *s,
                                                t38_rx_indicator_handler_t *rx_indicator_handler,
                                                t38_rx_data_handler_t *rx_data_handler,
@@ -336,8 +349,16 @@
                                                t38_tx_packet_handler_t *tx_packet_handler,
                                                void *tx_packet_user_data);
 
+/*! Release a signaling tone transmitter context.
+    \brief Release a signaling tone transmitter context.
+    \param s The T.38 context.
+    \return 0 for OK */
 SPAN_DECLARE(int) t38_core_release(t38_core_state_t *s);
 
+/*! Free a signaling tone transmitter context.
+    \brief Free a signaling tone transmitter context.
+    \param s The T.38 context.
+    \return 0 for OK */
 SPAN_DECLARE(int) t38_core_free(t38_core_state_t *s);
 
 #if defined(__cplusplus)

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/t38_gateway.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/t38_gateway.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/t38_gateway.h	Mon Apr 20 13:33:33 2009
@@ -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_gateway.h,v 1.62 2009/02/10 13:06:47 steveu Exp $
+ * $Id: t38_gateway.h,v 1.63 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -40,9 +40,11 @@
 \section t38_gateway_page_sec_2 How does it work?
 */
 
+/*! The receive buffer length */
 #define T38_RX_BUF_LEN          2048
+/*! The number of HDLC transmit buffers */
 #define T38_TX_HDLC_BUFS        256
-/* Make sure the HDLC frame buffers are big enough for ECM frames. */
+/*! The maximum length of an HDLC frame buffer. This must be big enough for ECM frames. */
 #define T38_MAX_HDLC_LEN        260
 
 typedef struct t38_gateway_state_s t38_gateway_state_t;
@@ -62,6 +64,9 @@
                                                      const uint8_t *msg,
                                                      int len);
 
+/*!
+    T.38 gateway results.
+ */
 typedef struct
 {
     /*! \brief The current bit rate for image transfer. */

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/t4.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/t4.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/t4.h	Mon Apr 20 13:33:33 2009
@@ -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: t4.h,v 1.58 2009/02/20 12:34:20 steveu Exp $
+ * $Id: t4.h,v 1.59 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -258,6 +258,11 @@
     \return 0 for success, otherwise -1. */
 SPAN_DECLARE(int) t4_rx_free(t4_state_t *s);
 
+/*! \brief Set the row write handler for a T.4 receive context.
+    \param s The T.4 receive context.
+    \param handler A pointer to the handler routine.
+    \param user_data An opaque pointer passed to the handler routine.
+    \return 0 for success, otherwise -1. */
 SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_state_t *s, t4_row_write_handler_t handler, void *user_data);
 
 /*! \brief Set the encoding for the received data.
@@ -416,6 +421,11 @@
     \param info A string, of up to 50 bytes, which will form the info field. */
 SPAN_DECLARE(void) t4_tx_set_header_info(t4_state_t *s, const char *info);
 
+/*! \brief Set the row read handler for a T.4 transmit context.
+    \param s The T.4 transmit context.
+    \param handler A pointer to the handler routine.
+    \param user_data An opaque pointer passed to the handler routine.
+    \return 0 for success, otherwise -1. */
 SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_state_t *s, t4_row_read_handler_t handler, void *user_data);
 
 /*! \brief Get the row-to-row (y) resolution of the current page.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/telephony.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/telephony.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/telephony.h	Mon Apr 20 13:33:33 2009
@@ -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: telephony.h,v 1.17 2009/02/25 15:30:21 steveu Exp $
+ * $Id: telephony.h,v 1.18 2009/03/23 14:17:42 steveu Exp $
  */
 
 #if !defined(_SPANDSP_TELEPHONY_H_)
@@ -63,6 +63,9 @@
 /*! \brief A handler for receive, where the buffer can be altered. */
 typedef int (span_mod_handler_t)(void *s, int16_t amp[], int len);
 
+/*! \brief A handler for missing receive data fill-in. */
+typedef int (span_rx_fillin_handler_t)(void *s, int len);
+
 /*! \brief A handler for transmit, where the buffer will be filled. */
 typedef int (span_tx_handler_t)(void *s, int16_t amp[], int max_len);
 

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v17rx.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v17rx.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v17rx.h	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v17rx.h,v 1.61 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v17rx.h,v 1.63 2009/04/12 04:20:01 steveu Exp $
  */
 
 /*! \file */
@@ -213,16 +213,21 @@
 
 /* Target length for the equalizer is about 63 taps, to deal with the worst stuff
    in V.56bis. */
-#define V17_EQUALIZER_PRE_LEN       8  /* This much before the real event */
-#define V17_EQUALIZER_POST_LEN      8  /* This much after the real event (must be even) */
+/*! Samples before the target position in the equalizer buffer */
+#define V17_EQUALIZER_PRE_LEN       8
+/*! Samples after the target position in the equalizer buffer */
+#define V17_EQUALIZER_POST_LEN      8
 
+/*! The number of taps in the pulse shaping/bandpass filter */
 #define V17_RX_FILTER_STEPS         27
 
 /* We can store more trellis depth that we look back over, so that we can push out a group
    of symbols in one go, giving greater processing efficiency, at the expense of a bit more
    latency through the modem. */
 /* Right now we don't take advantage of this optimisation. */
+/*! The depth of the trellis buffer */
 #define V17_TRELLIS_STORAGE_DEPTH   16
+/*! How far we look back into history for trellis decisions */
 #define V17_TRELLIS_LOOKBACK_DEPTH  16
 
 /*!
@@ -265,6 +270,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v17_rx_free(v17_rx_state_t *s);
 
+/*! Get the logging context associated with a V.17 modem receive context.
+    \brief Get the logging context associated with a V.17 modem receive context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v17_rx_get_logging_state(v17_rx_state_t *s);
 
 /*! Change the put_bit function associated with a V.17 modem receive context.
@@ -290,6 +299,15 @@
 */
 SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len);
 
+/*! Fake processing of a missing block of received V.17 modem audio samples.
+    (e.g due to packet loss).
+    \brief Fake processing of a missing block of received V.17 modem audio samples.
+    \param s The modem context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed.
+*/
+SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len);
+
 /*! Get a snapshot of the current equalizer coefficients.
     \brief Get a snapshot of the current equalizer coefficients.
     \param s The modem context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v17tx.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v17tx.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v17tx.h	Mon Apr 20 13:33:33 2009
@@ -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: v17tx.h,v 1.40 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v17tx.h,v 1.41 2009/04/12 09:12:11 steveu Exp $
  */
 
 /*! \file */
@@ -81,6 +81,7 @@
 transmitter. 
 */
 
+/*! The number of taps in the pulse shaping/bandpass filter */
 #define V17_TX_FILTER_STEPS     9
 
 /*!
@@ -132,6 +133,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v17_tx_free(v17_tx_state_t *s);
 
+/*! Get the logging context associated with a V.17 modem transmit context.
+    \brief Get the logging context associated with a V.17 modem transmit context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v17_tx_get_logging_state(v17_tx_state_t *s);
 
 /*! Change the get_bit function associated with a V.17 modem transmit context.

Added: freeswitch/trunk/libs/spandsp/src/spandsp/v18.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v18.h	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,155 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * v18.h - V.18 text telephony for the deaf.
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2004-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 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: v18.h,v 1.3 2009/04/12 09:12:11 steveu Exp $
+ */
+ 
+/*! \file */
+
+/*! \page v18_page The V.18 text telephony protocols
+\section v18_page_sec_1 What does it do?
+
+\section v18_page_sec_2 How does it work?
+*/
+
+#if !defined(_SPANDSP_V18_H_)
+#define _SPANDSP_V18_H_
+
+typedef struct v18_state_s v18_state_t;
+
+enum
+{
+    V18_MODE_NONE = 0,
+    /* V.18 Annex A - Weitbrecht TDD at 45.45bps, half-duplex, 5 bit baudot. */
+    V18_MODE_5BIT_45 = 1,
+    /* V.18 Annex A - Weitbrecht TDD at 50bps, half-duplex, 5 bit baudot. */
+    V18_MODE_5BIT_50 = 2,
+    /* V.18 Annex B - DTMF encoding of ASCII. */
+    V18_MODE_DTMF = 3,
+    /* V.18 Annex C - EDT 110bps, V.21, half-duplex, ASCII. */
+    V18_MODE_EDT = 4,
+    /* V.18 Annex D - 300bps, Bell 103, duplex, ASCII. */
+    V18_MODE_BELL103 = 5,
+    /* V.18 Annex E - 1200bps Videotex terminals, ASCII. */
+    V18_MODE_V23VIDEOTEX = 6,
+    /* V.18 Annex F - V.21 text telephone, V.21, duplex, ASCII. */
+    V18_MODE_V21TEXTPHONE = 7,
+    /* V.18 Annex G - V.18 text telephone mode. */
+    V18_MODE_V18TEXTPHONE = 8
+};
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s);
+
+/*! Initialise a V.18 context.
+    \brief Initialise a V.18 context.
+    \param s The V.18 context.
+    \param caller TRUE if caller mode, else answerer mode.
+    \param mode Mode of operation.
+    \param put_msg A callback routine called to deliver the received text
+           to the application.
+    \param user_data An opaque pointer for the callback routine.
+    \return A pointer to the V.18 context, or NULL if there was a problem. */
+SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
+                                     int caller,
+                                     int mode,
+                                     put_msg_func_t put_msg,
+                                     void *user_data);
+
+/*! Release a V.18 context.
+    \brief Release a V.18 context.
+    \param s The V.18 context.
+    \return 0 for OK. */
+SPAN_DECLARE(int) v18_release(v18_state_t *s);
+
+/*! Free a V.18 context.
+    \brief Release a V.18 context.
+    \param s The V.18 context.
+    \return 0 for OK. */
+SPAN_DECLARE(int) v18_free(v18_state_t *s);
+
+/*! Generate a block of V.18 audio samples.
+    \brief Generate a block of V.18 audio samples.
+    \param s The V.18 context.
+    \param amp The audio sample buffer.
+    \param max_len The number of samples to be generated.
+    \return The number of samples actually generated.
+*/
+SPAN_DECLARE(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len);
+
+/*! Process a block of received V.18 audio samples.
+    \brief Process a block of received V.18 audio samples.
+    \param s The V.18 context.
+    \param amp The audio sample buffer.
+    \param len The number of samples in the buffer.
+*/
+SPAN_DECLARE(int) v18_rx(v18_state_t *s, const int16_t amp[], int len);
+
+/*! \brief Put a string to a V.18 context's input buffer.
+    \param s The V.18 context.
+    \param msg The string to be added.
+    \param len The length of the string. If negative, the string is
+           assumed to be a NULL terminated string.
+    \return The number of characters actually added. This may be less than the
+            length of the digit string, if the buffer fills up. */
+SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len);
+
+/*! Convert a text string to a V.18 DTMF string.
+    \brief Convert a text string to a V.18 DTMF string.
+    \param s The V.18 context.
+    \param dtmf The resulting DTMF string.
+    \param msg The text string to be converted.
+    \return The length of the DTMF string.
+*/
+SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[]);
+
+/*! Convert a V.18 DTMF string to a text string.
+    \brief Convert a V.18 DTMF string to a text string.
+    \param s The V.18 context.
+    \param msg The resulting test string.
+    \param dtmf The DTMF string to be converted.
+    \return The length of the text string.
+*/
+SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[]);
+
+SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch);
+
+SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch);
+
+/*! \brief Return a short name for an V.18 mode
+    \param mode The code for the V.18 mode.
+    \return A pointer to the name.
+*/
+SPAN_DECLARE(const char *) v18_mode_to_str(int mode);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v22bis.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v22bis.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v22bis.h	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v22bis.h,v 1.35 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v22bis.h,v 1.39 2009/04/17 14:37:53 steveu Exp $
  */
 
 /*! \file */
@@ -50,11 +50,22 @@
 #if !defined(_SPANDSP_V22BIS_H_)
 #define _SPANDSP_V22BIS_H_
 
-#define V22BIS_EQUALIZER_LEN    7  /* this much to the left and this much to the right */
-#define V22BIS_EQUALIZER_MASK   15 /* one less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */
+enum
+{
+    V22BIS_GUARD_TONE_NONE,
+    V22BIS_GUARD_TONE_550HZ,
+    V22BIS_GUARD_TONE_1800HZ
+};
+
+/*! The number of steps to the left and to the right of the target position in the equalizer buffer. */
+#define V22BIS_EQUALIZER_LEN    7
+/*! One less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */
+#define V22BIS_EQUALIZER_MASK   15
 
+/*! The number of taps in the transmit pulse shaping filter */
 #define V22BIS_TX_FILTER_STEPS  9
 
+/*! The number of taps in the receive pulse shaping/bandpass filter */
 #define V22BIS_RX_FILTER_STEPS  37
 
 /*!
@@ -85,6 +96,14 @@
     \return The number of samples unprocessed. */
 SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len);
 
+/*! Fake processing of a missing block of received V.22bis modem audio samples.
+    (e.g due to packet loss).
+    \brief Fake processing of a missing block of received V.22bis modem audio samples.
+    \param s The modem context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed. */
+SPAN_DECLARE(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
+
 /*! Get a snapshot of the current equalizer coefficients.
     \brief Get a snapshot of the current equalizer coefficients.
     \param coeffs The vector of complex coefficients.
@@ -106,6 +125,11 @@
     \return The signal power, in dBm0. */
 SPAN_DECLARE(float) v22bis_rx_signal_power(v22bis_state_t *s);
 
+/*! Set the power level at which the carrier detection will cut in
+    \param s The modem context.
+    \param cutoff The signal cutoff power, in dBm0. */
+SPAN_DECLARE(void) v22bis_rx_signal_cutoff(v22bis_state_t *s, float cutoff);
+
 /*! Set a handler routine to process QAM status reports
     \param s The modem context.
     \param handler The handler routine.
@@ -164,6 +188,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v22bis_free(v22bis_state_t *s);
 
+/*! Get the logging context associated with a V.22bis modem context.
+    \brief Get the logging context associated with a V.22bis modem context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v22bis_get_logging_state(v22bis_state_t *s);
 
 /*! Change the get_bit function associated with a V.22bis modem context.
@@ -180,6 +208,13 @@
     \param user_data An opaque pointer. */
 SPAN_DECLARE(void) v22bis_set_put_bit(v22bis_state_t *s, put_bit_func_t put_bit, void *user_data);
 
+/*! Change the modem status report function associated with a V.22bis modem receive context.
+    \brief Change the modem status report function associated with a V.22bis modem receive context.
+    \param s The modem context.
+    \param handler The callback routine used to report modem status changes.
+    \param user_data An opaque pointer. */
+SPAN_DECLARE(void) v22bis_set_modem_status_handler(v22bis_state_t *s, modem_rx_status_func_t handler, void *user_data);
+
 #if defined(__cplusplus)
 }
 #endif

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_rx.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_rx.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_rx.h	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v27ter_rx.h,v 1.57 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v27ter_rx.h,v 1.59 2009/04/12 09:12:11 steveu Exp $
  */
 
 /*! \file */
@@ -48,10 +48,14 @@
 
 /* Target length for the equalizer is about 43 taps for 4800bps and 32 taps for 2400bps
    to deal with the worst stuff in V.56bis. */
+/*! Samples before the target position in the equalizer buffer */
 #define V27TER_EQUALIZER_PRE_LEN        16  /* This much before the real event */
+/*! Samples after the target position in the equalizer buffer */
 #define V27TER_EQUALIZER_POST_LEN       14  /* This much after the real event (must be even) */
 
+/*! The number of taps in the 4800bps pulse shaping/bandpass filter */
 #define V27TER_RX_4800_FILTER_STEPS     27
+/*! The number of taps in the 2400bps pulse shaping/bandpass filter */
 #define V27TER_RX_2400_FILTER_STEPS     27
 
 #if V27TER_RX_4800_FILTER_STEPS > V27TER_RX_2400_FILTER_STEPS
@@ -100,6 +104,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v27ter_rx_free(v27ter_rx_state_t *s);
 
+/*! Get the logging context associated with a V.27ter modem receive context.
+    \brief Get the logging context associated with a V.27ter modem receive context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v27ter_rx_get_logging_state(v27ter_rx_state_t *s);
 
 /*! Change the put_bit function associated with a V.27ter modem receive context.
@@ -125,6 +133,15 @@
 */
 SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len);
 
+/*! Fake processing of a missing block of received V.27ter modem audio samples.
+    (e.g due to packet loss).
+    \brief Fake processing of a missing block of received V.27ter modem audio samples.
+    \param s The modem context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed.
+*/
+SPAN_DECLARE(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len);
+
 /*! Get a snapshot of the current equalizer coefficients.
     \brief Get a snapshot of the current equalizer coefficients.
     \param coeffs The vector of complex coefficients.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_tx.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_tx.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v27ter_tx.h	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v27ter_tx.h,v 1.40 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v27ter_tx.h,v 1.41 2009/04/12 09:12:11 steveu Exp $
  */
 
 /*! \file */
@@ -64,6 +64,7 @@
 transmitter.
 */
 
+/*! The number of taps in the pulse shaping/bandpass filter */
 #define V27TER_TX_FILTER_STEPS      9
 
 /*!
@@ -113,6 +114,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v27ter_tx_free(v27ter_tx_state_t *s);
 
+/*! Get the logging context associated with a V.27ter modem transmit context.
+    \brief Get the logging context associated with a V.27ter modem transmit context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v27ter_tx_get_logging_state(v27ter_tx_state_t *s);
 
 /*! Change the get_bit function associated with a V.27ter modem transmit context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v29rx.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v29rx.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v29rx.h	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v29rx.h,v 1.68 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v29rx.h,v 1.70 2009/04/12 09:12:11 steveu Exp $
  */
 
 /*! \file */
@@ -122,9 +122,12 @@
 
 /* Target length for the equalizer is about 63 taps, to deal with the worst stuff
    in V.56bis. */
-#define V29_EQUALIZER_PRE_LEN   16  /* This much before the real event */
-#define V29_EQUALIZER_POST_LEN  14  /* This much after the real event (must be even) */
+/*! Samples before the target position in the equalizer buffer */
+#define V29_EQUALIZER_PRE_LEN   16
+/*! Samples after the target position in the equalizer buffer */
+#define V29_EQUALIZER_POST_LEN  14
 
+/*! The number of taps in the pulse shaping/bandpass filter */
 #define V29_RX_FILTER_STEPS     27
 
 typedef void (*qam_report_handler_t)(void *user_data, const complexf_t *constel, const complexf_t *target, int symbol);
@@ -169,6 +172,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v29_rx_free(v29_rx_state_t *s);
 
+/*! Get the logging context associated with a V.29 modem receive context.
+    \brief Get the logging context associated with a V.29 modem receive context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v29_rx_get_logging_state(v29_rx_state_t *s);
 
 /*! Change the put_bit function associated with a V.29 modem receive context.
@@ -193,6 +200,14 @@
     \return The number of samples unprocessed. */
 SPAN_DECLARE(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len);
 
+/*! Fake processing of a missing block of received V.29 modem audio samples.
+    (e.g due to packet loss).
+    \brief Fake processing of a missing block of received V.29 modem audio samples.
+    \param s The modem context.
+    \param len The number of samples to fake.
+    \return The number of samples unprocessed. */
+SPAN_DECLARE(int) v29_rx_fillin(v29_rx_state_t *s, int len);
+
 /*! Get a snapshot of the current equalizer coefficients.
     \brief Get a snapshot of the current equalizer coefficients.
     \param s The modem context.

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v29tx.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v29tx.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v29tx.h	Mon Apr 20 13:33:33 2009
@@ -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: v29tx.h,v 1.38 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v29tx.h,v 1.39 2009/04/12 09:12:11 steveu Exp $
  */
 
 /*! \file */
@@ -94,6 +94,7 @@
 
 */
 
+/*! The number of taps in the pulse shaping/bandpass filter */
 #define V29_TX_FILTER_STEPS     9
 
 /*!
@@ -144,6 +145,10 @@
     \return 0 for OK */
 SPAN_DECLARE(int) v29_tx_free(v29_tx_state_t *s);
 
+/*! Get the logging context associated with a V.29 modem transmit context.
+    \brief Get the logging context associated with a V.29 modem transmit context.
+    \param s The modem context.
+    \return A pointer to the logging context */
 SPAN_DECLARE(logging_state_t *) v29_tx_get_logging_state(v29_tx_state_t *s);
 
 /*! Change the get_bit function associated with a V.29 modem transmit context.
@@ -167,7 +172,7 @@
     \param len The number of samples to be generated.
     \return The number of samples actually generated.
 */
-SPAN_DECLARE(int) v29_tx(v29_tx_state_t *s, int16_t *amp, int len);
+SPAN_DECLARE(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len);
 
 #if defined(__cplusplus)
 }

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/v42bis.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/v42bis.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/v42bis.h	Mon Apr 20 13:33:33 2009
@@ -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: v42bis.h,v 1.26 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v42bis.h,v 1.27 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \page v42bis_page V.42bis modem data compression
@@ -107,11 +107,11 @@
     \param negotiated_p0 The negotiated P0 parameter, from the V.42bis spec.
     \param negotiated_p1 The negotiated P1 parameter, from the V.42bis spec.
     \param negotiated_p2 The negotiated P2 parameter, from the V.42bis spec.
-    \param frame_handler .
-    \param frame_user_data .
+    \param frame_handler Frame callback handler.
+    \param frame_user_data An opaque pointer passed to the frame callback handler.
     \param max_frame_len The maximum length that should be passed to the frame handler.
-    \param data_handler .
-    \param data_user_data .
+    \param data_handler data callback handler.
+    \param data_user_data An opaque pointer passed to the data callback handler.
     \param max_data_len The maximum length that should be passed to the data handler.
     \return The V.42bis context. */
 SPAN_DECLARE(v42bis_state_t *) v42bis_init(v42bis_state_t *s,

Modified: freeswitch/trunk/libs/spandsp/src/spandsp/version.h
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/spandsp/version.h	(original)
+++ freeswitch/trunk/libs/spandsp/src/spandsp/version.h	Mon Apr 20 13:33:33 2009
@@ -30,9 +30,9 @@
 
 /* The date and time of the version are in UTC form. */
 
-#define SPANDSP_RELEASE_DATE            20090307
-#define SPANDSP_RELEASE_TIME            165620
-#define SPANDSP_RELEASE_DATETIME_STRING "20090307 165620"
+#define SPANDSP_RELEASE_DATE            20090420
+#define SPANDSP_RELEASE_TIME            163808
+#define SPANDSP_RELEASE_DATETIME_STRING "20090420 163808"
 
 #endif
 /*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/t30.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t30.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t30.c	Mon Apr 20 13:33:33 2009
@@ -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.288 2009/02/26 12:11:51 steveu Exp $
+ * $Id: t30.c,v 1.290 2009/04/16 12:11:54 steveu Exp $
  */
 
 /*! \file */
@@ -73,8 +73,10 @@
 
 #include "t30_local.h"
 
+/*! The maximum number of consecutive retries allowed. */
 #define MAX_MESSAGE_TRIES   3
 
+/*! Conversion between milliseconds and audio samples. */
 #define ms_to_samples(t)    (((t)*SAMPLE_RATE)/1000)
 
 /* T.30 defines the following call phases:
@@ -207,7 +209,7 @@
 
 /* All timers specified in milliseconds */
 
-/* Time-out T0 defines the amount of time an automatic calling terminal waits for the called terminal
+/*! Time-out T0 defines the amount of time an automatic calling terminal waits for the called terminal
 to answer the call.
 T0 begins after the dialling of the number is completed and is reset:
 a) when T0 times out; or
@@ -219,41 +221,45 @@
 NOTE - National regulations may require the use of other values for T0. */
 #define DEFAULT_TIMER_T0                60000
 
-/* Time-out T1 defines the amount of time two terminals will continue to attempt to identify each
+/*! Time-out T1 defines the amount of time two terminals will continue to attempt to identify each
 other. T1 is 35+-5s, begins upon entering phase B, and is reset upon detecting a valid signal or
 when T1 times out.
 For operating methods 3 and 4 (see 3.1), the calling terminal starts time-out T1 upon reception of
 the V.21 modulation scheme.
 For operating method 4 bis a (see 3.1), the calling terminal starts time-out T1 upon starting
-transmission using the V.21 modulation scheme. */
+transmission using the V.21 modulation scheme.
+Annex A says T1 is also the timeout to be used for the receipt of the first HDLC frame after the
+start of high speed flags in ECM mode. This seems a strange reuse of the T1 name, so we distinguish
+it here by calling it T1A. */
 #define DEFAULT_TIMER_T1                35000
+#define DEFAULT_TIMER_T1A               35000
 
-/* Time-out T2 makes use of the tight control between commands and responses to detect the loss of
+/*! Time-out T2 makes use of the tight control between commands and responses to detect the loss of
 command/response synchronization. T2 is 6+-1s, and begins when initiating a command search
 (e.g., the first entrance into the "command received" subroutine, reference flow diagram in section 5.2).
 T2 is reset when an HDLC flag is received or when T2 times out. */
 #define DEFAULT_TIMER_T2                7000
 
-/* Once HDLC flags begin, T2 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
+/*! Once HDLC flags begin, T2 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
 term it T2A. No tolerance is specified for this timer. T2A specifies the maximum time to wait for the
 end of a frame, after the initial flag has been seen. */
 #define DEFAULT_TIMER_T2A               3000
 
-/* If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
+/*! If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
    don't, there are circumstances where we could continue and reply before the incoming signals have
    really finished. E.g. if a bad DCS is received in a DCS-TCF sequence, we need wait for the TCF
    carrier to pass, before continuing. This timer is specified as 200ms, but no tolerance is specified.
-   It is unnamed in T.30. Here we termin it T2B */
+   It is unnamed in T.30. Here we term it T2B */
 #define DEFAULT_TIMER_T2B               200
 
-/* Time-out T3 defines the amount of time a terminal will attempt to alert the local operator in
+/*! Time-out T3 defines the amount of time a terminal will attempt to alert the local operator in
 response to a procedural interrupt. Failing to achieve operator intervention, the terminal will
 discontinue this attempt and shall issue other commands or responses. T3 is 10+-5s, begins on the
 first detection of a procedural interrupt command/response signal (i.e., PIN/PIP or PRI-Q) and is
 reset when T3 times out or when the operator initiates a line request. */
 #define DEFAULT_TIMER_T3                15000
 
-/* Time-out T4 defines the amount of time a terminal will wait for flags to begin, when waiting for a
+/*! Time-out T4 defines the amount of time a terminal will wait for flags to begin, when waiting for a
 response from a remote terminal. T2 is 3s +-15%, and begins when initiating a response search
 (e.g., the first entrance into the "response received" subroutine, reference flow diagram in section 5.2).
 T4 is reset when an HDLC flag is received or when T4 times out.
@@ -262,19 +268,20 @@
 be reduced to 3.0s +-15%. T4 = 3.0s +-15% for automatic units. */
 #define DEFAULT_TIMER_T4                3450
 
-/* Once HDLC flags begin, T4 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
+/*! Once HDLC flags begin, T4 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
 term it T4A. No tolerance is specified for this timer. T4A specifies the maximum time to wait for the
-end of a frame, after the initial flag has been seen. */
+end of a frame, after the initial flag has been seen. Note that a different timer is used for the fast
+HDLC in ECM mode, to provide time for physical paper handling. */
 #define DEFAULT_TIMER_T4A               3000
 
-/* If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
+/*! If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
    don't, there are circumstances where we could continue and reply before the incoming signals have
    really finished. E.g. if a bad DCS is received in a DCS-TCF sequence, we need wait for the TCF
    carrier to pass, before continuing. This timer is specified as 200ms, but no tolerance is specified.
-   It is unnamed in T.30. Here we termin it T4B */
+   It is unnamed in T.30. Here we term it T4B */
 #define DEFAULT_TIMER_T4B               200
 
-/* Time-out T5 is defined for the optional T.4 error correction mode. Time-out T5 defines the amount
+/*! Time-out T5 is defined for the optional T.4 error correction mode. Time-out T5 defines the amount
 of time waiting for clearance of the busy condition of the receiving terminal. T5 is 60+-5s and
 begins on the first detection of the RNR response. T5 is reset when T5 times out or the MCF or PIP
 response is received or when the ERR or PIN response is received in the flow control process after
@@ -282,27 +289,27 @@
 call release. */
 #define DEFAULT_TIMER_T5                65000
 
-/* (Annex C - ISDN) Time-out T6 defines the amount of time two terminals will continue to attempt to
+/*! (Annex C - ISDN) Time-out T6 defines the amount of time two terminals will continue to attempt to
 identify each other. T6 is 5+-0.5s. The timeout begins upon entering Phase B, and is reset upon
 detecting a valid signal, or when T6 times out. */
 #define DEFAULT_TIMER_T6                5000
 
-/* (Annex C - ISDN) Time-out T7 is used to detect loss of command/response synchronization. T7 is 6+-1s.
+/*! (Annex C - ISDN) Time-out T7 is used to detect loss of command/response synchronization. T7 is 6+-1s.
 The timeout begins when initiating a command search (e.g., the first entrance into the "command received"
 subroutine - see flow diagram in C.5) and is reset upon detecting a valid signal or when T7 times out. */
 #define DEFAULT_TIMER_T7                7000
 
-/* (Annex C - ISDN) Time-out T8 defines the amount of time waiting for clearance of the busy condition
+/*! (Annex C - ISDN) Time-out T8 defines the amount of time waiting for clearance of the busy condition
 of the receiving terminal. T8 is 10+-1s. The timeout begins on the first detection of the combination
 of no outstanding corrections and the RNR response. T8 is reset when T8 times out or MCF response is
 received. If the timer T8 expires, a DCN command is transmitted for call release. */
 #define DEFAULT_TIMER_T8                10000
 
-/* Final time we allow for things to flush through the system, before we disconnect, in milliseconds.
+/*! Final time we allow for things to flush through the system, before we disconnect, in milliseconds.
    200ms should be fine for a PSTN call. For a T.38 call something longer is desirable. */
 #define FINAL_FLUSH_TIME                1000
 
-/* The number of PPRs received before CTC or EOR is sent in ECM mode. T.30 defines this as 4,
+/*! The number of PPRs received before CTC or EOR is sent in ECM mode. T.30 defines this as 4,
    but it could be varied, and the Japanese spec, for example, does make this value a
    variable. */
 #define PPR_LIMIT_BEFORE_CTC_OR_EOR     4
@@ -320,8 +327,11 @@
 };
 
 /* Start points in the fallback table for different capabilities */
+/*! The starting point in the modem fallback sequence if V.17 is allowed */
 #define T30_V17_FALLBACK_START          0
+/*! The starting point in the modem fallback sequence if V.17 is not allowed */
 #define T30_V29_FALLBACK_START          3
+/*! The starting point in the modem fallback sequence if V.29 is not allowed */
 #define T30_V27TER_FALLBACK_START       6
 
 static const struct
@@ -361,10 +371,15 @@
 static void timer_t4_start(t30_state_t *s);
 static void timer_t4a_start(t30_state_t *s);
 static void timer_t4b_start(t30_state_t *s);
+static void timer_t2_t4_stop(t30_state_t *s);
 
+/*! Test a specified bit within a DIS, DTC or DCS frame */
 #define test_ctrl_bit(s,bit) ((s)[3 + ((bit - 1)/8)] & (1 << ((bit - 1)%8)))
+/*! Set a specified bit within a DIS, DTC or DCS frame */
 #define set_ctrl_bit(s,bit) (s)[3 + ((bit - 1)/8)] |= (1 << ((bit - 1)%8))
+/*! Set a specified block of bits within a DIS, DTC or DCS frame */
 #define set_ctrl_bits(s,val,bit) (s)[3 + ((bit - 1)/8)] |= ((val) << ((bit - 1)%8))
+/*! Clear a specified bit within a DIS, DTC or DCS frame */
 #define clr_ctrl_bit(s,bit) (s)[3 + ((bit - 1)/8)] &= ~(1 << ((bit - 1)%8))
 
 static int terminate_operation_in_progress(t30_state_t *s)
@@ -4648,8 +4663,19 @@
 
 static void timer_t2a_start(t30_state_t *s)
 {
-    span_log(&s->logging, SPAN_LOG_FLOW, "Start T2A\n");
-    s->timer_t2_t4 = ms_to_samples(DEFAULT_TIMER_T2A);
+    /* T.30 Annex A says timeout T1 should be used in ECM phase C to time out the
+       first frame after the flags start. This seems a strange reuse of the name T1
+       for a different purpose, but there it is. We distinguish it by calling it T1A. */
+    if (s->phase == T30_PHASE_C_ECM_RX)
+    {
+        span_log(&s->logging, SPAN_LOG_FLOW, "Start T1A\n");
+        s->timer_t2_t4 = ms_to_samples(DEFAULT_TIMER_T1A);
+    }
+    else
+    {
+        span_log(&s->logging, SPAN_LOG_FLOW, "Start T2A\n");
+        s->timer_t2_t4 = ms_to_samples(DEFAULT_TIMER_T2A);
+    }
     s->timer_t2_t4_is = TIMER_IS_T2A;
 }
 /*- End of function --------------------------------------------------------*/
@@ -4686,6 +4712,13 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+static void timer_t2_t4_stop(t30_state_t *s)
+{
+    span_log(&s->logging, SPAN_LOG_FLOW, "Stop T2/T4\n");
+    s->timer_t2_t4 = 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 static void timer_t0_expired(t30_state_t *s)
 {
     span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired in state %d\n", s->state);
@@ -4934,7 +4967,7 @@
         s->tcf_most_zeros = 0;
         s->rx_signal_present = TRUE;
         s->rx_trained = TRUE;
-        s->timer_t2_t4 = 0;
+        timer_t2_t4_stop(s);
         break;
     case SIG_STATUS_CARRIER_UP:
         break;
@@ -5261,11 +5294,11 @@
         {
         case TIMER_IS_T2B:
             s->timer_t2_t4_is = TIMER_IS_T2C;
-            s->timer_t2_t4 = 0;
+            timer_t2_t4_stop(s);
             break;
         case TIMER_IS_T4B:
             s->timer_t2_t4_is = TIMER_IS_T4C;
-            s->timer_t2_t4 = 0;
+            timer_t2_t4_stop(s);
             break;
         }
         break;
@@ -5276,7 +5309,7 @@
            its time to change. */
         if (s->next_phase != T30_PHASE_IDLE)
         {
-            s->timer_t2_t4 = 0;
+            timer_t2_t4_stop(s);
             set_phase(s, s->next_phase);
             if (s->next_phase == T30_PHASE_C_NON_ECM_RX)
                 timer_t2_start(s);
@@ -5384,7 +5417,7 @@
     }
     s->rx_frame_received = TRUE;
     /* Cancel the command or response timer */
-    s->timer_t2_t4 = 0;
+    timer_t2_t4_stop(s);
     process_rx_control_msg(s, msg, len);
 }
 /*- End of function --------------------------------------------------------*/
@@ -5684,7 +5717,7 @@
             /* Cancel any receive timeout, and declare that a receive signal is present,
                since the front end is explicitly telling us we have seen something. */
             s->rx_signal_present = TRUE;
-            s->timer_t2_t4 = 0;
+            timer_t2_t4_stop(s);
             break;
         }
         break;

Modified: freeswitch/trunk/libs/spandsp/src/t30_logging.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t30_logging.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t30_logging.c	Mon Apr 20 13:33:33 2009
@@ -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_logging.c,v 1.11 2009/02/03 16:28:40 steveu Exp $
+ * $Id: t30_logging.c,v 1.12 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -72,6 +72,7 @@
 
 #include "t30_local.h"
 
+/*! Value string pair structure */
 typedef struct
 {
     int val;

Modified: freeswitch/trunk/libs/spandsp/src/t31.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t31.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t31.c	Mon Apr 20 13:33:33 2009
@@ -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.144 2009/02/16 09:57:22 steveu Exp $
+ * $Id: t31.c,v 1.150 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */
@@ -86,6 +86,7 @@
 
 #include "spandsp/private/logging.h"
 #include "spandsp/private/t38_core.h"
+#include "spandsp/private/silence_gen.h"
 #include "spandsp/private/fsk.h"
 #include "spandsp/private/v17tx.h"
 #include "spandsp/private/v17rx.h"
@@ -100,10 +101,15 @@
 #include "spandsp/private/t31.h"
 
 /* Settings suitable for paced transmission over a UDP transport */
+/*! The default number of milliseconds per transmitted IFP when sending bulk T.38 data */
 #define MS_PER_TX_CHUNK                         30
+/*! The number of transmissions of indicator IFP packets */
 #define INDICATOR_TX_COUNT                      3
+/*! The number of transmissions of data IFP packets */
 #define DATA_TX_COUNT                           1
+/*! The number of transmissions of terminating data IFP packets */
 #define DATA_END_TX_COUNT                       3
+/*! The default DTE timeout, in seconds */
 #define DEFAULT_DTE_TIMEOUT                     5
 
 /* Settings suitable for unpaced transmission over a TCP transport */
@@ -135,26 +141,6 @@
     DISBIT8 = 0x80
 };
 
-/* BEWARE: right now this must match up with a list in the AT interpreter code. */
-enum
-{
-    T31_NONE = -1,
-    T31_FLUSH = 0,
-    T31_SILENCE_TX,
-    T31_SILENCE_RX,
-    T31_CED_TONE,
-    T31_CNG_TONE,
-    T31_NOCNG_TONE,
-    T31_V21_TX,
-    T31_V17_TX,
-    T31_V27TER_TX,
-    T31_V29_TX,
-    T31_V21_RX,
-    T31_V17_RX,
-    T31_V27TER_RX,
-    T31_V29_RX
-};
-
 enum
 {
     T38_CHUNKING_MERGE_FCS_WITH_DATA    = 0x0001,
@@ -190,6 +176,9 @@
 
 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_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 v27ter_v21_rx(void *user_data, const int16_t amp[], int len);
 static int v29_v21_rx(void *user_data, const int16_t amp[], int len);
@@ -239,8 +228,8 @@
     case T30_FRONT_END_SEND_STEP_COMPLETE:
         switch (s->modem)
         {
-        case T31_SILENCE_TX:
-            s->modem = T31_NONE;
+        case FAX_MODEM_SILENCE_TX:
+            s->modem = FAX_MODEM_NONE;
             at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
             if (s->at_state.do_hangup)
             {
@@ -253,20 +242,20 @@
                 t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
             }
             break;
-        case T31_CED_TONE:
+        case FAX_MODEM_CED_TONE:
             /* Go directly to V.21/HDLC transmit. */
-            s->modem = T31_NONE;
-            restart_modem(s, T31_V21_TX);
+            s->modem = FAX_MODEM_NONE;
+            restart_modem(s, FAX_MODEM_V21_TX);
             t31_set_at_rx_mode(s, AT_MODE_HDLC);
             break;
-        case T31_V21_TX:
-        case T31_V17_TX:
-        case T31_V27TER_TX:
-        case T31_V29_TX:
-            s->modem = T31_NONE;
+        case FAX_MODEM_V21_TX:
+        case FAX_MODEM_V17_TX:
+        case FAX_MODEM_V27TER_TX:
+        case FAX_MODEM_V29_TX:
+            s->modem = FAX_MODEM_NONE;
             at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
             t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
-            restart_modem(s, T31_SILENCE_TX);
+            restart_modem(s, FAX_MODEM_SILENCE_TX);
             break;
         }
         break;
@@ -669,7 +658,7 @@
 
 static __inline__ int bits_to_us(t31_state_t *s, int bits)
 {
-    if (s->t38_fe.ms_per_tx_chunk == 0)
+    if (s->t38_fe.ms_per_tx_chunk == 0  ||  s->t38_fe.tx_bit_rate == 0)
         return 0;
     return bits*1000000/s->t38_fe.tx_bit_rate;
 }
@@ -1075,7 +1064,7 @@
                                       t->at_state.rx_data_bytes);
             t->at_state.rx_data_bytes = 0;
         }
-        restart_modem(t, T31_SILENCE_TX);
+        restart_modem(t, FAX_MODEM_SILENCE_TX);
         break;
     case AT_MODEM_CONTROL_RESTART:
         restart_modem(t, (int) (intptr_t) num);
@@ -1339,7 +1328,7 @@
         s->at_state.rx_trained = TRUE;
         break;
     case SIG_STATUS_CARRIER_UP:
-        if (s->modem == T31_CNG_TONE  ||  s->modem == T31_NOCNG_TONE  ||  s->modem == T31_V21_RX)
+        if (s->modem == FAX_MODEM_CNG_TONE  ||  s->modem == FAX_MODEM_NOCNG_TONE  ||  s->modem == FAX_MODEM_V21_RX)
         {
             s->at_state.rx_signal_present = TRUE;
             s->rx_frame_received = FALSE;
@@ -1372,14 +1361,14 @@
         s->at_state.rx_trained = FALSE;
         break;
     case SIG_STATUS_FRAMING_OK:
-        if (s->modem == T31_CNG_TONE  ||  s->modem == T31_NOCNG_TONE)
+        if (s->modem == FAX_MODEM_CNG_TONE  ||  s->modem == FAX_MODEM_NOCNG_TONE)
         {
             /* Once we get any valid HDLC the CNG tone stops, and we drop
                to the V.21 receive modem on its own. */
-            s->modem = T31_V21_RX;
+            s->modem = FAX_MODEM_V21_RX;
             s->at_state.transmit = FALSE;
         }
-        if (s->modem == T31_V17_RX  ||  s->modem == T31_V27TER_RX  ||  s->modem == T31_V29_RX)
+        if (s->modem == FAX_MODEM_V17_RX  ||  s->modem == FAX_MODEM_V27TER_RX  ||  s->modem == FAX_MODEM_V29_RX)
         {
             /* V.21 has been detected while expecting a different carrier.
                If +FAR=0 then result +FCERROR and return to command-mode.
@@ -1389,7 +1378,7 @@
             {
                 s->at_state.rx_signal_present = TRUE;
                 s->rx_frame_received = TRUE;
-                s->modem = T31_V21_RX;
+                s->modem = FAX_MODEM_V21_RX;
                 s->at_state.transmit = FALSE;
                 s->at_state.dte_is_waiting = TRUE;
                 at_put_response_code(&s->at_state, AT_RESPONSE_CODE_FRH3);
@@ -1397,7 +1386,7 @@
             }
             else
             {
-                s->modem = T31_SILENCE_TX;
+                s->modem = FAX_MODEM_SILENCE_TX;
                 t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
                 s->rx_frame_received = FALSE;
                 at_put_response_code(&s->at_state, AT_RESPONSE_CODE_FCERROR);
@@ -1530,12 +1519,11 @@
     s->at_state.rx_signal_present = FALSE;
     s->at_state.rx_trained = FALSE;
     s->rx_frame_received = FALSE;
-    t->rx_handler = (span_rx_handler_t *) &span_dummy_rx;
-    t->rx_user_data = NULL;
+    set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL);
     use_hdlc = FALSE;
     switch (s->modem)
     {
-    case T31_CNG_TONE:
+    case FAX_MODEM_CNG_TONE:
         if (s->t38_mode)
         {
             s->t38_fe.next_tx_samples = s->t38_fe.samples;
@@ -1550,31 +1538,27 @@
             /* 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. */
-            t->rx_handler = (span_rx_handler_t *) &cng_rx;
-            t->rx_user_data = s;
+            set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s);
             t31_v21_rx(s);
-            t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
-            t->tx_user_data = &t->connect_tx;
-            s->audio.next_tx_handler = NULL;
+            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);
         }
         s->at_state.transmit = TRUE;
         break;
-    case T31_NOCNG_TONE:
+    case FAX_MODEM_NOCNG_TONE:
         if (s->t38_mode)
         {
         }
         else
         {
-            t->rx_handler = (span_rx_handler_t *) &cng_rx;
-            t->rx_user_data = s;
+            set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s);
             t31_v21_rx(s);
             silence_gen_set(&t->silence_gen, 0);
-            t->tx_handler = (span_tx_handler_t *) &silence_gen;
-            t->tx_user_data = &t->silence_gen;
+            set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
         }
         s->at_state.transmit = FALSE;
         break;
-    case T31_CED_TONE:
+    case FAX_MODEM_CED_TONE:
         if (s->t38_mode)
         {
             s->t38_fe.next_tx_samples = s->t38_fe.samples;
@@ -1584,13 +1568,12 @@
         else
         {
             modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CED);
-            t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
-            t->tx_user_data = &t->connect_tx;
-            s->audio.next_tx_handler = NULL;
+            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);
         }
         s->at_state.transmit = TRUE;
         break;
-    case T31_V21_TX:
+    case FAX_MODEM_V21_TX:
         if (s->t38_mode)
         {
             s->t38_fe.next_tx_indicator = T38_IND_V21_PREAMBLE;
@@ -1605,27 +1588,25 @@
             /* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
             hdlc_tx_flags(&t->hdlc_tx, 32);
             fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &t->hdlc_tx);
-            t->tx_handler = (span_tx_handler_t *) &fsk_tx;
-            t->tx_user_data = &t->v21_tx;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         }
         s->hdlc_tx.final = FALSE;
         s->hdlc_tx.len = 0;
         s->dled = FALSE;
         s->at_state.transmit = TRUE;
         break;
-    case T31_V21_RX:
+    case FAX_MODEM_V21_RX:
         if (s->t38_mode)
         {
         }
         else
         {
-            t->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            t->rx_user_data = &t->v21_rx;
+            set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx);
             t31_v21_rx(s);
         }
         break;
-    case T31_V17_TX:
+    case FAX_MODEM_V17_TX:
         if (s->t38_mode)
         {
             switch (s->bit_rate)
@@ -1653,26 +1634,24 @@
         else
         {
             v17_tx_restart(&t->v17_tx, s->bit_rate, FALSE, s->short_train);
-            t->tx_handler = (span_tx_handler_t *) &v17_tx;
-            t->tx_user_data = &t->v17_tx;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         }
         s->tx.out_bytes = 0;
         s->tx.data_started = FALSE;
         s->at_state.transmit = TRUE;
         break;
-    case T31_V17_RX:
+    case FAX_MODEM_V17_RX:
         if (!s->t38_mode)
         {
-            t->rx_handler = (span_rx_handler_t *) &v17_v21_rx;
-            t->rx_user_data = s;
+            set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, s);
             v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train);
             /* Allow for +FCERROR/+FRH:3 */
             t31_v21_rx(s);
         }
         s->at_state.transmit = FALSE;
         break;
-    case T31_V27TER_TX:
+    case FAX_MODEM_V27TER_TX:
         if (s->t38_mode)
         {
             switch (s->bit_rate)
@@ -1692,26 +1671,24 @@
         else
         {
             v27ter_tx_restart(&t->v27ter_tx, s->bit_rate, FALSE);
-            t->tx_handler = (span_tx_handler_t *) &v27ter_tx;
-            t->tx_user_data = &t->v27ter_tx;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         }
         s->tx.out_bytes = 0;
         s->tx.data_started = FALSE;
         s->at_state.transmit = TRUE;
         break;
-    case T31_V27TER_RX:
+    case FAX_MODEM_V27TER_RX:
         if (!s->t38_mode)
         {
-            t->rx_handler = (span_rx_handler_t *) &v27ter_v21_rx;
-            t->rx_user_data = s;
+            set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, s);
             v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE);
             /* Allow for +FCERROR/+FRH:3 */
             t31_v21_rx(s);
         }
         s->at_state.transmit = FALSE;
         break;
-    case T31_V29_TX:
+    case FAX_MODEM_V29_TX:
         if (s->t38_mode)
         {
             switch (s->bit_rate)
@@ -1731,26 +1708,24 @@
         else
         {
             v29_tx_restart(&t->v29_tx, s->bit_rate, FALSE);
-            t->tx_handler = (span_tx_handler_t *) &v29_tx;
-            t->tx_user_data = &t->v29_tx;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         }
         s->tx.out_bytes = 0;
         s->tx.data_started = FALSE;
         s->at_state.transmit = TRUE;
         break;
-    case T31_V29_RX:
+    case FAX_MODEM_V29_RX:
         if (!s->t38_mode)
         {
-            t->rx_handler = (span_rx_handler_t *) &v29_v21_rx;
-            t->rx_user_data = s;
+            set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, s);
             v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE);
             /* Allow for +FCERROR/+FRH:3 */
             t31_v21_rx(s);
         }
         s->at_state.transmit = FALSE;
         break;
-    case T31_SILENCE_TX:
+    case FAX_MODEM_SILENCE_TX:
         if (s->t38_mode)
         {
             t38_core_send_indicator(&s->t38_fe.t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT);
@@ -1761,26 +1736,22 @@
         else
         {
             silence_gen_set(&t->silence_gen, 0);
-            t->tx_handler = (span_tx_handler_t *) &silence_gen;
-            t->tx_user_data = &t->silence_gen;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         }
         s->at_state.transmit = FALSE;
         break;
-    case T31_SILENCE_RX:
+    case FAX_MODEM_SILENCE_RX:
         if (!s->t38_mode)
         {
-            t->rx_handler = (span_rx_handler_t *) &silence_rx;
-            t->rx_user_data = s;
-
+            set_rx_handler(s, (span_rx_handler_t *) &silence_rx, s);
             silence_gen_set(&t->silence_gen, 0);
-            t->tx_handler = (span_tx_handler_t *) &silence_gen;
-            t->tx_user_data = &t->silence_gen;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         }
         s->at_state.transmit = FALSE;
         break;
-    case T31_FLUSH:
+    case FAX_MODEM_FLUSH:
         /* Send 200ms of silence to "push" the last audio out */
         if (s->t38_mode)
         {
@@ -1788,11 +1759,10 @@
         }
         else
         {
-            s->modem = T31_SILENCE_TX;
+            s->modem = FAX_MODEM_SILENCE_TX;
             silence_gen_alter(&t->silence_gen, ms_to_samples(200));
-            t->tx_handler = (span_tx_handler_t *) &silence_gen;
-            t->tx_user_data = &t->silence_gen;
-            s->audio.next_tx_handler = NULL;
+            set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+            set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
             s->at_state.transmit = TRUE;
         }
         break;
@@ -1910,7 +1880,7 @@
         if (new_transmit)
         {
             /* Send a specified period of silence, to space transmissions. */
-            restart_modem(s, T31_SILENCE_TX);
+            restart_modem(s, FAX_MODEM_SILENCE_TX);
             if (s->t38_mode)
                 s->t38_fe.next_tx_samples = s->t38_fe.samples + ms_to_samples(val*10);
             else
@@ -1930,7 +1900,7 @@
             }
             else
             {
-                restart_modem(s, T31_SILENCE_RX);
+                restart_modem(s, FAX_MODEM_SILENCE_RX);
             }
         }
         immediate_response = FALSE;
@@ -1940,7 +1910,7 @@
         switch (val)
         {
         case 3:
-            new_modem = (new_transmit)  ?  T31_V21_TX  :  T31_V21_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V21_TX  :  FAX_MODEM_V21_RX;
             s->short_train = FALSE;
             s->bit_rate = 300;
             break;
@@ -2003,84 +1973,84 @@
         case 24:
             s->t38_fe.next_tx_indicator = T38_IND_V27TER_2400_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V27TER_2400;
-            new_modem = (new_transmit)  ?  T31_V27TER_TX  :  T31_V27TER_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V27TER_TX  :  FAX_MODEM_V27TER_RX;
             s->short_train = FALSE;
             s->bit_rate = 2400;
             break;
         case 48:
             s->t38_fe.next_tx_indicator = T38_IND_V27TER_4800_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V27TER_4800;
-            new_modem = (new_transmit)  ?  T31_V27TER_TX  :  T31_V27TER_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V27TER_TX  :  FAX_MODEM_V27TER_RX;
             s->short_train = FALSE;
             s->bit_rate = 4800;
             break;
         case 72:
             s->t38_fe.next_tx_indicator = T38_IND_V29_7200_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V29_7200;
-            new_modem = (new_transmit)  ?  T31_V29_TX  :  T31_V29_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V29_TX  :  FAX_MODEM_V29_RX;
             s->short_train = FALSE;
             s->bit_rate = 7200;
             break;
         case 96:
             s->t38_fe.next_tx_indicator = T38_IND_V29_9600_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V29_9600;
-            new_modem = (new_transmit)  ?  T31_V29_TX  :  T31_V29_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V29_TX  :  FAX_MODEM_V29_RX;
             s->short_train = FALSE;
             s->bit_rate = 9600;
             break;
         case 73:
             s->t38_fe.next_tx_indicator = T38_IND_V17_7200_LONG_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_7200;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = FALSE;
             s->bit_rate = 7200;
             break;
         case 74:
             s->t38_fe.next_tx_indicator = T38_IND_V17_7200_SHORT_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_7200;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = TRUE;
             s->bit_rate = 7200;
             break;
         case 97:
             s->t38_fe.next_tx_indicator = T38_IND_V17_9600_LONG_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_9600;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = FALSE;
             s->bit_rate = 9600;
             break;
         case 98:
             s->t38_fe.next_tx_indicator = T38_IND_V17_9600_SHORT_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_9600;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = TRUE;
             s->bit_rate = 9600;
             break;
         case 121:
             s->t38_fe.next_tx_indicator = T38_IND_V17_12000_LONG_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_12000;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = FALSE;
             s->bit_rate = 12000;
             break;
         case 122:
             s->t38_fe.next_tx_indicator = T38_IND_V17_12000_SHORT_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_12000;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = TRUE;
             s->bit_rate = 12000;
             break;
         case 145:
             s->t38_fe.next_tx_indicator = T38_IND_V17_14400_LONG_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_14400;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = FALSE;
             s->bit_rate = 14400;
             break;
         case 146:
             s->t38_fe.next_tx_indicator = T38_IND_V17_14400_SHORT_TRAINING;
             s->t38_fe.current_tx_data_type = T38_DATA_V17_14400;
-            new_modem = (new_transmit)  ?  T31_V17_TX  :  T31_V17_RX;
+            new_modem = (new_transmit)  ?  FAX_MODEM_V17_TX  :  FAX_MODEM_V17_RX;
             s->short_train = TRUE;
             s->bit_rate = 14400;
             break;
@@ -2134,8 +2104,8 @@
             }
             s->at_state.rx_data_bytes = 0;
             s->at_state.transmit = FALSE;
-            s->modem = T31_SILENCE_TX;
-            s->audio.modems.rx_handler = span_dummy_rx;
+            s->modem = FAX_MODEM_SILENCE_TX;
+            set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL);
             t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
             at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
         }
@@ -2158,6 +2128,27 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data)
+{
+    s->audio.modems.rx_handler = handler;
+    s->audio.modems.rx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void set_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data)
+{
+    s->audio.modems.tx_handler = handler;
+    s->audio.modems.tx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void set_next_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data)
+{
+    s->audio.modems.next_tx_handler = handler;
+    s->audio.modems.next_tx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
 static int silence_rx(void *user_data, const int16_t amp[], int len)
 {
     t31_state_t *s;
@@ -2184,7 +2175,7 @@
     {
         /* After calling, S7 has elapsed... no carrier found. */
         at_put_response_code(&s->at_state, AT_RESPONSE_CODE_NO_CARRIER);
-        restart_modem(s, T31_SILENCE_TX);
+        restart_modem(s, FAX_MODEM_SILENCE_TX);
         at_modem_control(&s->at_state, AT_MODEM_CONTROL_HANGUP, NULL);
         t31_set_at_rx_mode(s, AT_MODE_ONHOOK_COMMAND);
     }
@@ -2209,8 +2200,7 @@
         /* 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));
-        s->rx_handler = (span_rx_handler_t *) &v17_rx;
-        s->rx_user_data = &s->v17_rx;
+        set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
     }
     else
     {
@@ -2220,8 +2210,7 @@
             /* 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));
-            s->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            s->rx_user_data = &s->v21_rx;
+            set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
         }
     }
     return len;
@@ -2241,8 +2230,7 @@
         /* 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));
-        s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
-        s->rx_user_data = &s->v27ter_rx;
+        set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
     }
     else
     {
@@ -2252,8 +2240,7 @@
             /* 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));
-            s->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            s->rx_user_data = &s->v21_rx;
+            set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
         }
     }
     return len;
@@ -2273,8 +2260,7 @@
         /* 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));
-        s->rx_handler = (span_rx_handler_t *) &v29_rx;
-        s->rx_user_data = &s->v29_rx;
+        set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
     }
     else
     {
@@ -2284,8 +2270,7 @@
             /* 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));
-            s->rx_handler = (span_rx_handler_t *) &fsk_rx;
-            s->rx_user_data = &s->v21_rx;
+            set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
         }
     }
     return len;
@@ -2298,7 +2283,7 @@
     int32_t power;
 
     /* Monitor for received silence.  Maximum needed detection is AT+FRS=255 (255*10ms). */
-    /* We could probably only run this loop if (s->modem == T31_SILENCE_RX), however,
+    /* We could probably only run this loop if (s->modem == FAX_MODEM_SILENCE_RX), however,
        the spec says "when silence has been present on the line for the amount of
        time specified".  That means some of the silence may have occurred before
        the AT+FRS=n command. This condition, however, is not likely to ever be the
@@ -2329,12 +2314,54 @@
     {
         t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
         at_put_response_code(&s->at_state, AT_RESPONSE_CODE_ERROR);
-        restart_modem(s, T31_SILENCE_TX);
+        restart_modem(s, FAX_MODEM_SILENCE_TX);
     }
 
-    if (!s->at_state.transmit  ||  s->modem == T31_CNG_TONE)
+    if (!s->at_state.transmit  ||  s->modem == FAX_MODEM_CNG_TONE)
         s->audio.modems.rx_handler(s->audio.modems.rx_user_data, amp, len);
-    return  0;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) t31_rx_fillin(t31_state_t *s, int len)
+{
+    /* To mitigate the effect of lost packets on a packet network we should
+       try to sustain the status quo. If there is no receive modem running, keep
+       things that way. If there is a receive modem running, try to sustain its
+       operation, without causing a phase hop, or letting its adaptive functions
+       diverge. */
+    /* Time is determined by counting the samples in audio packets coming in. */
+    s->call_samples += len;
+
+    /* In HDLC transmit mode, if 5 seconds elapse without data from the DTE
+       we must treat this as an error. We return the result ERROR, and change
+       to command-mode. */
+    if (s->dte_data_timeout  &&  s->call_samples > s->dte_data_timeout)
+    {
+        t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
+        at_put_response_code(&s->at_state, AT_RESPONSE_CODE_ERROR);
+        restart_modem(s, FAX_MODEM_SILENCE_TX);
+    }
+    /* Call the fillin function of the current modem (if there is one). */
+    switch (s->modem)
+    {
+    case FAX_MODEM_V21_RX:
+        len = fsk_rx_fillin(&s->audio.modems.v21_rx, len);
+        break;
+    case FAX_MODEM_V27TER_RX:
+        /* TODO: what about FSK in the early stages */
+        len = v27ter_rx_fillin(&s->audio.modems.v27ter_rx, len);
+        break;
+    case FAX_MODEM_V29_RX:
+        /* TODO: what about FSK in the early stages */
+        len = v29_rx_fillin(&s->audio.modems.v29_rx, len);
+        break;
+    case FAX_MODEM_V17_RX:
+        /* TODO: what about FSK in the early stages */
+        len = v17_rx_fillin(&s->audio.modems.v17_rx, len);
+        break;
+    }
+    return 0;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -2342,16 +2369,14 @@
 {
     if (s->audio.next_tx_handler)
     {
-        s->audio.modems.tx_handler = s->audio.next_tx_handler;
-        s->audio.modems.tx_user_data = s->audio.next_tx_user_data;
-        s->audio.next_tx_handler = NULL;
+        set_tx_handler(s, s->audio.next_tx_handler, s->audio.next_tx_user_data);
+        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         return 0;
     }
     /* There is nothing else to change to, so use zero length silence */
     silence_gen_alter(&(s->audio.modems.silence_gen), 0);
-    s->audio.modems.tx_handler = (span_tx_handler_t *) &silence_gen;
-    s->audio.modems.tx_user_data = &(s->audio.modems.silence_gen);
-    s->audio.next_tx_handler = NULL;
+    set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &s->audio.modems.silence_gen);
+    set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
     return -1;
 }
 /*- End of function --------------------------------------------------------*/
@@ -2523,7 +2548,7 @@
     s->audio.silence_heard = 0;
     s->silence_awaited = 0;
     s->call_samples = 0;
-    s->modem = T31_NONE;
+    s->modem = FAX_MODEM_NONE;
     s->at_state.transmit = TRUE;
 
     if ((s->rx_queue = queue_init(NULL, 4096, QUEUE_WRITE_ATOMIC | QUEUE_READ_ATOMIC)) == NULL)

Modified: freeswitch/trunk/libs/spandsp/src/t35.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t35.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t35.c	Mon Apr 20 13:33:33 2009
@@ -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: t35.c,v 1.29 2009/02/03 16:28:40 steveu Exp $
+ * $Id: t35.c,v 1.30 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*
@@ -68,19 +68,29 @@
 #include "spandsp/bit_operations.h"
 #include "spandsp/t35.h"
 
+/*! NSF pattern for FAX machine identification */
 typedef struct
 {
+    /*! The number of bytes of the NSF byte string to match */
     int model_id_size;
+    /*! The NSF byte string to expect */
     const char *model_id;
+    /*! The model name of the FAX terminal */
     const char *model_name;
 } model_data_t;
 
+/*! NSF pattern for identifying the manufacturer of a FAX machine */
 typedef struct
 {
+    /*! The vendor ID byte string */
     const char *vendor_id;
+    /*! The length of the vendor ID byte string */
     int vendor_id_len;
+    /*! The vendor's name */
     const char *vendor_name;
+    /*! TRUE if the station ID for this vendor is reversed */
     int inverse_station_id_order;
+    /*! A pointer to a list of known models from this vendor */
     const model_data_t *known_models;
 } nsf_data_t;
 

Modified: freeswitch/trunk/libs/spandsp/src/t38_gateway.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t38_gateway.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t38_gateway.c	Mon Apr 20 13:33:33 2009
@@ -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: t38_gateway.c,v 1.157 2009/02/16 09:57:22 steveu Exp $
+ * $Id: t38_gateway.c,v 1.162 2009/04/12 14:18:02 steveu Exp $
  */
 
 /*! \file */
@@ -84,6 +84,7 @@
 #include "spandsp/t38_gateway.h"
 
 #include "spandsp/private/logging.h"
+#include "spandsp/private/silence_gen.h"
 #include "spandsp/private/fsk.h"
 #include "spandsp/private/v17tx.h"
 #include "spandsp/private/v17rx.h"
@@ -102,12 +103,18 @@
 
 /* This is the target time per transmission chunk. The actual
    packet timing will sync to the data octets. */
-#define MS_PER_TX_CHUNK                 30
-#define HDLC_START_BUFFER_LEVEL         8
-
-#define INDICATOR_TX_COUNT              3
-#define DATA_TX_COUNT                   1
-#define DATA_END_TX_COUNT               3
+/*! The default number of milliseconds per transmitted IFP when sending bulk T.38 data */
+#define MS_PER_TX_CHUNK                         30
+/*! The number of bytes which must be in the audio to T.38 HDLC buffer before we start
+    outputting them as IFP messages. */
+#define HDLC_START_BUFFER_LEVEL                 8
+
+/*! The number of transmissions of indicator IFP packets */
+#define INDICATOR_TX_COUNT                      3
+/*! The number of transmissions of data IFP packets */
+#define DATA_TX_COUNT                           1
+/*! The number of transmissions of terminating data IFP packets */
+#define DATA_END_TX_COUNT                       3
 
 enum
 {
@@ -152,8 +159,11 @@
     TCF_MODE_PREDICTABLE_MODEM_START_BEGIN
 };
 
+/*! The maximum number of bytes to be zapped, in order to corrupt NSF,
+    NSS and NSC messages, so the receiver does not recognise them. */
 #define MAX_NSX_SUPPRESSION             10
 
+/*! The number of consecutive flags to declare HDLC framing is OK. */
 #define HDLC_FRAMING_OK_THRESHOLD       5
 
 static uint8_t nsx_overwrite[2][MAX_NSX_SUPPRESSION] =
@@ -181,6 +191,20 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+static void set_tx_handler(t38_gateway_state_t *s, span_tx_handler_t *handler, void *user_data)
+{
+    s->audio.modems.tx_handler = handler;
+    s->audio.modems.tx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void set_next_tx_handler(t38_gateway_state_t *s, span_tx_handler_t *handler, void *user_data)
+{
+    s->audio.modems.next_tx_handler = handler;
+    s->audio.modems.next_tx_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
 static void set_rx_active(t38_gateway_state_t *s, int active)
 {
     s->audio.modems.rx_handler = (active)  ?  s->audio.base_rx_handler  :  span_dummy_rx;
@@ -195,17 +219,17 @@
     t = (t38_gateway_state_t *) user_data;
     s = &t->audio.modems;
     v17_rx(&s->v17_rx, amp, len);
-    fsk_rx(&s->v21_rx, amp, len);
-    if (s->rx_signal_present)
+    if (s->rx_trained)
     {
-        if (s->rx_trained)
-        {
-            /* 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);
-        }
-        else
+        /* 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);
+    }
+    else
+    {
+        fsk_rx(&s->v21_rx, amp, len);
+        if (s->rx_signal_present)
         {
             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);
@@ -225,17 +249,17 @@
     t = (t38_gateway_state_t *) user_data;
     s = &t->audio.modems;
     v27ter_rx(&s->v27ter_rx, amp, len);
-    fsk_rx(&s->v21_rx, amp, len);
-    if (s->rx_signal_present)
+    if (s->rx_trained)
     {
-        if (s->rx_trained)
-        {
-            /* 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);
-        }
-        else
+        /* 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);
+    }
+    else
+    {
+        fsk_rx(&s->v21_rx, amp, len);
+        if (s->rx_signal_present)
         {
             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);
@@ -255,17 +279,17 @@
     t = (t38_gateway_state_t *) user_data;
     s = &t->audio.modems;
     v29_rx(&s->v29_rx, amp, len);
-    fsk_rx(&s->v21_rx, amp, len);
-    if (s->rx_signal_present)
+    if (s->rx_trained)
     {
-        if (s->rx_trained)
-        {
-            /* 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);
-        }
-        else
+        /* 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);
+    }
+    else
+    {
+        fsk_rx(&s->v21_rx, amp, len);
+        if (s->rx_signal_present)
         {
             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);
@@ -348,9 +372,8 @@
     if (t->next_tx_handler)
     {
         /* There is a handler queued, so that is the next one. */
-        t->tx_handler = t->next_tx_handler;
-        t->tx_user_data = t->next_tx_user_data;
-        t->next_tx_handler = NULL;
+        set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
+        set_next_tx_handler(s, NULL, NULL);
         if (t->tx_handler == (span_tx_handler_t *) &(silence_gen)
             ||
             t->tx_handler == (span_tx_handler_t *) &(tone_gen))
@@ -399,27 +422,23 @@
         t->tx_bit_rate = 0;
         /* Impose 75ms minimum on transmitted silence */
         //silence_gen_set(&t->silence_gen, ms_to_samples(75));
-        t->tx_handler = (span_tx_handler_t *) &(silence_gen);
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = NULL;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_CNG:
         t->tx_bit_rate = 0;
         modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
-        t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
-        t->tx_user_data = &t->connect_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
         silence_gen_set(&t->silence_gen, 0);
-        t->next_tx_handler = (span_tx_handler_t *) &(silence_gen);
-        t->next_tx_user_data = &t->silence_gen;
+        set_next_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_CED:
         t->tx_bit_rate = 0;
         modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CED);
-        t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
-        t->tx_user_data = &t->connect_tx;
-        t->next_tx_handler = NULL;
+        set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
+        set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_V21_PREAMBLE:
@@ -429,10 +448,8 @@
         silence_gen_alter(&t->silence_gen, ms_to_samples(75));
         u->buf[u->in].len = 0;
         fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &t->hdlc_tx);
-        t->tx_handler = (span_tx_handler_t *) &(silence_gen);
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &(fsk_tx);
-        t->next_tx_user_data = &t->v21_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_V27TER_2400_TRAINING:
@@ -450,10 +467,8 @@
         silence_gen_alter(&t->silence_gen, ms_to_samples(75));
         v27ter_tx_restart(&t->v27ter_tx, t->tx_bit_rate, t->use_tep);
         v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
-        t->tx_handler = (span_tx_handler_t *) &(silence_gen);
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &(v27ter_tx);
-        t->next_tx_user_data = &t->v27ter_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_V29_7200_TRAINING:
@@ -471,10 +486,8 @@
         silence_gen_alter(&t->silence_gen, ms_to_samples(75));
         v29_tx_restart(&t->v29_tx, t->tx_bit_rate, t->use_tep);
         v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
-        t->tx_handler = (span_tx_handler_t *) &(silence_gen);
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &(v29_tx);
-        t->next_tx_user_data = &t->v29_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_V17_7200_SHORT_TRAINING:
@@ -521,10 +534,8 @@
         silence_gen_alter(&t->silence_gen, ms_to_samples(75));
         v17_tx_restart(&t->v17_tx, t->tx_bit_rate, t->use_tep, short_train);
         v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
-        t->tx_handler = (span_tx_handler_t *) &(silence_gen);
-        t->tx_user_data = &t->silence_gen;
-        t->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
-        t->next_tx_user_data = &t->v17_tx;
+        set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
+        set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
         set_rx_active(s, TRUE);
         break;
     case T38_IND_V8_ANSAM:
@@ -1575,8 +1586,8 @@
         s->data[s->data_ptr++] = (uint8_t) (s->bit_stream << (8 - s->bit_no));
     }
     t38_core_send_data(&t->t38x.t38, t->t38x.current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, s->data, s->data_ptr, t->t38x.t38.data_end_tx_count);
-    s->out_octets += s->data_ptr;
     s->in_bits += s->bits_absorbed;
+    s->out_octets += s->data_ptr;
     s->data_ptr = 0;
 }
 /*- End of function --------------------------------------------------------*/
@@ -1589,8 +1600,8 @@
     if (s->data_ptr)
     {
         t38_core_send_data(&t->t38x.t38, t->t38x.current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, s->data, s->data_ptr, t->t38x.t38.data_tx_count);
-        s->out_octets += s->data_ptr;
         s->in_bits += s->bits_absorbed;
+        s->out_octets += s->data_ptr;
         s->bits_absorbed = 0;
         s->data_ptr = 0;
     }

Modified: freeswitch/trunk/libs/spandsp/src/t38_terminal.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t38_terminal.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t38_terminal.c	Mon Apr 20 13:33:33 2009
@@ -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.123 2009/02/10 13:06:46 steveu Exp $
+ * $Id: t38_terminal.c,v 1.124 2009/03/13 14:49:56 steveu Exp $
  */
 
 /*! \file */
@@ -527,7 +527,7 @@
 
 static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits)
 {
-    if (s->t38_fe.ms_per_tx_chunk == 0)
+    if (s->t38_fe.ms_per_tx_chunk == 0  ||  s->t38_fe.tx_bit_rate == 0)
         return 0;
     return bits*1000000/s->t38_fe.tx_bit_rate;
 }

Modified: freeswitch/trunk/libs/spandsp/src/t4.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/t4.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/t4.c	Mon Apr 20 13:33:33 2009
@@ -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: t4.c,v 1.128 2009/03/01 11:47:03 steveu Exp $
+ * $Id: t4.c,v 1.130 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*
@@ -91,13 +91,19 @@
 #include "spandsp/private/logging.h"
 #include "spandsp/private/t4.h"
 
+/*! The number of centimetres in one inch */
 #define CM_PER_INCH                 2.54f
 
+/*! The number of EOLs to be sent at the end of a T.4 page */
 #define EOLS_TO_END_T4_TX_PAGE      6
+/*! The number of EOLs to be sent at the end of a T.6 page */
 #define EOLS_TO_END_T6_TX_PAGE      2
 
+/*! The number of EOLs to expect at the end of a T.4 page */
 #define EOLS_TO_END_ANY_RX_PAGE     6
+/*! The number of EOLs to check at the end of a T.4 page */
 #define EOLS_TO_END_T4_RX_PAGE      5
+/*! The number of EOLs to check at the end of a T.6 page */
 #define EOLS_TO_END_T6_RX_PAGE      2
 
 /* Finite state machine state codes */
@@ -134,19 +140,26 @@
 #define STATE_TRACE(...) /**/
 #endif
 
-/* Finite state machine state table entry */
+/*! T.4 finite state machine state table entry */
 typedef struct
 {
-    uint8_t state;          /* See above */
-    uint8_t width;          /* Width of code in bits */
-    int16_t param;          /* Run length in bits */
+    /*! State */
+    uint8_t state;
+    /*! Width of code in bits */
+    uint8_t width;
+    /*! Run length in bits */
+    int16_t param;
 } t4_table_entry_t;
 
+/*! T.4 run length table entry */
 typedef struct
 {
-    uint16_t length;        /* Length of T.4 code, in bits */
-    uint16_t code;          /* T.4 code */
-    int16_t run_length;     /* Run length, in bits */
+    /*! Length of T.4 code, in bits */
+    uint16_t length;
+    /*! T.4 code */
+    uint16_t code;
+    /*! Run length, in bits */
+    int16_t run_length;
 } t4_run_table_entry_t;
 
 #include "t4_states.h"
@@ -302,24 +315,25 @@
         {             -1.00f, -1, -1}
     };
     uint16_t res_unit;
-    uint32_t parm;
+    uint16_t parm16;
+    uint32_t parm32;
     float x_resolution;
     float y_resolution;
     int i;
     t4_tiff_state_t *t;
 
     t = &s->tiff;
-    parm = 0;
-    TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm);
-    if (parm != 1)
+    parm16 = 0;
+    TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16);
+    if (parm16 != 1)
         return -1;
-    parm = 0;
-    TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm);
-    s->image_width = parm;
+    parm32 = 0;
+    TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
+    s->image_width = parm32;
     s->bytes_per_row = (s->image_width + 7)/8;
-    parm = 0;
-    TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm);
-    s->image_length = parm;
+    parm32 = 0;
+    TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32);
+    s->image_length = parm32;
     x_resolution = 0.0f;
     TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
     y_resolution = 0.0f;
@@ -400,20 +414,21 @@
         {             -1.00f, -1, -1}
     };
     uint16_t res_unit;
-    uint32_t parm;
+    uint16_t parm16;
+    uint32_t parm32;
     float x_resolution;
     float y_resolution;
     int i;
     t4_tiff_state_t *t;
 
     t = &s->tiff;
-    parm = 0;
-    TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm);
-    if (parm != 1)
+    parm16 = 0;
+    TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16);
+    if (parm16 != 1)
         return -1;
-    parm = 0;
-    TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm);
-    if (s->image_width != (int) parm)
+    parm32 = 0;
+    TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
+    if (s->image_width != (int) parm32)
         return 1;
     x_resolution = 0.0f;
     TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);

Modified: freeswitch/trunk/libs/spandsp/src/tone_detect.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/tone_detect.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/tone_detect.c	Mon Apr 20 13:33:33 2009
@@ -22,10 +22,10 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: tone_detect.c,v 1.51 2009/02/10 13:06:47 steveu Exp $
+ * $Id: tone_detect.c,v 1.53 2009/04/12 09:12:10 steveu Exp $
  */
  
-/*! \file tone_detect.h */
+/*! \file */
 
 #if defined(HAVE_CONFIG_H)
 #include "config.h"

Modified: freeswitch/trunk/libs/spandsp/src/tone_generate.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/tone_generate.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/tone_generate.c	Mon Apr 20 13:33:33 2009
@@ -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: tone_generate.c,v 1.50 2009/02/10 13:06:47 steveu Exp $
+ * $Id: tone_generate.c,v 1.52 2009/04/12 09:12:10 steveu Exp $
  */
 
 /*! \file */

Modified: freeswitch/trunk/libs/spandsp/src/v17rx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v17rx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v17rx.c	Mon Apr 20 13:33:33 2009
@@ -1,3 +1,4 @@
+#define IAXMODEM_STUFF
 /*
  * SpanDSP - a series of DSP components for telephony
  *
@@ -22,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: v17rx.c,v 1.133 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v17rx.c,v 1.145 2009/04/20 16:36:36 steveu Exp $
  */
 
 /*! \file */
@@ -71,21 +72,33 @@
 #include "v17rx_floating_rrc.h"
 #endif
 
+/*! The nominal frequency of the carrier, in Hertz */
 #define CARRIER_NOMINAL_FREQ            1800.0f
+/*! The nominal baud or symbol rate */
 #define BAUD_RATE                       2400
+/*! The adaption rate coefficient for the equalizer during initial training */
 #define EQUALIZER_DELTA                 0.21f
+/*! The adaption rate coefficient for the equalizer during continuous fine tuning */
 #define EQUALIZER_SLOW_ADAPT_RATIO      0.1f
 
 /* Segments of the training sequence */
+/*! The length of training segment 1, in symbols */
 #define V17_TRAINING_SEG_1_LEN          256
+/*! The length of training segment 2 in long training mode, in symbols */
 #define V17_TRAINING_SEG_2_LEN          2976
+/*! The length of training segment 2 in short training mode, in symbols */
 #define V17_TRAINING_SHORT_SEG_2_LEN    38
+/*! The length of training segment 3, in symbols */
 #define V17_TRAINING_SEG_3_LEN          64
+/*! The length of training segment 4A, in symbols */
 #define V17_TRAINING_SEG_4A_LEN         15
+/*! The length of training segment 4, in symbols */
 #define V17_TRAINING_SEG_4_LEN          48
 
+/*! The 16 bit pattern used in the bridge section of the training sequence */
 #define V17_BRIDGE_WORD                 0x8880
 
+/*! The length of the equalizer buffer */
 #define V17_EQUALIZER_LEN    (V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN)
 
 enum
@@ -106,13 +119,25 @@
 };
 
 /* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
-#define SYNC_LOW_BAND_EDGE_COEFF_0       1.764193f    /* 2*alpha*cos(low_edge) */
-#define SYNC_LOW_BAND_EDGE_COEFF_1      -0.980100f    /* -alpha^2 */
-#define SYNC_HIGH_BAND_EDGE_COEFF_0     -1.400072f    /* 2*alpha*cos(high_edge) */
-#define SYNC_HIGH_BAND_EDGE_COEFF_1     -0.980100f    /* -alpha^2 */
-#define SYNC_CROSS_CORR_COEFF_A         -0.932131f    /* -alpha^2*sin(freq_diff) */
-#define SYNC_CROSS_CORR_COEFF_B          0.700036f    /* alpha*sin(high_edge) */
-#define SYNC_CROSS_CORR_COEFF_C         -0.449451f    /* -alpha*sin(low_edge) */
+/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
+/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
+#if defined(SPANDSP_USE_FIXED_POINTx)
+#define SYNC_LOW_BAND_EDGE_COEFF_0      ((int)(FP_FACTOR* 1.764193f))   /* 2*alpha*cos(low_edge) */
+#define SYNC_LOW_BAND_EDGE_COEFF_1      ((int)(FP_FACTOR*-0.980100f))   /* -alpha^2 */
+#define SYNC_HIGH_BAND_EDGE_COEFF_0     ((int)(FP_FACTOR*-1.400072f))   /* 2*alpha*cos(high_edge) */
+#define SYNC_HIGH_BAND_EDGE_COEFF_1     ((int)(FP_FACTOR*-0.980100f))   /* -alpha^2 */
+#define SYNC_CROSS_CORR_COEFF_A         ((int)(FP_FACTOR*-0.932131f))   /* -alpha^2*sin(freq_diff) */
+#define SYNC_CROSS_CORR_COEFF_B         ((int)(FP_FACTOR* 0.700036f))   /* alpha*sin(high_edge) */
+#define SYNC_CROSS_CORR_COEFF_C         ((int)(FP_FACTOR*-0.449451f))   /* -alpha*sin(low_edge) */
+#else
+#define SYNC_LOW_BAND_EDGE_COEFF_0       1.764193f                      /* 2*alpha*cos(low_edge) */
+#define SYNC_LOW_BAND_EDGE_COEFF_1      -0.980100f                      /* -alpha^2 */
+#define SYNC_HIGH_BAND_EDGE_COEFF_0     -1.400072f                      /* 2*alpha*cos(high_edge) */
+#define SYNC_HIGH_BAND_EDGE_COEFF_1     -0.980100f                      /* -alpha^2 */
+#define SYNC_CROSS_CORR_COEFF_A         -0.932131f                      /* -alpha^2*sin(freq_diff) */
+#define SYNC_CROSS_CORR_COEFF_B          0.700036f                      /* alpha*sin(high_edge) */
+#define SYNC_CROSS_CORR_COEFF_C         -0.449451f                      /* -alpha*sin(low_edge) */
+#endif
 
 #if defined(SPANDSP_USE_FIXED_POINTx)
 static const int constellation_spacing[4] =
@@ -146,7 +171,7 @@
 
 SPAN_DECLARE(float) v17_rx_signal_power(v17_rx_state_t *s)
 {
-    return power_meter_current_dbm0(&s->power);
+    return power_meter_current_dbm0(&s->power) + 3.98f;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -504,11 +529,40 @@
 static __inline__ void symbol_sync(v17_rx_state_t *s)
 {
     int i;
+#if defined(SPANDSP_USE_FIXED_POINTx)
+    int32_t v;
+    int32_t p;
+#else
     float v;
     float p;
+#endif
 
     /* This routine adapts the position of the half baud samples entering the equalizer. */
 
+#if defined(SPANDSP_USE_FIXED_POINTx)
+    /* TODO: The scalings used here need more thorough evaluation, to see if overflows are possible. */
+    /* Cross correlate */
+    v = (((s->symbol_sync_low[1] >> 5)*(s->symbol_sync_high[1] >> 4)) >> 15)*SYNC_CROSS_CORR_COEFF_A
+      + (((s->symbol_sync_low[0] >> 5)*(s->symbol_sync_high[1] >> 4)) >> 15)*SYNC_CROSS_CORR_COEFF_B
+      + (((s->symbol_sync_low[1] >> 5)*(s->symbol_sync_high[0] >> 4)) >> 15)*SYNC_CROSS_CORR_COEFF_C;
+    /* Filter away any DC component */
+    p = v - s->symbol_sync_dc_filter[1];
+    s->symbol_sync_dc_filter[1] = s->symbol_sync_dc_filter[0];
+    s->symbol_sync_dc_filter[0] = v;
+    /* A little integration will now filter away much of the noise */
+    s->baud_phase -= p;
+    if (abs(s->baud_phase) > 100*FP_FACTOR)
+    {
+        if (s->baud_phase > 0)
+            i = (s->baud_phase > 1000*FP_FACTOR)  ?  5  :  1;
+        else
+            i = (s->baud_phase < -1000*FP_FACTOR)  ?  -5  :  -1;
+
+        //printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
+        s->eq_put_step += i;
+        s->total_baud_timing_correction += i;
+    }
+#else
     /* Cross correlate */
     v = s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_A
       + s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_B
@@ -532,6 +586,7 @@
         s->eq_put_step += i;
         s->total_baud_timing_correction += i;
     }
+#endif
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -589,11 +644,7 @@
     case TRAINING_STAGE_SYMBOL_ACQUISITION:
         /* Allow time for the symbol synchronisation to settle the symbol timing. */
         target = &zero;
-#if defined(IAXMODEM_STUFF)
         if (++s->training_count >= 100)
-#else
-        if (++s->training_count >= 50)
-#endif
         {
             /* Record the current phase angle */
             s->angles[0] =
@@ -723,8 +774,9 @@
             s->carrier_phase += (angle - 219937506);
 
             /* We have just seen the first symbol of the scrambled sequence, so skip it. */
-            descramble(s, 1);
-            descramble(s, 1);
+            bit = descramble(s, 1);
+            bit = (bit << 1) | descramble(s, 1);
+            target = &cdba[bit];
             s->training_count = 1;
             s->training_stage = TRAINING_STAGE_COARSE_TRAIN_ON_CDBA;
             report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
@@ -826,7 +878,6 @@
         }
         break;
     case TRAINING_STAGE_SHORT_WAIT_FOR_CDBA:
-        target = &cdba[(s->training_count & 1) + 2];
         /* Look for the initial ABAB sequence to display a phase reversal, which will
            signal the start of the scrambled CDBA segment */
         angle = arctan2(z.im, z.re);
@@ -835,13 +886,15 @@
         {
             /* We seem to have a phase reversal */
             /* We have just seen the first symbol of the scrambled sequence, so skip it. */
-            descramble(s, 1);
-            descramble(s, 1);
+            bit = descramble(s, 1);
+            bit = (bit << 1) | descramble(s, 1);
+            target = &cdba[bit];
             s->training_count = 1;
             s->training_error = 0.0f;
             s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
             break;
         }
+        target = &cdba[(s->training_count & 1) + 2];
         track_carrier(s, &z, target);
         if (++s->training_count > V17_TRAINING_SEG_1_LEN)
         {
@@ -984,7 +1037,7 @@
            We need to measure the power with the DC blocked, but not using
            a slow to respond DC blocker. Use the most elementary HPF. */
         x = amp[i] >> 1;
-        /* There could be oveflow here, but it isn't a problem in practice */
+        /* There could be overflow here, but it isn't a problem in practice */
         diff = x - s->last_sample;
         power = power_meter_update(&(s->power), diff);
 #if defined(IAXMODEM_STUFF)
@@ -1111,6 +1164,34 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
+{
+    int i;
+
+    /* We want to sustain the current state (i.e carrier on<->carrier off), and
+       try to sustain the carrier phase. We should probably push the filters, as well */
+    span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
+    if (!s->signal_present)
+        return 0;
+    if (s->training_stage == TRAINING_STAGE_PARKED)
+        return 0;
+    for (i = 0;  i < len;  i++)
+    {
+#if defined(SPANDSP_USE_FIXED_POINT)
+        dds_advance(&s->carrier_phase, s->carrier_phase_rate);
+#else
+        dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
+#endif
+        /* Advance the symbol phase the appropriate amount */
+        s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
+        if (s->eq_put_step <= 0)
+            s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
+        /* TODO: Should we rotate any buffers */
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(void) v17_rx_set_put_bit(v17_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
 {
     s->put_bit = put_bit;

Modified: freeswitch/trunk/libs/spandsp/src/v17tx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v17tx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v17tx.c	Mon Apr 20 13:33:33 2009
@@ -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: v17tx.c,v 1.71 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v17tx.c,v 1.72 2009/04/12 04:20:01 steveu Exp $
  */
 
 /*! \file */
@@ -69,21 +69,31 @@
 #include "v17tx_floating_rrc.h"
 #endif
 
+/*! The nominal frequency of the carrier, in Hertz */
 #define CARRIER_NOMINAL_FREQ        1800.0f
 
 /* Segments of the training sequence */
+/*! The start of the optional TEP, that may preceed the actual training, in symbols */
 #define V17_TRAINING_SEG_TEP_A      0
+/*! The mid point of the optional TEP, that may preceed the actual training, in symbols */
 #define V17_TRAINING_SEG_TEP_B      (V17_TRAINING_SEG_TEP_A + 480)
+/*! The start of training segment 1, in symbols */
 #define V17_TRAINING_SEG_1          (V17_TRAINING_SEG_TEP_B + 48)
+/*! The start of training segment 2, in symbols */
 #define V17_TRAINING_SEG_2          (V17_TRAINING_SEG_1 + 256)
+/*! The start of training segment 3, in symbols */
 #define V17_TRAINING_SEG_3          (V17_TRAINING_SEG_2 + 2976)
+/*! The start of training segment 4, in symbols */
 #define V17_TRAINING_SEG_4          (V17_TRAINING_SEG_3 + 64)
+/*! The start of training segment 4 in short training mode, in symbols */
+#define V17_TRAINING_SHORT_SEG_4    (V17_TRAINING_SEG_2 + 38)
+/*! The end of the training, in symbols */
 #define V17_TRAINING_END            (V17_TRAINING_SEG_4 + 48)
 #define V17_TRAINING_SHUTDOWN_A     (V17_TRAINING_END + 32)
+/*! The end of the shutdown sequence, in symbols */
 #define V17_TRAINING_SHUTDOWN_END   (V17_TRAINING_SHUTDOWN_A + 48)
 
-#define V17_TRAINING_SHORT_SEG_4    (V17_TRAINING_SEG_2 + 38)
-
+/*! The 16 bit pattern used in the bridge section of the training sequence */
 #define V17_BRIDGE_WORD             0x8880
 
 static __inline__ int scramble(v17_tx_state_t *s, int in_bit)

Added: freeswitch/trunk/libs/spandsp/src/v18.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/src/v18.c	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,819 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * v18.c - V.18 text telephony for the deaf.
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2004-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 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: v18.c,v 1.6 2009/04/20 16:36:36 steveu Exp $
+ */
+ 
+/*! \file */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <memory.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/queue.h"
+#include "spandsp/async.h"
+#include "spandsp/complex.h"
+#include "spandsp/dds.h"
+#include "spandsp/tone_detect.h"
+#include "spandsp/tone_generate.h"
+#include "spandsp/super_tone_rx.h"
+#include "spandsp/power_meter.h"
+#include "spandsp/fsk.h"
+#include "spandsp/dtmf.h"
+#include "spandsp/modem_connect_tones.h"
+#include "spandsp/v8.h"
+#include "spandsp/v18.h"
+
+#include "spandsp/private/logging.h"
+#include "spandsp/private/queue.h"
+#include "spandsp/private/tone_generate.h"
+#include "spandsp/private/async.h"
+#include "spandsp/private/fsk.h"
+#include "spandsp/private/dtmf.h"
+#include "spandsp/private/modem_connect_tones.h"
+#include "spandsp/private/v18.h"
+
+#include <stdlib.h>
+
+/*! The baudot code to shift from alpha to digits and symbols */
+#define BAUDOT_FIGURE_SHIFT     0x1B
+/*! The baudot code to shift from digits and symbols to alpha */
+#define BAUDOT_LETTER_SHIFT     0x1F
+
+struct dtmf_to_ascii_s
+{
+    const char *dtmf;
+    char ascii;
+};
+
+static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
+{
+    {"###1", 'C'},
+    {"###2", 'F'},
+    {"###3", 'I'},
+    {"###4", 'L'},
+    {"###5", 'O'},
+    {"###6", 'R'},
+    {"###7", 'U'},
+    {"###8", 'X'},
+    {"###9", ';'},
+    {"###0", '!'},
+    {"##*1", 'A'},
+    {"##*2", 'D'},
+    {"##*3", 'G'},
+    {"##*4", 'J'},
+    {"##*5", 'M'},
+    {"##*6", 'P'},
+    {"##*7", 'S'},
+    {"##*8", 'V'},
+    {"##*9", 'Y'},
+    {"##1", 'B'},
+    {"##2", 'E'},
+    {"##3", 'H'},
+    {"##4", 'K'},
+    {"##5", 'N'},
+    {"##6", 'Q'},
+    {"##7", 'T'},
+    {"##8", 'W'},
+    {"##9", 'Z'},
+    {"##0", ' '},
+    {"#*1", 'æ'}, // (Note 1) 111 1011
+    {"#*2", 'ø'}, // (Note 1) 111 1100
+    {"#*3", 'å'}, // (Note 1) 111 1101
+    {"#*4", 'Æ'}, // (Note 1) 101 1011
+    {"#*5", 'Ø'}, // (Note 1) 101 1100
+    {"#*6", 'Å'}, // (Note 1) 101 1101
+    {"#0", '?'},
+    {"#1", 'c'},
+    {"#2", 'f'},
+    {"#3", 'i'},
+    {"#4", 'l'},
+    {"#5", 'o'},
+    {"#6", 'r'},
+    {"#7", 'u'},
+    {"#8", 'x'},
+    {"#9", '.'},
+    {"*#0", '0'},
+    {"*#1", '1'},
+    {"*#2", '2'},
+    {"*#3", '3'},
+    {"*#4", '4'},
+    {"*#5", '5'},
+    {"*#6", '6'},
+    {"*#7", '7'},
+    {"*#8", '8'},
+    {"*#9", '9'},
+    {"**1", '+'},
+    {"**2", '-'},
+    {"**3", '='},
+    {"**4", ':'},
+    {"**5", '%'},
+    {"**6", '('},
+    {"**7", ')'},
+    {"**8", ','},
+    {"**9", '\n'},
+    {"*0", '\b'},
+    {"*1", 'a'},
+    {"*2", 'd'},
+    {"*3", 'g'},
+    {"*4", 'j'},
+    {"*5", 'm'},
+    {"*6", 'p'},
+    {"*7", 's'},
+    {"*8", 'v'},
+    {"*9", 'y'},
+    {"0", ' '},
+    {"1", 'b'},
+    {"2", 'e'},
+    {"3", 'h'},
+    {"4", 'k'},
+    {"5", 'n'},
+    {"6", 'q'},
+    {"7", 't'},
+    {"8", 'w'},
+    {"9", 'z'},
+    {"", '\0'}
+};
+
+static const char *ascii_to_dtmf[128] =
+{
+    "",         /* NULL */
+    "",         /* SOH */
+    "",         /* STX */
+    "",         /* ETX */
+    "",         /* EOT */
+    "",         /* ENQ */
+    "",         /* ACK */
+    "",         /* BEL */
+    "*0",       /* BACK SPACE */
+    "0",        /* HT >> SPACE */
+    "**9",      /* LF */
+    "**9",      /* VT >> LF */
+    "**9",      /* FF >> LF */
+    "",         /* CR */
+    "",         /* SO */
+    "",         /* SI */
+    "",         /* DLE */
+    "",         /* DC1 */
+    "",         /* DC2 */
+    "",         /* DC3 */
+    "",         /* DC4 */
+    "",         /* NAK */
+    "",         /* SYN */
+    "",         /* ETB */
+    "",         /* CAN */
+    "",         /* EM */
+    "#0",       /* SUB >> ? */
+    "",         /* ESC */
+    "**9",      /* IS4 >> LF */
+    "**9",      /* IS3 >> LF */
+    "**9",      /* IS2 >> LF */
+    "0",        /* IS1 >> SPACE */
+    "0",        /* SPACE */
+    "###0",     /* ! */
+    "",         /* " */
+    "",         /* # */
+    "",         /* $ */
+    "**5",      /* % */
+    "**1",      /* & >> + */
+    "",         /* ’ */
+    "**6",      /* ( */
+    "**7",      /* ) */
+    "#9",       /* _ >> . */
+    "**1",      /* + */
+    "**8",      /* , */
+    "**2",      /* - */
+    "#9",       /* . */
+    "",         /* / */
+    "*#0",      /* 0 */
+    "*#1",      /* 1 */
+    "*#2",      /* 2 */
+    "*#3",      /* 3 */
+    "*#4",      /* 4 */
+    "*#5",      /* 5 */
+    "*#6",      /* 6 */
+    "*#7",      /* 7 */
+    "*#8",      /* 8 */
+    "*#9",      /* 9 */
+    "**4",      /* : */
+    "###9",     /* ; */
+    "**6",      /* < >> ( */
+    "**3",      /* = */
+    "**7",      /* > >> ) */
+    "#0",       /* ? */
+    "###8",     /* @ >> X */
+    "##*1",     /* A */
+    "##1",      /* B */
+    "###1",     /* C */
+    "##*2",     /* D */
+    "##2",      /* E */
+    "###2",     /* F */
+    "##*3",     /* G */
+    "##3",      /* H */
+    "###3",     /* I */
+    "##*4",     /* J */
+    "##4",      /* K */
+    "###4",     /* L */
+    "##*5",     /* M */
+    "##5",      /* N */
+    "###5",     /* O */
+    "##*6",     /* P */
+    "##6",      /* Q */
+    "###6",     /* R */
+    "##*7",     /* S */
+    "##7",      /* T */
+    "###7",     /* U */
+    "##*8",     /* V */
+    "##8",      /* W */
+    "###8",     /* X */
+    "##*9",     /* Y */
+    "##9",      /* Z */
+    "#*4",      /* Æ (National code) */
+    "#*5",      /* Ø (National code) */
+    "#*6",      /* Å (National code) */
+    "",         /* ^ */
+    "0",        /* _ >> SPACE */
+    "",         /* ’ */
+    "*1",       /* a */
+    "1",        /* b */
+    "#1",       /* c */
+    "*2",       /* d */
+    "2",        /* e */
+    "#2",       /* f */
+    "*3",       /* g */
+    "3",        /* h */
+    "#3",       /* i */
+    "*4",       /* j */
+    "4",        /* k */
+    "#4",       /* l */
+    "*5",       /* m */
+    "5",        /* n */
+    "#5",       /* o */
+    "*6",       /* p */
+    "6",        /* q */
+    "#6",       /* r */
+    "*7",       /* s */
+    "7",        /* t */
+    "#7",       /* u */
+    "*8",       /* v */
+    "8",        /* w */
+    "#8",       /* x */
+    "*9",       /* y */
+    "9",        /* z */
+    "#*1",      /* æ (National code) */
+    "#*2",      /* ø (National code) */
+    "#*3",      /* å (National code) */
+    "0",        /* ~ >> SPACE */
+    "*0"        /* DEL >> BACK SPACE */
+};
+
+static int cmp(const void *s, const void *t)
+{
+    const char *ss;
+    struct dtmf_to_ascii_s *tt;
+
+    ss = (const char *) s;
+    tt = (struct dtmf_to_ascii_s *) t;
+    return strncmp(ss, tt->dtmf, strlen(tt->dtmf));
+}
+
+SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
+{
+    const char *t;
+    char *u;
+    const char *v;
+    
+    t = msg;
+    u = dtmf;
+    while (*t)
+    {
+        v = ascii_to_dtmf[*t & 0x7F];
+        while (*v)
+            *u++ = *v++;
+        t++;
+    }
+    *u = '\0';
+
+    return u - dtmf;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[])
+{
+    int entries;
+    const char *t;
+    char *u;
+    struct dtmf_to_ascii_s *ss;
+
+    entries = sizeof(dtmf_to_ascii)/sizeof(dtmf_to_ascii[0]) - 1;
+    t = dtmf;
+    u = msg;
+    while (*t)
+    {
+        ss = bsearch(t, dtmf_to_ascii, entries, sizeof(dtmf_to_ascii[0]), cmp);
+        if (ss)
+        {
+            t += strlen(ss->dtmf);
+            *u++ = ss->ascii;
+        }
+        else
+        {
+            /* Can't match the code. Let's assume this is a code we just don't know, and skip over it */
+            while (*t == '#'  ||  *t == '*')
+                t++;
+            if (*t)
+                t++;
+        }
+    }
+    *u = '\0';
+    return u - msg;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
+{
+    static const uint8_t conv[128] =
+    {
+        0x00, /* NUL */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0x42, /* LF */
+        0xFF, /*   */
+        0xFF, /*   */
+        0x48, /* CR */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0xFF, /*   */
+        0x44, /*   */
+        0xFF, /* ! */
+        0xFF, /* " */
+        0x94, /* # */
+        0x89, /* $ */
+        0xFF, /* % */
+        0xFF, /* & */
+        0x85, /* ' */
+        0x8F, /* ( */
+        0x92, /* ) */
+        0x8B, /* * */
+        0x91, /* + */
+        0x8C, /* , */
+        0x83, /* - */
+        0x9C, /* . */
+        0x9D, /* / */
+        0x96, /* 0 */
+        0x97, /* 1 */
+        0x93, /* 2 */
+        0x81, /* 3 */
+        0x8A, /* 4 */
+        0x90, /* 5 */
+        0x95, /* 6 */
+        0x87, /* 7 */
+        0x86, /* 8 */
+        0x98, /* 9 */
+        0x8E, /* : */
+        0xFF, /* ; */
+        0xFF, /* < */
+        0x9E, /* = */
+        0xFF, /* > */
+        0x99, /* ? */
+        0xFF, /* @ */
+        0x03, /* A */
+        0x19, /* B */
+        0x0E, /* C */
+        0x09, /* D */
+        0x01, /* E */
+        0x0D, /* F */
+        0x1A, /* G */
+        0x14, /* H */
+        0x06, /* I */
+        0x0B, /* J */
+        0x0F, /* K */
+        0x12, /* L */
+        0x1C, /* M */
+        0x0C, /* N */
+        0x18, /* O */
+        0x16, /* P */
+        0x17, /* Q */
+        0x0A, /* R */
+        0x05, /* S */
+        0x10, /* T */
+        0x07, /* U */
+        0x1E, /* V */
+        0x13, /* W */
+        0x1D, /* X */
+        0x15, /* Y */
+        0x11, /* Z */
+        0xFF, /* [ */
+        0xFF, /* \ */
+        0xFF, /* ] */
+        0x9B, /* ^ */
+        0xFF, /* _ */
+        0xFF, /* ` */
+        0x03, /* a */
+        0x19, /* b */
+        0x0E, /* c */
+        0x09, /* d */
+        0x01, /* e */
+        0x0D, /* f */
+        0x1A, /* g */
+        0x14, /* h */
+        0x06, /* i */
+        0x0B, /* j */
+        0x0F, /* k */
+        0x12, /* l */
+        0x1C, /* m */
+        0x0C, /* n */
+        0x18, /* o */
+        0x16, /* p */
+        0x17, /* q */
+        0x0A, /* r */
+        0x05, /* s */
+        0x10, /* t */
+        0x07, /* u */
+        0x1E, /* v */
+        0x13, /* w */
+        0x1D, /* x */
+        0x15, /* y */
+        0x11, /* z */
+        0xFF, /* { */
+        0xFF, /* | */
+        0xFF, /* } */
+        0xFF, /* ~ */
+        0xFF, /* DEL */
+    };
+    uint16_t shift;
+
+    ch = conv[ch];
+    if (ch == 0xFF)
+        return 0;
+    if ((ch & 0x40))
+        return ch & 0x1F;
+    if ((ch & 0x80))
+    {
+        if (s->baudot_tx_shift == 1)
+            return ch & 0x1F;
+        s->baudot_tx_shift = 1;
+        shift = BAUDOT_FIGURE_SHIFT;
+    }
+    else
+    {
+        if (s->baudot_tx_shift == 0)
+            return ch & 0x1F;
+        s->baudot_tx_shift = 0;
+        shift = BAUDOT_LETTER_SHIFT;
+    }
+    return (shift << 5) | (ch & 0x1F);
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch)
+{
+    static const uint8_t conv[2][32] =
+    {
+        {"\000E\nA SIU\rDRJNFCKTZLWHYPQOBG^MXV^"},
+        {"\0003\n- '87\r$4*,*:(5+)2#6019?*^./=^"}
+    };
+
+    switch (ch)
+    {
+    case BAUDOT_FIGURE_SHIFT:
+        s->baudot_rx_shift = 1;
+        break;
+    case BAUDOT_LETTER_SHIFT:
+        s->baudot_rx_shift = 0;
+        break;
+    default:
+        return conv[s->baudot_rx_shift][ch];
+    }
+    /* return 0 if we did not produce a character */
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void v18_rx_dtmf(void *user_data, const char digits[], int len)
+{
+    v18_state_t *s;
+
+    s = (v18_state_t *) user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int v18_tdd_get_async_byte(void *user_data)
+{
+    v18_state_t *s;
+    int ch;
+    
+    s = (v18_state_t *) user_data;
+    if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
+    {
+        int space;
+        int cont;
+        space = queue_free_space(&s->queue.queue);
+        cont = queue_contents(&s->queue.queue);
+        return ch;
+    }
+    if (s->tx_signal_on)
+    {
+        /* The FSK should now be switched off. */
+        s->tx_signal_on = FALSE;
+    }
+    return 0x1F;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void v18_tdd_put_async_byte(void *user_data, int byte)
+{
+    v18_state_t *s;
+    uint8_t octet;
+    
+    s = (v18_state_t *) user_data;
+    //printf("Rx byte %x\n", byte);
+    if (byte < 0)
+    {
+        /* Special conditions */
+        span_log(&s->logging, SPAN_LOG_FLOW, "V.18 signal status is %s (%d)\n", signal_status_to_str(byte), byte);
+        switch (byte)
+        {
+        case SIG_STATUS_CARRIER_UP:
+            s->consecutive_ones = 0;
+            s->bit_pos = 0;
+            s->in_progress = 0;
+            s->rx_msg_len = 0;
+            break;
+        case SIG_STATUS_CARRIER_DOWN:
+            if (s->rx_msg_len > 0)
+            {
+                /* Whatever we have to date constitutes the message */
+                s->rx_msg[s->rx_msg_len] = '\0';
+                s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
+                s->rx_msg_len = 0;
+            }
+            break;
+        default:
+            span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put byte value - %d!\n", byte);
+            break;
+        }
+        return;
+    }
+    if ((octet = v18_decode_baudot(s, (uint8_t) (byte & 0x1F))))
+        s->rx_msg[s->rx_msg_len++] = octet;
+    if (s->rx_msg_len >= 256)
+    {
+        s->rx_msg[s->rx_msg_len] = '\0';
+        s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
+        s->rx_msg_len = 0;
+    }
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
+{
+    int len;
+    int lenx;
+
+    len = tone_gen(&(s->alert_tone_gen), amp, max_len);
+    if (s->tx_signal_on)
+    {
+        switch (s->mode)
+        {
+        case V18_MODE_DTMF:
+            if (len < max_len)
+                len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
+            break;
+        default:
+            if (len < max_len)
+            {
+                if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
+                    s->tx_signal_on = FALSE;
+                len += lenx;
+            }
+            break;
+        }
+    }
+    return len;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
+{
+    switch (s->mode)
+    {
+    case V18_MODE_DTMF:
+        /* Apply a message timeout. */
+        s->in_progress -= len;
+        if (s->in_progress <= 0)
+            s->rx_msg_len = 0;
+        dtmf_rx(&(s->dtmfrx), amp, len);
+        break;
+    default:
+        fsk_rx(&(s->fskrx), amp, len);
+        break;
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
+{
+    char buf[256 + 1];
+    int x;
+    int n;
+    int i;
+
+    /* This returns the number of characters that would not fit in the buffer.
+       The buffer will only be loaded if the whole string of digits will fit,
+       in which case zero is returned. */
+    if (len < 0)
+    {
+        if ((len = strlen(msg)) == 0)
+            return 0;
+    }
+    switch (s->mode)
+    {
+    case V18_MODE_5BIT_45:
+    case V18_MODE_5BIT_50:
+        for (i = 0;  i < len;  i++)
+        {
+            n = 0;
+            if ((x = v18_encode_baudot(s, msg[i])))
+            {
+                if ((x & 0x3E0))
+                    buf[n++] = (uint8_t) ((x >> 5) & 0x1F);
+                buf[n++] = (uint8_t) (x & 0x1F);
+                /* TODO: Deal with out of space condition */
+                if (queue_write(&s->queue.queue, (const uint8_t *) buf, n) < 0)
+                    return 0;
+                s->tx_signal_on = TRUE;
+            }
+        }
+        break;
+    case V18_MODE_DTMF:
+        break;
+    }
+    return -1;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s)
+{
+    return &s->logging;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
+                                     int caller,
+                                     int mode,
+                                     put_msg_func_t put_msg,
+                                     void *user_data)
+{
+    if (s == NULL)
+    {
+        if ((s = (v18_state_t *) malloc(sizeof(*s))) == NULL)
+            return NULL;
+    }
+    memset(s, 0, sizeof(*s));
+    s->caller = caller;
+    s->mode = mode;
+    s->put_msg = put_msg;
+    s->user_data = user_data;
+
+    switch (s->mode)
+    {
+    case V18_MODE_5BIT_45:
+        fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
+        async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
+        /* Schedule an explicit shift at the start of baudot transmission */
+        s->baudot_tx_shift = 2;
+        /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
+           ride over the fraction. */
+        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], 7, v18_tdd_put_async_byte, s);
+        s->baudot_rx_shift = 0;
+        break;
+    case V18_MODE_5BIT_50:
+        fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &(s->asynctx));
+        async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
+        /* Schedule an explicit shift at the start of baudot transmission */
+        s->baudot_tx_shift = 2;
+        /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
+           ride over the fraction. */
+        fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT50], 7, v18_tdd_put_async_byte, s);
+        s->baudot_rx_shift = 0;
+        break;
+    case V18_MODE_DTMF:
+        dtmf_tx_init(&(s->dtmftx));
+        dtmf_rx_init(&(s->dtmfrx), v18_rx_dtmf, s);
+        break;
+    case V18_MODE_EDT:
+        break;
+    case V18_MODE_BELL103:
+        break;
+    case V18_MODE_V23VIDEOTEX:
+        break;
+    case V18_MODE_V21TEXTPHONE:
+        break;
+    case V18_MODE_V18TEXTPHONE:
+        break;
+    }
+    queue_init(&s->queue.queue, 128, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC);
+    return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) v18_release(v18_state_t *s)
+{
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) v18_free(v18_state_t *s)
+{
+    free(s);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
+{
+    switch (mode)
+    {
+    case V18_MODE_NONE:
+        return "None";
+    case V18_MODE_5BIT_45:
+        return "Weitbrecht TDD (45.45bps)";
+    case V18_MODE_5BIT_50:
+        return "Weitbrecht TDD (50bps)";
+    case V18_MODE_DTMF:
+        return "DTMF";
+    case V18_MODE_EDT:
+        return "EDT";
+    case V18_MODE_BELL103:
+        return "Bell 103";
+    case V18_MODE_V23VIDEOTEX:
+        return "Videotex";
+    case V18_MODE_V21TEXTPHONE:
+        return "V.21";
+    case V18_MODE_V18TEXTPHONE:
+        return "V.18 text telephone";
+    }
+    return "???";
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/src/v22bis_rx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v22bis_rx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v22bis_rx.c	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v22bis_rx.c,v 1.47 2009/02/03 16:28:40 steveu Exp $
+ * $Id: v22bis_rx.c,v 1.56 2009/04/20 12:26:38 steveu Exp $
  */
 
 /*! \file */
@@ -61,7 +61,7 @@
 #include "spandsp/private/logging.h"
 #include "spandsp/private/v22bis.h"
 
-#if defined(SPANDSP_USE_FIXED_POINT)
+#if defined(SPANDSP_USE_FIXED_POINTx)
 #include "v22bis_rx_1200_floating_rrc.h"
 #include "v22bis_rx_2400_floating_rrc.h"
 #else
@@ -71,7 +71,9 @@
 
 #define ms_to_symbols(t)        (((t)*600)/1000)
 
+/*! The adaption rate coefficient for the equalizer */
 #define EQUALIZER_DELTA         0.25f
+/*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */
 #define PULSESHAPER_COEFF_SETS  12
 
 /*
@@ -102,16 +104,29 @@
 
 enum
 {
-    V22BIS_TRAINING_STAGE_NORMAL_OPERATION,
-    V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION,
-    V22BIS_TRAINING_STAGE_LOG_PHASE,
-    V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES,
-    V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011,
-    V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
-    V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400,
-    V22BIS_TRAINING_STAGE_WAIT_FOR_START_1,
-    V22BIS_TRAINING_STAGE_WAIT_FOR_START_2,
-    V22BIS_TRAINING_STAGE_PARKED
+    V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION,
+    V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION,
+    V22BIS_RX_TRAINING_STAGE_LOG_PHASE,
+    V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES,
+    V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
+    V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200_SUSTAINING,
+    V22BIS_RX_TRAINING_STAGE_WAIT_FOR_START_1,
+    V22BIS_RX_TRAINING_STAGE_WAIT_FOR_START_2,
+    V22BIS_RX_TRAINING_STAGE_PARKED
+};
+
+/* Segments of the training sequence */
+enum
+{
+    V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION = 0,
+    V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE,
+    V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE,
+    V22BIS_TX_TRAINING_STAGE_U11,
+    V22BIS_TX_TRAINING_STAGE_U0011,
+    V22BIS_TX_TRAINING_STAGE_S11,
+    V22BIS_TX_TRAINING_STAGE_TIMED_S11,
+    V22BIS_TX_TRAINING_STAGE_S1111,
+    V22BIS_TX_TRAINING_STAGE_PARKED
 };
 
 static const uint8_t space_map_v22bis[6][6] =
@@ -124,6 +139,19 @@
     {15, 14, 14,  1,  1,  3}
 };
 
+static const uint8_t phase_steps[4] =
+{
+    1, 0, 2, 3
+};
+
+static const uint8_t ones[] =
+{
+    0, 1, 1, 2,
+    1, 2, 2, 3,
+    1, 2, 2, 3,
+    2, 3, 3, 4
+};
+
 SPAN_DECLARE(float) v22bis_rx_carrier_frequency(v22bis_state_t *s)
 {
     return dds_frequencyf(s->rx.carrier_phase_rate);
@@ -138,7 +166,23 @@
 
 SPAN_DECLARE(float) v22bis_rx_signal_power(v22bis_state_t *s)
 {
-    return power_meter_current_dbm0(&s->rx.rx_power);
+    return power_meter_current_dbm0(&s->rx.rx_power) + 6.34f;
+}
+/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(void) v22bis_rx_signal_cutoff(v22bis_state_t *s, float cutoff)
+{
+    s->rx.carrier_on_power = (int32_t) (power_meter_level_dbm0(cutoff + 2.5f)*0.232f);
+    s->rx.carrier_off_power = (int32_t) (power_meter_level_dbm0(cutoff - 2.5f)*0.232f);
+}
+/*- End of function --------------------------------------------------------*/
+
+static void report_status_change(v22bis_state_t *s, int status)
+{
+    if (s->status_handler)
+        s->status_handler(s->status_user_data, status);
+    else if (s->put_bit)
+        s->put_bit(s->user_data, status);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -240,15 +284,14 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-static __inline__ void put_bit(v22bis_state_t *s, int bit)
+static __inline__ int descramble(v22bis_state_t *s, int bit)
 {
     int out_bit;
 
     bit &= 1;
 
     /* Descramble the bit */
-    s->rx.scramble_reg = (s->rx.scramble_reg << 1) | bit;
-    out_bit = (bit ^ (s->rx.scramble_reg >> 15) ^ (s->rx.scramble_reg >> 18)) & 1;
+    out_bit = (bit ^ (s->rx.scramble_reg >> 14) ^ (s->rx.scramble_reg >> 17)) & 1;
     if (s->rx.scrambler_pattern_count >= 64)
     {
         out_bit ^= 1;
@@ -258,23 +301,29 @@
         s->rx.scrambler_pattern_count++;
     else
         s->rx.scrambler_pattern_count = 0;
+    s->rx.scramble_reg = (s->rx.scramble_reg << 1) | bit;
+    return out_bit;
+}
+/*- End of function --------------------------------------------------------*/
 
+static __inline__ void put_bit(v22bis_state_t *s, int bit)
+{
+    int out_bit;
+
+    /* Descramble the bit */
+    out_bit = descramble(s, bit);
     s->put_bit(s->user_data, out_bit);
 }
 /*- End of function --------------------------------------------------------*/
 
 static void decode_baud(v22bis_state_t *s, int nearest)
 {
-    static const uint8_t phase_steps[4] =
-    {
-        1, 0, 2, 3
-    };
     int raw_bits;
 
-    raw_bits = phase_steps[((nearest - s->rx.constellation_state) >> 2) & 3];
+    raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
     /* The first two bits are the quadrant */
-    put_bit(s, raw_bits);
     put_bit(s, raw_bits >> 1);
+    put_bit(s, raw_bits);
     if (s->bit_rate == 2400)
     {
         /* The other two bits are the position within the quadrant */
@@ -285,23 +334,36 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+static int decode_baudx(v22bis_state_t *s, int nearest)
+{
+    int raw_bits;
+    int out_bits;
+
+    raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
+    /* The first two bits are the quadrant */
+    out_bits = descramble(s, raw_bits >> 1);
+    out_bits = (out_bits << 1) | descramble(s, raw_bits);
+    if (s->bit_rate == 2400)
+    {
+        /* The other two bits are the position within the quadrant */
+        out_bits = (out_bits << 1) | descramble(s, nearest >> 1);
+        out_bits = (out_bits << 1) | descramble(s, nearest);
+    }
+    s->rx.constellation_state = nearest;
+    return out_bits;
+}
+/*- End of function --------------------------------------------------------*/
+
 static __inline__ int find_quadrant(const complexf_t *z)
 {
     int b1;
     int b2;
 
-#if 0
-    /* Split along the axes, as follows:
-        1  0
-        2  3
-     */
-    b1 = (z->re <= 0.0f);
-    b2 = (z->im <= 0.0f);
-    return (b2 << 1) | (b1 ^ b2);
-#endif    
     /* Split the space along the two diagonals, as follows:
          \ 1 /
-        2     0
+          \ /
+       2   X   0
+          / \
          / 3 \
      */
     b1 = (z->im > z->re);
@@ -324,6 +386,8 @@
     int re;
     int im;
     int nearest;
+    int bitstream;
+    int raw_bits;
 
     z.re = sample->re;
     z.im = sample->im;
@@ -379,16 +443,15 @@
            when the true symbol boundary is close to a sample boundary. */
         s->rx.eq_put_step += (s->rx.gardner_integrate/16);
         s->rx.total_baud_timing_correction += (s->rx.gardner_integrate/16);
-span_log(&s->logging, SPAN_LOG_FLOW, "Gardner kick %d [total %d]\n", s->rx.gardner_integrate, s->rx.total_baud_timing_correction);
+//span_log(&s->logging, SPAN_LOG_FLOW, "Gardner kick %d [total %d]\n", s->rx.gardner_integrate, s->rx.total_baud_timing_correction);
         if (s->rx.qam_report)
             s->rx.qam_report(s->rx.qam_user_data, NULL, NULL, s->rx.gardner_integrate);
         s->rx.gardner_integrate = 0;
     }
 
     z = equalizer_get(s);
-printf("VVV %15.5f %15.5f\n", z.re, z.im);
 
-span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx.training);
+//span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx.training);
     if (s->rx.sixteen_way_decisions)
     {
         re = (int) (z.re + 3.0f);
@@ -408,153 +471,203 @@
         zz = complex_setf(3.0f/sqrtf(10.0f), -1.0f/sqrtf(10.0f));
         zz = complex_mulf(&z, &zz);
         nearest = (find_quadrant(&zz) << 2) | 0x01;
-        printf("Trackit %15.5f %15.5f     %15.5f %15.5f   %d\n", z.re, z.im, zz.re, zz.im, nearest);
+        printf("Trackit rx %p %15.5f %15.5f     %15.5f %15.5f   %d\n", s, z.re, z.im, zz.re, zz.im, nearest);
     }
 
     switch (s->rx.training)
     {
-    case V22BIS_TRAINING_STAGE_NORMAL_OPERATION:
+    case V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION:
         /* Normal operation. */
         track_carrier(s, &z, &v22bis_constellation[nearest]);
         tune_equalizer(s, &z, &v22bis_constellation[nearest]);
         decode_baud(s, nearest);
         target = &v22bis_constellation[s->rx.constellation_state];
         break;
-    case V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION:
+    case V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION:
         /* Allow time for the Gardner algorithm to settle the symbol timing. */
         target = &z;
         if (++s->rx.training_count >= 40)
         {
+            /* QAM and Gardner only play nicely with heavy damping, so we need to change to
+               a slow rate of symbol timing adaption. However, it must not be so slow that it
+               cannot track the worst case timing error specified in V.22bis. This should be 0.01%,
+               but since we might be off in the opposite direction from the source, the total
+               error could be higher. */
             s->rx.gardner_step = 4;
+            s->rx.detected_unscrambled_zeros = 0;
+            s->rx.detected_unscrambled_ones = 0;
+            s->rx.detected_2400bps_markers = 0;
             if (s->caller)
-            {
-                s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
-            }
+                s->rx.training = V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES;
             else
-            {
-                if (s->bit_rate == 2400)
-                    s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
-                else
-                    s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
-            }
+                s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
             break;
         }
-
-        /* QAM and Gardner only play nicely with heavy damping, so we need to change to
-           a slow rate of symbol timing adaption. However, it must not be so slow that it
-           cannot track the worst case timing error specified in V.22bis. This should be 0.01%,
-           but since we might be off in the opposite direction from the source, the total
-           error could be higher. */
+        /* Once we have pulled in the symbol timing in a coarse way, use finer
+           steps to fine tune the timing. */
         if (s->rx.training_count == 30)
             s->rx.gardner_step = 32;
         break;
-    case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES:
-        /* The answering modem should initially receive unscrambled ones at 1200bps */
+    case V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES:
+        /* Calling modem only */
+        /* The calling modem should initially receive unscrambled ones at 1200bps */
         track_carrier(s, &z, &v22bis_constellation[nearest]);
         target = &z;
-        if (nearest == ((s->rx.constellation_state - 4) & 0x0F))
-            s->detected_unscrambled_ones++;
-        if (nearest == ((s->rx.constellation_state + 4) & 0x0F))
-            s->detected_unscrambled_zeros++;
+        raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
         s->rx.constellation_state = nearest;
-span_log(&s->logging, SPAN_LOG_FLOW, "TWIDDLING THUMBS - %d\n", s->rx.training_count);
-        if (++s->rx.training_count == ms_to_symbols(155 + 456))
+        switch (raw_bits)
         {
-            if (s->detected_unscrambled_ones >= 250  ||  s->detected_unscrambled_zeros >= 250)
-                s->detected_unscrambled_ones_or_zeros = TRUE;
+        case 0:
+            s->rx.detected_unscrambled_zeros++;
+            break;
+        case 3:
+            s->rx.detected_unscrambled_ones++;
+            break;
+        default:
+            s->rx.detected_2400bps_markers++;
+            break;
         }
-        if (s->rx.training_count == ms_to_symbols(155 + 457))
+span_log(&s->logging, SPAN_LOG_FLOW, "TWIDDLING THUMBS - %d %d\n", s->rx.training_count, s->rx.detected_2400bps_markers);
+        if (++s->rx.training_count == ms_to_symbols(155 + 456))
         {
-            /* We should only bother looking for the 2400bps marker if we are allowed to use
-               2400bps */
+            if (s->rx.detected_unscrambled_ones >= ms_to_symbols(456)
+                ||
+                s->rx.detected_unscrambled_zeros >= ms_to_symbols(456))
+            {
+                if (s->bit_rate == 2400)
+                {
+                    /* Try to establish at 2400bps */
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U0011 (S1) (Caller)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
+                    s->tx.training_count = 0;
+                }
+                else
+                {
+                    /* Only try to establish at 1200bps */
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 (Caller)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
+                    s->tx.training_count = 0;
+                }
+            }
+span_log(&s->logging, SPAN_LOG_FLOW, "unscrambled ones = %d, unscrambled zeros = %d, 2400 markers = %d\n", s->rx.detected_unscrambled_ones, s->rx.detected_unscrambled_zeros, s->rx.detected_2400bps_markers);
             s->rx.training_count = 0;
-            if (s->bit_rate == 2400)
-                s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
-            else
-                s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
+            s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
+            s->rx.detected_unscrambled_zeros = 0;
+            s->rx.detected_unscrambled_ones = 0;
+            s->rx.detected_2400bps_markers = 0;
+            s->rx.scrambled_ones_to_date = 0;
         }
         break;
-    case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011:
-s->rx.sixteen_way_decisions = TRUE;
-        /* If we can actually find this it means we can use 2400bps. If we find unscrambled ones, it means we
-           we must use 1200bps. */
+    case V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
         track_carrier(s, &z, &v22bis_constellation[nearest]);
         tune_equalizer(s, &z, &v22bis_constellation[nearest]);
         target = &z;
-        //s->rx.carrier_track_i = 1000.0f;
-        //s->rx.carrier_track_p = 1000000.0f;
-#if 0
-        if (++s->rx.training_count > ms_to_symbols(800))
+        raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
+        switch (raw_bits)
         {
-            s->detected_unscrambled_0011_ending = TRUE;
-            s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
-        }
-#else
-        if (++s->rx.training_count == 1)
-        {
-            s->detected_unscrambled_zeros = nearest;
-            s->detected_unscrambled_ones = 0;
+        case 0:
+            s->rx.detected_unscrambled_zeros++;
+            break;
+        case 3:
+            s->rx.detected_unscrambled_ones++;
+            break;
+        default:
+            s->rx.detected_2400bps_markers++;
+            break;
         }
-        else
+        bitstream = decode_baudx(s, nearest);
+        s->rx.scrambled_ones_to_date += ones[bitstream];
+span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x 0x%02x 0x%X %d %d %d %d %d %d\n", raw_bits, nearest, bitstream, s->rx.scrambled_ones_to_date, s->rx.detected_unscrambled_ones, s->rx.detected_unscrambled_zeros, s->rx.detected_2400bps_markers, s->rx.training_count, s->rx.detected_2400bps_markers);
+        if (s->rx.detected_2400bps_markers  &&  ++s->rx.training_count > ms_to_symbols(270))
         {
-span_log(&s->logging, SPAN_LOG_FLOW, "0x%X 0x%X 0x%X\n", s->detected_unscrambled_zeros, nearest, (s->detected_unscrambled_zeros + nearest) & 0x0F);
-            if ((s->rx.training_count & 1) == 0)
+            if (!s->caller)
             {
-span_log(&s->logging, SPAN_LOG_FLOW, "AAA\n");
-                if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06)
-                    s->detected_unscrambled_ones = 1;
-                else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02)
-                    s->detected_unscrambled_ones = -1;
-                else
+                if (s->bit_rate == 2400  &&  s->rx.detected_2400bps_markers > 20)
                 {
-span_log(&s->logging, SPAN_LOG_FLOW, "AAA 1\n");
-                    if (s->detected_unscrambled_ones > 5  ||  s->detected_unscrambled_ones < -5)
-                        s->detected_unscrambled_0011_ending = TRUE;
-                    else
-                        s->bit_rate = 1200;
-                    s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
+                    /* Try to establish at 2400bps */
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U0011 (S1) (Answerer)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
+                    s->tx.training_count = 0;
                 }
-            }
-            else
-            {
-span_log(&s->logging, SPAN_LOG_FLOW, "BBB\n");
-                if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06)
-                    s->detected_unscrambled_ones = 1;
-                else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02)
-                    s->detected_unscrambled_ones = -1;
                 else
                 {
-span_log(&s->logging, SPAN_LOG_FLOW, "BBB 1\n");
-                    if (s->detected_unscrambled_ones > 5  ||  s->detected_unscrambled_ones < -5)
-                        s->detected_unscrambled_0011_ending = TRUE;
-                    else
-                        s->bit_rate = 1200;
-                    s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
+                    /* We are going to work at 1200bps. */
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ [1200] starting S11 (Answerer)\n");
+                    s->bit_rate = 1200;
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
+                    s->tx.training_count = 0;
                 }
             }
+            s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200_SUSTAINING;
         }
-#endif
         break;
-    case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
+    case V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200_SUSTAINING:
         track_carrier(s, &z, &v22bis_constellation[nearest]);
         tune_equalizer(s, &z, &v22bis_constellation[nearest]);
         target = &z;
-span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x\n", nearest);
-        if (++s->rx.training_count > ms_to_symbols(900))
+        raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
+        switch (raw_bits)
+        {
+        case 0:
+            s->rx.detected_unscrambled_zeros++;
+            break;
+        case 3:
+            s->rx.detected_unscrambled_ones++;
+            break;
+        default:
+            s->rx.detected_2400bps_markers++;
+            break;
+        }
+        bitstream = decode_baudx(s, nearest);
+        s->rx.scrambled_ones_to_date += ones[bitstream];
+span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x 0x%02x 0x%X %d %d %d %d %d sustain\n", raw_bits, nearest, bitstream, s->rx.scrambled_ones_to_date, s->rx.detected_unscrambled_ones, s->rx.detected_unscrambled_zeros, s->rx.detected_2400bps_markers, s->rx.training_count);
+        if (s->rx.detected_2400bps_markers == 20)
+        {
+            /* It looks like we have the S1 (Unscrambled 00 11) section, so 2400bps
+               operation is possible. */
+            s->rx.detected_2400bps_markers++;
+            if (s->bit_rate == 2400)
+            {
+                /* We are allowed to use 2400bps, and the far end is requesting 2400bps. Result: we are going to
+                   work at 2400bps */
+                span_log(&s->logging, SPAN_LOG_FLOW, "+++ [2400] starting U0011 (S1)\n");
+                s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
+                s->tx.training_count = 0;
+            }
+        }
+        if (++s->rx.training_count > ms_to_symbols(270 + 765))
         {
-            s->detected_scrambled_ones_or_zeros_at_1200bps = TRUE;
-            s->rx.training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION;
+            if (s->caller)
+            {
+                if (s->bit_rate == 2400)
+                {
+                    /* We've  continued for a further 756+-10ms. This should have given the other
+                       side enough time to train its equaliser. */
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S1111 (B)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_S1111;
+                    s->tx.training_count = 0;
+                }
+                else
+                {
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (1200)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
+                    s->tx.training_count = 0;
+                    s->tx.current_get_bit = s->get_bit;
+                }
+            }
+            if (s->bit_rate == 2400)
+                span_log(&s->logging, SPAN_LOG_FLOW, "+++ Rx normal operation (2400)\n");
+            else
+                span_log(&s->logging, SPAN_LOG_FLOW, "+++ Rx normal operation (1200)\n");
+            s->rx.training = V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION;
         }
         if (s->bit_rate == 2400  &&  s->rx.training_count == ms_to_symbols(450))
+        {
+            span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting 16 way decisions\n");
             s->rx.sixteen_way_decisions = TRUE;
+        }
         break;
-    case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400:
-        track_carrier(s, &z, &v22bis_constellation[nearest]);
-        tune_equalizer(s, &z, &v22bis_constellation[nearest]);
-        s->rx.sixteen_way_decisions = TRUE;
-        target = &z;
-        break;
-    case V22BIS_TRAINING_STAGE_PARKED:
+    case V22BIS_RX_TRAINING_STAGE_PARKED:
     default:
         /* We failed to train! */
         /* Park here until the carrier drops. */
@@ -590,7 +703,6 @@
 
         /* Calculate the I filter, with an arbitrary phase step, just so we can calculate
            the signal power. */
-        /* TODO: get rid of this */
         if (s->caller)
         {
             ii = rx_pulseshaper_2400_re[6][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
@@ -603,34 +715,34 @@
             for (j = 1;  j < V22BIS_RX_FILTER_STEPS;  j++)
                 ii += rx_pulseshaper_1200_re[6][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
         }
-        power = power_meter_update(&(s->rx.rx_power), (int16_t) (ii/10.0f));
+        power = power_meter_update(&(s->rx.rx_power), (int16_t) ii);
         if (s->rx.signal_present)
         {
-            /* Look for power below -48dBm0 to turn the carrier off */
+            /* Look for power below the carrier off point */
             if (power < s->rx.carrier_off_power)
             {
                 v22bis_rx_restart(s, s->bit_rate);
-                s->put_bit(s->user_data, SIG_STATUS_CARRIER_DOWN);
+                report_status_change(s, SIG_STATUS_CARRIER_DOWN);
                 continue;
             }
         }
         else
         {
-            /* Look for power exceeding -43dBm0 to turn the carrier on */
+            /* Look for power exceeding the carrier on point */
             if (power < s->rx.carrier_on_power)
                 continue;
             s->rx.signal_present = TRUE;
-            s->put_bit(s->user_data, SIG_STATUS_CARRIER_UP);
+            report_status_change(s, SIG_STATUS_CARRIER_UP);
         }
-        if (s->rx.training != V22BIS_TRAINING_STAGE_PARKED)
+        if (s->rx.training != V22BIS_RX_TRAINING_STAGE_PARKED)
         {
             /* Only spend effort processing this data if the modem is not
                parked, after training failure. */
-            z = dds_complexf(&(s->rx.carrier_phase), s->rx.carrier_phase_rate);
-            if (s->rx.training == V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION)
+            z = dds_complexf(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
+            if (s->rx.training == V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION)
             {
                 /* Only AGC during the initial symbol acquisition, and then lock the gain. */
-                s->rx.agc_scaling = 0.018f*3.60f/sqrtf(power);
+                s->rx.agc_scaling = 0.18f*3.60f/sqrtf(power);
             }
             /* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
                will fiddle the step to align this with the symbols. */
@@ -679,6 +791,28 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
+{
+    int i;
+
+    /* We want to sustain the current state (i.e carrier on<->carrier off), and
+       try to sustain the carrier phase. We should probably push the filters, as well */
+    span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
+    if (!s->rx.signal_present)
+        return 0;
+    for (i = 0;  i < len;  i++)
+    {
+#if defined(SPANDSP_USE_FIXED_POINTx)
+        dds_advance(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
+#else
+        dds_advancef(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
+#endif
+    }
+    /* TODO: Advance the symbol phase the appropriate amount */
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(int) v22bis_rx_restart(v22bis_state_t *s, int bit_rate)
 {
     /* If bit_rate is 2400, the real bit rate is negotiated. If bit_rate
@@ -688,15 +822,14 @@
     s->rx.rrc_filter_step = 0;
     s->rx.scramble_reg = 0;
     s->rx.scrambler_pattern_count = 0;
-    s->rx.training = V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION;
+    s->rx.training = V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION;
     s->rx.training_count = 0;
     s->rx.signal_present = FALSE;
 
     s->rx.carrier_phase_rate = dds_phase_ratef((s->caller)  ?  2400.0f  :  1200.0f);
     s->rx.carrier_phase = 0;
     power_meter_init(&(s->rx.rx_power), 5);
-    s->rx.carrier_on_power = power_meter_level_dbm0(-43);
-    s->rx.carrier_off_power = power_meter_level_dbm0(-48);
+    v22bis_rx_signal_cutoff(s, -45.5f);
     s->rx.agc_scaling = 0.0005f*0.025f;
 
     s->rx.constellation_state = 0;
@@ -704,8 +837,9 @@
 
     equalizer_reset(s);
 
-    s->detected_unscrambled_ones = 0;
-    s->detected_unscrambled_zeros = 0;
+    s->rx.detected_unscrambled_ones = 0;
+    s->rx.detected_unscrambled_zeros = 0;
+    s->rx.detected_2400bps_markers = 0;
     s->rx.gardner_integrate = 0;
     s->rx.gardner_step = 256;
     s->rx.baud_phase = 0;

Modified: freeswitch/trunk/libs/spandsp/src/v22bis_tx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v22bis_tx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v22bis_tx.c	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v22bis_tx.c,v 1.51 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v22bis_tx.c,v 1.56 2009/04/17 14:37:52 steveu Exp $
  */
 
 /*! \file */
@@ -61,7 +61,7 @@
 #include "spandsp/private/logging.h"
 #include "spandsp/private/v22bis.h"
 
-#if defined(SPANDSP_USE_FIXED_POINT)
+#if defined(SPANDSP_USE_FIXED_POINTx)
 #include "v22bis_tx_fixed_rrc.h"
 #else
 #include "v22bis_tx_floating_rrc.h"
@@ -243,13 +243,15 @@
 /* Segments of the training sequence */
 enum
 {
-    V22BIS_TRAINING_STAGE_NORMAL_OPERATION = 0,
-    V22BIS_TRAINING_STAGE_INITIAL_SILENCE,
-    V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES,
-    V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011,
-    V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
-    V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400,
-    V22BIS_TRAINING_STAGE_PARKED
+    V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION = 0,
+    V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE,
+    V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE,
+    V22BIS_TX_TRAINING_STAGE_U11,
+    V22BIS_TX_TRAINING_STAGE_U0011,
+    V22BIS_TX_TRAINING_STAGE_S11,
+    V22BIS_TX_TRAINING_STAGE_TIMED_S11,
+    V22BIS_TX_TRAINING_STAGE_S1111,
+    V22BIS_TX_TRAINING_STAGE_PARKED
 };
 
 static const int phase_steps[4] =
@@ -260,19 +262,19 @@
 const complexf_t v22bis_constellation[16] =
 {
     { 1.0f,  1.0f},
-    { 3.0f,  1.0f},
+    { 3.0f,  1.0f},     /* 1200bps 00 */
     { 1.0f,  3.0f},
     { 3.0f,  3.0f},
     {-1.0f,  1.0f},
-    {-1.0f,  3.0f},
+    {-1.0f,  3.0f},     /* 1200bps 01 */
     {-3.0f,  1.0f},
     {-3.0f,  3.0f},
     {-1.0f, -1.0f},
-    {-3.0f, -1.0f},
+    {-3.0f, -1.0f},     /* 1200bps 10 */
     {-1.0f, -3.0f},
     {-3.0f, -3.0f},
     { 1.0f, -1.0f},
-    { 1.0f, -3.0f},
+    { 1.0f, -3.0f},     /* 1200bps 11 */
     { 3.0f, -1.0f},
     { 3.0f, -3.0f}
 };
@@ -287,12 +289,12 @@
 {
     int out_bit;
 
-    out_bit = (bit ^ (s->tx.scramble_reg >> 14) ^ (s->tx.scramble_reg >> 17)) & 1;
     if (s->tx.scrambler_pattern_count >= 64)
     {
-        out_bit ^= 1;
+        bit ^= 1;
         s->tx.scrambler_pattern_count = 0;
     }
+    out_bit = (bit ^ (s->tx.scramble_reg >> 14) ^ (s->tx.scramble_reg >> 17)) & 1;
     if (out_bit == 1)
         s->tx.scrambler_pattern_count++;
     else
@@ -326,159 +328,90 @@
     /* V.22bis training sequence */
     switch (s->tx.training)
     {
-    case V22BIS_TRAINING_STAGE_INITIAL_SILENCE:
-        /* Segment 1: silence */
+    case V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE:
+        /* The answerer waits 75ms, then sends unscrambled ones */
+        if (++s->tx.training_count >= ms_to_symbols(75))
+        {
+            /* Initial 75ms of silence is over */
+            span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U11 1200\n");
+            s->tx.training = V22BIS_TX_TRAINING_STAGE_U11;
+            s->tx.training_count = 0;
+        }
+        /* Fall through */
+    case V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE:
+        /* Silence */
         s->tx.constellation_state = 0;
         z = complex_setf(0.0f, 0.0f);
-        if (s->caller)
-        {
-            /* The caller just waits for a signal from the far end, which should be unscrambled ones */
-            if (s->detected_unscrambled_ones_or_zeros)
-            {
-                if (s->bit_rate == 2400)
-                {
-                    /* Try to establish at 2400bps */
-                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting unscrambled 0011 at 1200 (S1)\n");
-                    s->tx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
-                }
-                else
-                {
-                    /* Only try at 1200bps */
-                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 1200 (A)\n");
-                    s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
-                }
-                s->tx.training_count = 0;
-            }
-        }
-        else
-        {
-            /* The answerer waits 75ms, then sends unscrambled ones */
-            if (++s->tx.training_count >= ms_to_symbols(75))
-            {
-                /* Inital 75ms of silence is over */
-                span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting unscrambled ones at 1200\n");
-                s->tx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
-                s->tx.training_count = 0;
-            }
-        }
         break;
-    case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES:
-        /* Segment 2: Continuous unscrambled ones at 1200bps (i.e. reversals). */
+    case V22BIS_TX_TRAINING_STAGE_U11:
+        /* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */
         /* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3]) & 3;
         z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
-        if (s->bit_rate == 2400  &&  s->detected_unscrambled_0011_ending)
-        {
-            /* We are allowed to use 2400bps, and the far end is requesting 2400bps. Result: we are going to
-               work at 2400bps */
-            span_log(&s->logging, SPAN_LOG_FLOW, "+++ [2400] starting unscrambled 0011 at 1200 (S1)\n");
-            s->tx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
-            s->tx.training_count = 0;
-            break;
-        }
-        if (s->detected_scrambled_ones_or_zeros_at_1200bps)
-        {
-            /* We are going to work at 1200bps. */
-            span_log(&s->logging, SPAN_LOG_FLOW, "+++ [1200] starting scrambled ones at 1200 (B)\n");
-            s->bit_rate = 1200;
-            s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
-            s->tx.training_count = 0;
-            break;
-        }
         break;
-    case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011:
-        /* Segment 3: Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
+    case V22BIS_TX_TRAINING_STAGE_U0011:
+        /* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
            the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this
            timed burst, we unconditionally change to sending scrambled ones at 1200bps. */
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[(s->tx.training_count & 1)  ?  3  :  0]) & 3;
-span_log(&s->logging, SPAN_LOG_FLOW, "U0011 Tx 0x%02x\n", s->tx.constellation_state);
         z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
         if (++s->tx.training_count >= ms_to_symbols(100))
         {
-            span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 1200 (C)\n");
-            s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
+            span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 after U0011\n");
+            if (s->caller)
+                s->tx.training = V22BIS_TX_TRAINING_STAGE_S11;
+            else
+                s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
             s->tx.training_count = 0;
         }
         break;
-    case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
-        /* Segment 4: Scrambled ones at 1200bps. */
-        bits = scramble(s, 1);
-        bits = (bits << 1) | scramble(s, 1);
-        s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
-        z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
-        if (s->caller)
+    case V22BIS_TX_TRAINING_STAGE_TIMED_S11:
+        /* A timed period of scrambled ones at 1200bps. */
+        if (!s->caller)
         {
-            if (s->detected_unscrambled_0011_ending)
-            {
-                /* Continue for a further 600+-10ms */
-                if (++s->tx.training_count >= ms_to_symbols(600))
-                {
-                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (A)\n");
-                    s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
-                    s->tx.training_count = 0;
-                }
-            }
-            else if (s->detected_scrambled_ones_or_zeros_at_1200bps)
+            if (++s->tx.training_count >= ms_to_symbols(756))
             {
                 if (s->bit_rate == 2400)
                 {
-                    /* Continue for a further 756+-10ms */
-                    if (++s->tx.training_count >= ms_to_symbols(756))
-                    {
-                        span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (B)\n");
-                        s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
-                        s->tx.training_count = 0;
-                    }
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S1111 (C)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_S1111;
+                    s->tx.training_count = 0;
                 }
                 else
                 {
-                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
-                    s->tx.training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION;
+                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (1200)\n");
+                    s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
                     s->tx.training_count = 0;
                     s->tx.current_get_bit = s->get_bit;
                 }
             }
         }
-        else
-        {
-            if (s->bit_rate == 2400)
-            {
-                if (++s->tx.training_count >= ms_to_symbols(500))
-                {
-                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (C)\n");
-                    s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
-                    s->tx.training_count = 0;
-                }
-            }
-            else
-            {
-                if (++s->tx.training_count >= ms_to_symbols(756))
-                {
-                    span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
-                    s->tx.training = 0;
-                    s->tx.training_count = 0;
-                }
-            }
-        }
+        /* Fall through */
+    case V22BIS_TX_TRAINING_STAGE_S11:
+        /* Scrambled ones at 1200bps. */
+        bits = scramble(s, 1);
+        bits = (bits << 1) | scramble(s, 1);
+        s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
+        z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
         break;
-    case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400:
-        /* Segment 4: Scrambled ones at 2400bps. */
+    case V22BIS_TX_TRAINING_STAGE_S1111:
+        /* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
         bits = scramble(s, 1);
         bits = (bits << 1) | scramble(s, 1);
         s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
         bits = scramble(s, 1);
         bits = (bits << 1) | scramble(s, 1);
-        z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
+        z = v22bis_constellation[(s->tx.constellation_state << 2) | bits];
         if (++s->tx.training_count >= ms_to_symbols(200))
         {
             /* We have completed training. Now handle some real work. */
-            span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
-            s->tx.training = 0;
+            span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (2400)\n");
+            s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
             s->tx.training_count = 0;
             s->tx.current_get_bit = s->get_bit;
         }
         break;
-    case V22BIS_TRAINING_STAGE_PARKED:
+    case V22BIS_TX_TRAINING_STAGE_PARKED:
     default:
         z = complex_setf(0.0f, 0.0f);
         break;
@@ -569,8 +502,26 @@
 {
     float l;
 
-    l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
-    s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+    if (s->tx.guard_phase_rate == dds_phase_ratef(550.0f))
+    {
+        l = 1.6f*powf(10.0f, (power - 1.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+        l = powf(10.0f, (power - 1.0f - 3.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.guard_level = l*32768.0f;
+    }
+    else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.0f))
+    {
+        l = 1.6f*powf(10.0f, (power - 1.0f - 1.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+        l = powf(10.0f, (power - 1.0f - 6.0f - DBM0_MAX_POWER)/20.0f);
+        s->tx.guard_level = l*32768.0f;
+    }
+    else
+    {
+        l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
+        s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
+        s->tx.guard_level = 0;
+    }
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -581,7 +532,10 @@
     s->tx.rrc_filter_step = 0;
     s->tx.scramble_reg = 0;
     s->tx.scrambler_pattern_count = 0;
-    s->tx.training = V22BIS_TRAINING_STAGE_INITIAL_SILENCE;
+    if (s->caller)
+        s->tx.training = V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE;
+    else
+        s->tx.training = V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE;
     s->tx.training_count = 0;
     s->tx.carrier_phase = 0;
     s->tx.guard_phase = 0;
@@ -607,6 +561,13 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(void) v22bis_set_modem_status_handler(v22bis_state_t *s, modem_tx_status_func_t handler, void *user_data)
+{
+    s->status_handler = handler;
+    s->status_user_data = user_data;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(logging_state_t *) v22bis_get_logging_state(v22bis_state_t *s)
 {
     return &s->logging;
@@ -653,21 +614,20 @@
     else
     {
         s->tx.carrier_phase_rate = dds_phase_ratef(2400.0f);
-        if (guard)
+        switch (guard)
         {
-            if (guard == 1)
-            {
-                s->tx.guard_phase_rate = dds_phase_ratef(550.0f);
-                s->tx.guard_level = 1500.0f;
-            }
-            else
-            {
-                s->tx.guard_phase_rate = dds_phase_ratef(1800.0f);
-                s->tx.guard_level = 1000.0f;
-            }
+        case V22BIS_GUARD_TONE_550HZ:
+            s->tx.guard_phase_rate = dds_phase_ratef(550.0f);
+            break;
+        case V22BIS_GUARD_TONE_1800HZ:
+            s->tx.guard_phase_rate = dds_phase_ratef(1800.0f);
+            break;
+        default:
+            s->tx.guard_phase_rate = 0;
+            break;
         }
     }
-    v22bis_tx_power(s, -10.0f);
+    v22bis_tx_power(s, -14.0f);
     v22bis_restart(s, s->bit_rate);
     return s;
 }

Modified: freeswitch/trunk/libs/spandsp/src/v27ter_rx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v27ter_rx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v27ter_rx.c	Mon Apr 20 13:33:33 2009
@@ -1,3 +1,4 @@
+#define IAXMODEM_STUFF
 /*
  * SpanDSP - a series of DSP components for telephony
  *
@@ -22,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: v27ter_rx.c,v 1.117 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v27ter_rx.c,v 1.125 2009/04/20 16:36:36 steveu Exp $
  */
 
 /*! \file */
@@ -74,7 +75,13 @@
    signal to a static constellation, even though dealing with differences is all
    that is necessary. */
 
+/*! The nominal frequency of the carrier, in Hertz */
 #define CARRIER_NOMINAL_FREQ            1800.0f
+/*! The nominal baud or symbol rate in 2400bps mode */
+#define BAUD_RATE_2400                  1200
+/*! The nominal baud or symbol rate in 4800bps mode */
+#define BAUD_RATE_4800                  1600
+/*! The adaption rate coefficient for the equalizer */
 #define EQUALIZER_DELTA                 0.25f
 
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -85,10 +92,14 @@
 /* Segments of the training sequence */
 /* V.27ter defines a long and a short sequence. FAX doesn't use the
    short sequence, so it is not implemented here. */
+/*! The length of training segment 3, in symbols */
 #define V27TER_TRAINING_SEG_3_LEN       50
+/*! The length of training segment 5, in symbols */
 #define V27TER_TRAINING_SEG_5_LEN       1074
+/*! The length of training segment 6, in symbols */
 #define V27TER_TRAINING_SEG_6_LEN       8
 
+/*! The length of the equalizer buffer */
 #define V27TER_EQUALIZER_LEN    (V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN)
 
 enum
@@ -145,7 +156,7 @@
 
 SPAN_DECLARE(float) v27ter_rx_signal_power(v27ter_rx_state_t *s)
 {
-    return power_meter_current_dbm0(&s->power);
+    return power_meter_current_dbm0(&s->power) + 3.98f;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -630,6 +641,7 @@
             s->training_bc ^= descramble(s, 1);
             descramble(s, 1);
             descramble(s, 1);
+            s->constellation_state = abab_pos[s->training_bc];
             s->training_count = 1;
             s->training_stage = TRAINING_STAGE_TRAIN_ON_ABAB;
             report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
@@ -772,7 +784,7 @@
                We need to measure the power with the DC blocked, but not using
                a slow to respond DC blocker. Use the most elementary HPF. */
             x = amp[i] >> 1;
-            /* There could be oveflow here, but it isn't a problem in practice */
+            /* There could be overflow here, but it isn't a problem in practice */
             diff = x - s->last_sample;
             power = power_meter_update(&(s->power), diff);
 #if defined(IAXMODEM_STUFF)
@@ -894,7 +906,7 @@
                We need to measure the power with the DC blocked, but not using
                a slow to respond DC blocker. Use the most elementary HPF. */
             x = amp[i] >> 1;
-            /* There could be oveflow here, but it isn't a problem in practice */
+            /* There could be overflow here, but it isn't a problem in practice */
             diff = x - s->last_sample;
             power = power_meter_update(&(s->power), diff);
 #if defined(IAXMODEM_STUFF)
@@ -1009,6 +1021,41 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len)
+{
+    int i;
+
+    /* We want to sustain the current state (i.e carrier on<->carrier off), and
+       try to sustain the carrier phase. We should probably push the filters, as well */
+    span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
+    if (!s->signal_present)
+        return 0;
+    if (s->training_stage == TRAINING_STAGE_PARKED)
+        return 0;
+    for (i = 0;  i < len;  i++)
+    {
+#if defined(SPANDSP_USE_FIXED_POINT)
+        dds_advance(&s->carrier_phase, s->carrier_phase_rate);
+#else
+        dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
+#endif
+        /* Advance the symbol phase the appropriate amount */
+        if (s->bit_rate == 4800)
+        {
+            if ((s->eq_put_step -= RX_PULSESHAPER_4800_COEFF_SETS) <= 0)
+                s->eq_put_step += RX_PULSESHAPER_4800_COEFF_SETS*5/2;
+        }
+        else
+        {
+            if ((s->eq_put_step -= RX_PULSESHAPER_2400_COEFF_SETS) <= 0)
+                s->eq_put_step += RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
+        }
+        /* TODO: Should we rotate any buffers */
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(void) v27ter_rx_set_put_bit(v27ter_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
 {
     s->put_bit = put_bit;

Modified: freeswitch/trunk/libs/spandsp/src/v27ter_tx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v27ter_tx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v27ter_tx.c	Mon Apr 20 13:33:33 2009
@@ -22,7 +22,7 @@
  * License along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: v27ter_tx.c,v 1.73 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v27ter_tx.c,v 1.74 2009/04/12 04:20:01 steveu Exp $
  */
 
 /*! \file */
@@ -66,17 +66,25 @@
 #include "v27ter_tx_2400_floating_rrc.h"
 #endif
 
+/*! The nominal frequency of the carrier, in Hertz */
 #define CARRIER_NOMINAL_FREQ            1800.0f
 
 /* Segments of the training sequence */
 /* V.27ter defines a long and a short sequence. FAX doesn't use the
    short sequence, so it is not implemented here. */
+/*! The start of training segment 1, in symbols */
 #define V27TER_TRAINING_SEG_1           0
+/*! The start of training segment 2, in symbols */
 #define V27TER_TRAINING_SEG_2           (V27TER_TRAINING_SEG_1 + 320)
+/*! The start of training segment 3, in symbols */
 #define V27TER_TRAINING_SEG_3           (V27TER_TRAINING_SEG_2 + 32)
+/*! The start of training segment 4, in symbols */
 #define V27TER_TRAINING_SEG_4           (V27TER_TRAINING_SEG_3 + 50)
+/*! The start of training segment 5, in symbols */
 #define V27TER_TRAINING_SEG_5           (V27TER_TRAINING_SEG_4 + 1074)
+/*! The end of the training, in symbols */
 #define V27TER_TRAINING_END             (V27TER_TRAINING_SEG_5 + 8)
+/*! The end of the shutdown sequence, in symbols */
 #define V27TER_TRAINING_SHUTDOWN_END    (V27TER_TRAINING_END + 32)
 
 static int fake_get_bit(void *user_data)

Modified: freeswitch/trunk/libs/spandsp/src/v29rx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v29rx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v29rx.c	Mon Apr 20 13:33:33 2009
@@ -1,3 +1,4 @@
+#define IAXMODEM_STUFF
 /*
  * SpanDSP - a series of DSP components for telephony
  *
@@ -22,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: v29rx.c,v 1.154 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v29rx.c,v 1.163 2009/04/20 16:36:36 steveu Exp $
  */
 
 /*! \file */
@@ -68,8 +69,11 @@
 #include "v29rx_floating_rrc.h"
 #endif
 
+/*! The nominal frequency of the carrier, in Hertz */
 #define CARRIER_NOMINAL_FREQ            1700.0f
+/*! The nominal baud or symbol rate */
 #define BAUD_RATE                       2400
+/*! The adaption rate coefficient for the equalizer */
 #define EQUALIZER_DELTA                 0.21f
 
 #if defined(SPANDSP_USE_FIXED_POINT)
@@ -78,10 +82,14 @@
 #endif
 
 /* Segments of the training sequence */
+/*! The length of training segment 2, in symbols */
 #define V29_TRAINING_SEG_2_LEN          128
+/*! The length of training segment 3, in symbols */
 #define V29_TRAINING_SEG_3_LEN          384
+/*! The length of training segment 4, in symbols */
 #define V29_TRAINING_SEG_4_LEN          48
 
+/*! The length of the equalizer buffer */
 #define V29_EQUALIZER_LEN    (V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN)
 
 enum
@@ -121,6 +129,8 @@
 };
 
 /* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
+/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
+/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
 #if defined(SPANDSP_USE_FIXED_POINT)
 #define SYNC_LOW_BAND_EDGE_COEFF_0      ((int)(FP_FACTOR* 1.829281f))   /* 2*alpha*cos(low_edge) */
 #define SYNC_LOW_BAND_EDGE_COEFF_1      ((int)(FP_FACTOR*-0.980100f))   /* -alpha^2 */
@@ -153,7 +163,7 @@
 
 SPAN_DECLARE(float) v29_rx_signal_power(v29_rx_state_t *s)
 {
-    return power_meter_current_dbm0(&s->power);
+    return power_meter_current_dbm0(&s->power) + 3.98f;
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -492,7 +502,7 @@
     s->symbol_sync_dc_filter[0] = v;
     /* A little integration will now filter away much of the noise */
     s->baud_phase -= p;
-    if (abs(s->baud_phase) > 100*FP_FACTOR)
+    if (abs(s->baud_phase) > 30*FP_FACTOR)
     {
         if (s->baud_phase > 0)
             i = (s->baud_phase > 1000*FP_FACTOR)  ?  5  :  1;
@@ -674,6 +684,8 @@
             s->carrier_phase += angle;
             /* We have just seen the first bit of the scrambled sequence, so skip it. */
             bit = scrambled_training_bit(s);
+            s->constellation_state = cdcd_pos[s->training_cd + bit];
+            target = &v29_9600_constellation[s->constellation_state];
             s->training_count = 1;
             s->training_stage = TRAINING_STAGE_TRAIN_ON_CDCD;
             report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
@@ -858,7 +870,7 @@
            We need to measure the power with the DC blocked, but not using
            a slow to respond DC blocker. Use the most elementary HPF. */
         x = amp[i] >> 1;
-        /* There could be oveflow here, but it isn't a problem in practice */
+        /* There could be overflow here, but it isn't a problem in practice */
         diff = x - s->last_sample;
         power = power_meter_update(&(s->power), diff);
 #if defined(IAXMODEM_STUFF)
@@ -999,6 +1011,34 @@
 }
 /*- End of function --------------------------------------------------------*/
 
+SPAN_DECLARE(int) v29_rx_fillin(v29_rx_state_t *s, int len)
+{
+    int i;
+
+    /* We want to sustain the current state (i.e carrier on<->carrier off), and
+       try to sustain the carrier phase. We should probably push the filters, as well */
+    span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
+    if (!s->signal_present)
+        return 0;
+    if (s->training_stage == TRAINING_STAGE_PARKED)
+        return 0;
+    for (i = 0;  i < len;  i++)
+    {
+#if defined(SPANDSP_USE_FIXED_POINT)
+        dds_advance(&s->carrier_phase, s->carrier_phase_rate);
+#else
+        dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
+#endif
+        /* Advance the symbol phase the appropriate amount */
+        s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
+        if (s->eq_put_step <= 0)
+            s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
+        /* TODO: Should we rotate any buffers */
+    }
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
 SPAN_DECLARE(void) v29_rx_set_put_bit(v29_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
 {
     s->put_bit = put_bit;

Modified: freeswitch/trunk/libs/spandsp/src/v29tx.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/src/v29tx.c	(original)
+++ freeswitch/trunk/libs/spandsp/src/v29tx.c	Mon Apr 20 13:33:33 2009
@@ -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: v29tx.c,v 1.86 2009/02/10 13:06:47 steveu Exp $
+ * $Id: v29tx.c,v 1.87 2009/04/12 04:20:01 steveu Exp $
  */
 
 /*! \file */
@@ -65,15 +65,23 @@
 #include "v29tx_floating_rrc.h"
 #endif
 
+/*! The nominal frequency of the carrier, in Hertz */
 #define CARRIER_NOMINAL_FREQ        1700.0f
 
 /* Segments of the training sequence */
+/*! The start of the optional TEP, that may preceed the actual training, in symbols */
 #define V29_TRAINING_SEG_TEP        0
+/*! The start of training segment 1, in symbols */
 #define V29_TRAINING_SEG_1          (V29_TRAINING_SEG_TEP + 480)
+/*! The start of training segment 2, in symbols */
 #define V29_TRAINING_SEG_2          (V29_TRAINING_SEG_1 + 48)
+/*! The start of training segment 3, in symbols */
 #define V29_TRAINING_SEG_3          (V29_TRAINING_SEG_2 + 128)
+/*! The start of training segment 4, in symbols */
 #define V29_TRAINING_SEG_4          (V29_TRAINING_SEG_3 + 384)
+/*! The end of the training, in symbols */
 #define V29_TRAINING_END            (V29_TRAINING_SEG_4 + 48)
+/*! The end of the shutdown sequence, in symbols */
 #define V29_TRAINING_SHUTDOWN_END   (V29_TRAINING_END + 32)
 
 static int fake_get_bit(void *user_data)

Modified: freeswitch/trunk/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c	(original)
+++ freeswitch/trunk/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c	Mon Apr 20 13:33:33 2009
@@ -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: generate_etsi_300_242_pages.c,v 1.4 2009/03/01 12:39:02 steveu Exp $
+ * $Id: generate_etsi_300_242_pages.c,v 1.5 2009/03/23 14:34:13 steveu Exp $
  */
 
 /*! \file */
@@ -186,12 +186,6 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-static void set_row(uint8_t buf[], int width)
-{
-    memset(buf, 0xFF, width/8 + 1);
-}
-/*- End of function --------------------------------------------------------*/
-
 static void set_pixel(uint8_t buf[], int row, int pixel)
 {
     row--;

Modified: freeswitch/trunk/libs/spandsp/tests/Makefile.am
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/Makefile.am	(original)
+++ freeswitch/trunk/libs/spandsp/tests/Makefile.am	Mon Apr 20 13:33:33 2009
@@ -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.110 2009/02/20 12:34:20 steveu Exp $
+## $Id: Makefile.am,v 1.112 2009/04/01 13:22:40 steveu Exp $
 
 AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
 AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
@@ -93,6 +93,7 @@
                     tone_generate_tests \
                     tsb85_tests \
                     v17_tests \
+                    v18_tests \
                     v22bis_tests \
                     v27ter_tests \
                     v29_tests \
@@ -107,6 +108,7 @@
 
 noinst_HEADERS =    echo_monitor.h \
                     fax_tester.h \
+                    fax_utils.h \
                     line_model_monitor.h \
                     media_monitor.h \
                     modem_monitor.h
@@ -291,6 +293,9 @@
 v17_tests_SOURCES = v17_tests.c line_model_monitor.cpp modem_monitor.cpp
 v17_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
 
+v18_tests_SOURCES = v18_tests.c
+v18_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
+
 v22bis_tests_SOURCES = v22bis_tests.c line_model_monitor.cpp modem_monitor.cpp
 v22bis_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
 

Modified: freeswitch/trunk/libs/spandsp/tests/adsi_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/adsi_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/adsi_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: adsi_tests.c,v 1.48 2008/11/30 10:17:31 steveu Exp $
+ * $Id: adsi_tests.c,v 1.55 2009/04/11 15:16:14 steveu Exp $
  */
 
 /*! \page adsi_tests_page ADSI tests
@@ -58,19 +58,38 @@
 #include "spandsp.h"
 #include "spandsp-sim.h"
 
-#define OUT_FILE_NAME   "adsi.wav"
+#define OUTPUT_FILE_NAME    "adsi.wav"
 
-#define BLOCK_LEN       160
+#define BLOCK_LEN           160
+
+#define MITEL_DIR                   "../test-data/mitel/"
+#define BELLCORE_DIR                "../test-data/bellcore/"
+
+const char *bellcore_files[] =
+{
+    MITEL_DIR    "mitel-cm7291-talkoff.wav",
+    BELLCORE_DIR "tr-tsy-00763-1.wav",
+    BELLCORE_DIR "tr-tsy-00763-2.wav",
+    BELLCORE_DIR "tr-tsy-00763-3.wav",
+    BELLCORE_DIR "tr-tsy-00763-4.wav",
+    BELLCORE_DIR "tr-tsy-00763-5.wav",
+    BELLCORE_DIR "tr-tsy-00763-6.wav",
+    ""
+};
 
 char *decode_test_file = NULL;
 
 int errors = 0;
+int basic_testing = FALSE;
 
 adsi_rx_state_t *rx_adsi;
 adsi_tx_state_t *tx_adsi;
 
 int current_standard = 0;
 int good_message_received;
+int log_audio = FALSE;
+AFfilehandle outhandle = NULL;
+int short_preamble = FALSE;
 
 static int adsi_create_message(adsi_tx_state_t *s, uint8_t *msg)
 {
@@ -453,13 +472,16 @@
                     }
                     break;
                 case ADSI_STANDARD_TDD:
-                    if (len != 59
-                        ||
-                        memcmp(msg, "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789#$*()", 59))
-                    {
-                        printf("\n");
-                        printf("String error\n");
-                        exit(2);
+                    if (basic_testing)
+                    {
+                        if (len != 59
+                            ||
+                            memcmp(msg, "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789#$*()", 59))
+                        {
+                            printf("\n");
+                            printf("String error\n");
+                            exit(2);
+                        }
                     }
                     break;
                 }
@@ -568,32 +590,175 @@
 }
 /*- End of function --------------------------------------------------------*/
 
-int main(int argc, char *argv[])
+static void tdd_character_set_tests(void)
+{
+#if 0
+    char *s;
+    int ch;
+    int xx;
+    int yy;
+
+    /* This part tests internal static routines in the ADSI module. It can
+       only be run with a modified version of the ADSI module, which makes
+       the routines visible. */
+    /* Check the character encode/decode cycle */
+    tx_adsi = adsi_tx_init(NULL, ADSI_STANDARD_TDD);
+    rx_adsi = adsi_rx_init(NULL, ADSI_STANDARD_TDD, put_adsi_msg, NULL);
+    s = "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()";
+    while ((ch = *s++))
+    {
+        xx = adsi_encode_baudot(tx_adsi, ch);
+        if ((xx & 0x3E0))
+        {
+            yy = adsi_decode_baudot(rx_adsi, (xx >> 5) & 0x1F);
+            if (yy)
+                printf("%c", yy);
+        }
+        yy = adsi_decode_baudot(rx_adsi, xx & 0x1F);
+        if (yy)
+            printf("%c", yy);
+    }
+    adsi_tx_free(tx_adsi);
+    adsi_rx_free(rx_adsi);
+    printf("\n");
+#endif
+}
+/*- End of function --------------------------------------------------------*/
+
+static void basic_tests(int standard)
 {
     int16_t amp[BLOCK_LEN];
     uint8_t adsi_msg[256 + 42];
-    int adsi_msg_len;
-    AFfilehandle inhandle;
-    AFfilehandle outhandle;
     int outframes;
     int len;
-    int i;
+    int adsi_msg_len;
     int push;
-    int log_audio;
-    int short_preamble;
+    int i;
+
+    basic_testing = TRUE;
+    printf("Testing %s\n", adsi_standard_to_str(standard));
+    tx_adsi = adsi_tx_init(NULL, standard);
+    if (short_preamble)
+        adsi_tx_set_preamble(tx_adsi, 50, 20, 5, -1);
+    rx_adsi = adsi_rx_init(NULL, standard, put_adsi_msg, NULL);
+
+    /* Fake an OK condition for the first message test */
+    good_message_received = TRUE;
+    push = 0;
+    for (i = 0;  i < 100000;  i++)
+    {
+        if (push == 0)
+        {
+            if ((len = adsi_tx(tx_adsi, amp, BLOCK_LEN)) == 0)
+                push = 10;
+        }
+        else
+        {
+            len = 0;
+            /* Push a little silence through, to flush things out */
+            if (--push == 0)
+            {
+                if (!good_message_received)
+                {
+                    printf("No message received %s (%d)\n", adsi_standard_to_str(standard), i);
+                    exit(2);
+                }
+                good_message_received = FALSE;
+                adsi_msg_len = adsi_create_message(tx_adsi, adsi_msg);
+                adsi_msg_len = adsi_tx_put_message(tx_adsi, adsi_msg, adsi_msg_len);
+            }
+        }
+        if (len < BLOCK_LEN)
+        {
+            memset(&amp[len], 0, sizeof(int16_t)*(BLOCK_LEN - len));
+            len = BLOCK_LEN;
+        }
+        if (log_audio)
+        {
+            outframes = afWriteFrames(outhandle,
+                                      AF_DEFAULT_TRACK,
+                                      amp,
+                                      len);
+            if (outframes != len)
+            {
+                fprintf(stderr, "    Error writing wave file\n");
+                exit(2);
+            }
+        }
+        adsi_rx(rx_adsi, amp, len);
+    }
+    adsi_rx_free(rx_adsi);
+    adsi_tx_free(tx_adsi);
+    basic_testing = FALSE;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void mitel_cm7291_side_2_and_bellcore_tests(int standard)
+{
+    int j;
+    int16_t amp[BLOCK_LEN];
+    AFfilehandle inhandle;
+    int frames;
+
+    /* The remainder of the Mitel tape is the talk-off test */
+    /* Here we use the Bellcore test tapes (much tougher), in six
+       wave files - 1 from each side of the original 3 cassette tapes */
+    printf("Talk-off tests for %s\n", adsi_standard_to_str(standard));
+    rx_adsi = adsi_rx_init(NULL, standard, put_adsi_msg, NULL);
+    for (j = 0;  bellcore_files[j][0];  j++)
+    {
+        printf("Testing with %s\n", bellcore_files[j]);
+        if ((inhandle = afOpenFile_telephony_read(bellcore_files[j], 1)) == AF_NULL_FILEHANDLE)
+        {
+            printf("    Cannot open speech file '%s'\n", bellcore_files[j]);
+            exit(2);
+        }
+        while ((frames = afReadFrames(inhandle, AF_DEFAULT_TRACK, amp, BLOCK_LEN)))
+        {
+            adsi_rx(rx_adsi, amp, frames);
+        }
+        if (afCloseFile(inhandle) != 0)
+        {
+            printf("    Cannot close speech file '%s'\n", bellcore_files[j]);
+            exit(2);
+        }
+    }
+    adsi_rx_free(rx_adsi);
+    if (j > 470)
+    {
+        printf("    Failed\n");
+        exit(2);
+    }
+    printf("    Passed\n");
+}
+/*- End of function --------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+    int16_t amp[BLOCK_LEN];
+    AFfilehandle inhandle;
+    int len;
     int test_standard;
     int first_standard;
     int last_standard;
     int opt;
+    int enable_basic_tests;
+    int enable_talkoff_tests;
 
     log_audio = FALSE;
     decode_test_file = NULL;
     test_standard = -1;
     short_preamble = FALSE;
-    while ((opt = getopt(argc, argv, "d:lps:")) != -1)
+    enable_basic_tests = TRUE;
+    enable_talkoff_tests = FALSE;
+    while ((opt = getopt(argc, argv, "bd:lps:t")) != -1)
     {
         switch (opt)
         {
+        case 'b':
+            enable_basic_tests = TRUE;
+            enable_talkoff_tests = FALSE;
+            break;
         case 'd':
             decode_test_file = optarg;
             break;
@@ -619,6 +784,10 @@
             else
                 test_standard = atoi(optarg);
             break;
+        case 't':
+            enable_basic_tests = FALSE;
+            enable_talkoff_tests = TRUE;
+            break;
         default:
             //usage();
             exit(2);
@@ -627,32 +796,7 @@
     }
     outhandle = AF_NULL_FILEHANDLE;
     
-#if 0
-    /* This part tests internal static routines in the ADSI module. It can
-       only be run with a modified version of the ADSI module, which makes
-       the routines visible. */
-    /* Check the character encode/decode cycle */
-    current_standard = ADSI_STANDARD_TDD;
-    tx_adsi = adsi_tx_init(NULL, ADSI_STANDARD_TDD);
-    rx_adsi = adsi_rx_init(NULL, ADSI_STANDARD_TDD, put_adsi_msg, NULL);
-    s = "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()";
-    while ((ch = *s++))
-    {
-        xx = adsi_encode_baudot(tx_adsi, ch);
-        if ((xx & 0x3E0))
-        {
-            yy = adsi_decode_baudot(rx_adsi, (xx >> 5) & 0x1F);
-            if (yy)
-                printf("%c", yy);
-        }
-        yy = adsi_decode_baudot(rx_adsi, xx & 0x1F);
-        if (yy)
-            printf("%c", yy);
-    }
-    adsi_tx_free(tx_adsi);
-    adsi_rx_free(rx_adsi);
-    printf("\n");
-#endif
+    tdd_character_set_tests();
 
     if (decode_test_file)
     {
@@ -693,9 +837,9 @@
     {
         if (log_audio)
         {
-            if ((outhandle = afOpenFile_telephony_write(OUT_FILE_NAME, 1)) == AF_NULL_FILEHANDLE)
+            if ((outhandle = afOpenFile_telephony_write(OUTPUT_FILE_NAME, 1)) == AF_NULL_FILEHANDLE)
             {
-                fprintf(stderr, "    Cannot create wave file '%s'\n", OUT_FILE_NAME);
+                fprintf(stderr, "    Cannot create wave file '%s'\n", OUTPUT_FILE_NAME);
                 exit(2);
             }
         }
@@ -713,71 +857,22 @@
         }
         for (current_standard = first_standard;  current_standard <= last_standard;  current_standard++)
         {
-            printf("Testing %s\n", adsi_standard_to_str(current_standard));
-            tx_adsi = adsi_tx_init(NULL, current_standard);
-            if (short_preamble)
-                adsi_tx_set_preamble(tx_adsi, 50, 20, 5, -1);
-            rx_adsi = adsi_rx_init(NULL, current_standard, put_adsi_msg, NULL);
-
-            /* Fake an OK condition for the first message test */
-            good_message_received = TRUE;
-            push = 0;
-            for (i = 0;  i < 100000;  i++)
-            {
-                if (push == 0)
-                {
-                    if ((len = adsi_tx(tx_adsi, amp, BLOCK_LEN)) == 0)
-                        push = 10;
-                }
-                else
-                {
-                    len = 0;
-                    /* Push a little silence through, to flush things out */
-                    if (--push == 0)
-                    {
-                        if (!good_message_received)
-                        {
-                            printf("No message received %s (%d)\n", adsi_standard_to_str(current_standard), i);
-                            exit(2);
-                        }
-                        good_message_received = FALSE;
-                        adsi_msg_len = adsi_create_message(tx_adsi, adsi_msg);
-                        adsi_msg_len = adsi_tx_put_message(tx_adsi, adsi_msg, adsi_msg_len);
-                    }
-                }
-                if (len < BLOCK_LEN)
-                {
-                    memset(&amp[len], 0, sizeof(int16_t)*(BLOCK_LEN - len));
-                    len = BLOCK_LEN;
-                }
-                if (log_audio)
-                {
-                    outframes = afWriteFrames(outhandle,
-                                              AF_DEFAULT_TRACK,
-                                              amp,
-                                              len);
-                    if (outframes != len)
-                    {
-                        fprintf(stderr, "    Error writing wave file\n");
-                        exit(2);
-                    }
-                }
-                adsi_rx(rx_adsi, amp, len);
-            }
-            adsi_rx_free(rx_adsi);
-            adsi_tx_free(tx_adsi);
+            if (enable_basic_tests)
+                basic_tests(current_standard);
+            if (enable_talkoff_tests)
+                mitel_cm7291_side_2_and_bellcore_tests(current_standard);
         }
         if (log_audio)
         {
             if (afCloseFile(outhandle) != 0)
             {
-                fprintf(stderr, "    Cannot close wave file '%s'\n", OUT_FILE_NAME);
+                fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_FILE_NAME);
                 exit(2);
             }
         }
+        printf("Tests passed.\n");
     }
-    
-    printf("Tests passed.\n");
+
     return 0;
 }
 /*- End of function --------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/tests/bell_mf_rx_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/bell_mf_rx_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/bell_mf_rx_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: bell_mf_rx_tests.c,v 1.14 2008/11/30 10:17:31 steveu Exp $
+ * $Id: bell_mf_rx_tests.c,v 1.15 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -79,6 +79,9 @@
 #define MF_PAUSE                    (68*8)
 #define MF_CYCLE                    (MF_DURATION + MF_PAUSE)
 
+/*!
+    MF tone descriptor for tests.
+*/
 typedef struct
 {
     float       f1;         /* First freq */

Modified: freeswitch/trunk/libs/spandsp/tests/bert_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/bert_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/bert_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: bert_tests.c,v 1.26 2008/11/30 12:38:27 steveu Exp $
+ * $Id: bert_tests.c,v 1.27 2009/04/14 16:04:54 steveu Exp $
  */
 
 /*! \file */
@@ -212,7 +212,7 @@
             zeros++;
         }
         bert_put_bit(&rx_bert, bit);        
-        test[tx_bert.tx_reg]++;
+        test[tx_bert.tx.reg]++;
     }
     failed = FALSE;
     if (test[0] != 0)
@@ -256,7 +256,7 @@
             zeros++;
         }
         bert_put_bit(&rx_bert, bit);        
-        test[tx_bert.tx_reg]++;
+        test[tx_bert.tx.reg]++;
     }
     failed = FALSE;
     if (test[0] != 0)
@@ -300,7 +300,7 @@
             zeros++;
         }
         bert_put_bit(&rx_bert, bit);        
-        test[tx_bert.tx_reg]++;
+        test[tx_bert.tx.reg]++;
     }
     failed = FALSE;
     if (test[0] != 0)
@@ -344,7 +344,7 @@
             zeros++;
         }
         bert_put_bit(&rx_bert, bit);        
-        test[tx_bert.tx_reg]++;
+        test[tx_bert.tx.reg]++;
     }
     failed = FALSE;
     if (test[0] != 0)
@@ -385,7 +385,7 @@
             zeros++;
         }
         bert_put_bit(&rx_bert, bit);        
-        test[tx_bert.tx_reg]++;
+        test[tx_bert.tx.reg]++;
     }
     failed = FALSE;
     if (test[0] != 0)

Added: freeswitch/trunk/libs/spandsp/tests/fax_utils.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/tests/fax_utils.h	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,49 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * fax_utils.h
+ *
+ * Written by Steve Underwood <steveu at 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: fax_utils.h,v 1.1 2009/02/20 12:34:20 steveu Exp $
+ */
+
+/*! \file */
+
+#if !defined(_SPANDSP_FAX_UTILS_H_)
+#define _SPANDSP_FAX_UTILS_H_
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+void log_tx_parameters(t30_state_t *s, const char *tag);
+
+void log_rx_parameters(t30_state_t *s, const char *tag);
+
+void log_transfer_statistics(t30_state_t *s, const char *tag);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/tests/fsk_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/fsk_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/fsk_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: fsk_tests.c,v 1.55 2009/02/12 14:21:16 steveu Exp $
+ * $Id: fsk_tests.c,v 1.56 2009/04/14 16:04:54 steveu Exp $
  */
 
 /*! \page fsk_tests_page FSK modem tests
@@ -392,7 +392,7 @@
         bert_set_report(&caller_bert, 100000, reporter, (void *) (intptr_t) 1);
         bert_init(&answerer_bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
         bert_set_report(&answerer_bert, 100000, reporter, (void *) (intptr_t) 2);
-        if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, noise_level, channel_codec, rbs_pattern)) == NULL)
+        if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec, rbs_pattern)) == NULL)
         {
             fprintf(stderr, "    Failed to create line model\n");
             exit(2);

Modified: freeswitch/trunk/libs/spandsp/tests/queue_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/queue_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/queue_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: queue_tests.c,v 1.12 2008/11/30 13:08:42 steveu Exp $
+ * $Id: queue_tests.c,v 1.13 2009/04/11 17:43:04 steveu Exp $
  */
 
 /* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */
@@ -65,7 +65,7 @@
 static void tests_failed(void)
 {
     printf("Tests failed\n");
-    tests_failed();
+    exit(2);
 }
 /*- End of function --------------------------------------------------------*/
 
@@ -309,7 +309,7 @@
 static int monitored_queue_write(const uint8_t buf[], int len)
 {
     int lenx;
-    
+
     lenx = queue_write(queue, buf, len);
     if (lenx >= 0)
         total_in += lenx;
@@ -321,7 +321,7 @@
 static int monitored_queue_write_byte(const uint8_t buf)
 {
     int res;
-    
+
     if ((res = queue_write_byte(queue, buf)) >= 0)
         total_in++;
     check_contents(total_in, total_out);
@@ -332,7 +332,7 @@
 static int monitored_queue_read(uint8_t buf[], int len)
 {
     int lenx;
-    
+
     lenx = queue_read(queue, buf, len);
     if (lenx >= 0)
         total_out += lenx;
@@ -344,7 +344,7 @@
 static int monitored_queue_read_byte(void)
 {
     int res;
-    
+
     if ((res = queue_read_byte(queue)) >= 0)
         total_out++;
     check_contents(total_in, total_out);
@@ -357,7 +357,7 @@
     uint8_t buf[MSG_LEN];
     int i;
     int res;
-    
+
     total_in = 0;
     total_out = 0;
 

Modified: freeswitch/trunk/libs/spandsp/tests/r2_mf_rx_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/r2_mf_rx_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/r2_mf_rx_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: r2_mf_rx_tests.c,v 1.12 2008/11/30 10:17:31 steveu Exp $
+ * $Id: r2_mf_rx_tests.c,v 1.13 2009/04/11 18:11:19 steveu Exp $
  */
 
 /*! \file */
@@ -87,6 +87,9 @@
 #define MF_PAUSE                    (68*8)
 #define MF_CYCLE                    (MF_DURATION + MF_PAUSE)
 
+/*!
+    MF tone generator descriptor for tests.
+*/
 typedef struct
 {
     float       f1;         /* First freq */

Modified: freeswitch/trunk/libs/spandsp/tests/regression_tests.sh
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/regression_tests.sh	(original)
+++ freeswitch/trunk/libs/spandsp/tests/regression_tests.sh	Mon Apr 20 13:33:33 2009
@@ -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.55 2009/02/20 14:04:40 steveu Exp $
+# $Id: regression_tests.sh,v 1.56 2009/04/02 13:43:49 steveu Exp $
 #
 
 ITUTESTS_TIF=../test-data/itu/fax/itutests.tif
@@ -800,6 +800,15 @@
 fi
 echo v8_tests completed OK
 
+./v18_tests >$STDOUT_DEST 2>$STDERR_DEST
+RETVAL=$?
+if [ $RETVAL != 0 ]
+then
+    echo v18_tests failed!
+    exit $RETVAL
+fi
+echo v18_tests completed OK
+
 ./vector_float_tests >$STDOUT_DEST 2>$STDERR_DEST
 RETVAL=$?
 if [ $RETVAL != 0 ]

Modified: freeswitch/trunk/libs/spandsp/tests/v17_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/v17_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/v17_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: v17_tests.c,v 1.100 2009/02/12 14:21:16 steveu Exp $
+ * $Id: v17_tests.c,v 1.101 2009/03/15 09:09:21 steveu Exp $
  */
 
 /*! \page v17_tests_page V.17 modem tests
@@ -189,7 +189,7 @@
         fpower = (constel->re - target->re)*(constel->re - target->re)
                + (constel->im - target->im)*(constel->im - target->im);
         smooth_power = 0.95f*smooth_power + 0.05f*fpower;
-        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.2f\n",
+        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.4f\n",
                symbol_no,
                constel->re,
                constel->im,

Added: freeswitch/trunk/libs/spandsp/tests/v18_tests.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/spandsp/tests/v18_tests.c	Mon Apr 20 13:33:33 2009
@@ -0,0 +1,492 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * v18_tests.c
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2004-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: v18_tests.c,v 1.5 2009/04/11 18:11:19 steveu Exp $
+ */
+
+/*! \page v18_tests_page V.18 tests
+\section v18_tests_page_sec_1 What does it do?
+*/
+
+/* Enable the following definition to enable direct probing into the spandsp structures */
+//#define WITH_SPANDSP_INTERNALS
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <audiofile.h>
+
+//#if defined(WITH_SPANDSP_INTERNALS)
+#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
+//#endif
+
+#include "spandsp.h"
+#include "spandsp-sim.h"
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+#define OUTPUT_FILE_NAME    "v18.wav"
+
+#define SAMPLES_PER_CHUNK   160
+
+int log_audio = FALSE;
+AFfilehandle outhandle = NULL;
+
+char *decode_test_file = NULL;
+
+int good_message_received;
+
+#if 1
+static void put_text_msg(void *user_data, const uint8_t *msg, int len)
+{
+    if (strcmp((const char *) msg, "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789#$*()"))
+        printf("%s\n", msg);
+    else
+        good_message_received = TRUE;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void basic_tests(int mode)
+{
+    int16_t amp[SAMPLES_PER_CHUNK];
+    int outframes;
+    int len;
+    int push;
+    int i;
+    v18_state_t *v18_a;
+    v18_state_t *v18_b;
+
+    printf("Testing %s\n", v18_mode_to_str(mode));
+    v18_a = v18_init(NULL, TRUE, mode, put_text_msg, NULL);
+    v18_b = v18_init(NULL, FALSE, mode, put_text_msg, NULL);
+
+    /* Fake an OK condition for the first message test */
+    good_message_received = TRUE;
+    push = 0;
+    v18_put(v18_a, "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()", -1);
+    for (i = 0;  i < 100000;  i++)
+    {
+        if (push == 0)
+        {
+            if ((len = v18_tx(v18_a, amp, SAMPLES_PER_CHUNK)) == 0)
+                push = 10;
+        }
+        else
+        {
+            len = 0;
+            /* Push a little silence through, to flush things out */
+            if (--push == 0)
+            {
+                if (!good_message_received)
+                {
+                    printf("No message received\n");
+                    exit(2);
+                }
+                good_message_received = FALSE;
+                v18_put(v18_a, "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()", -1);
+            }
+        }
+        if (len < SAMPLES_PER_CHUNK)
+        {
+            memset(&amp[len], 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - len));
+            len = SAMPLES_PER_CHUNK;
+        }
+        if (log_audio)
+        {
+            outframes = afWriteFrames(outhandle,
+                                      AF_DEFAULT_TRACK,
+                                      amp,
+                                      len);
+            if (outframes != len)
+            {
+                fprintf(stderr, "    Error writing wave file\n");
+                exit(2);
+            }
+        }
+        v18_rx(v18_b, amp, len);
+    }
+    v18_free(v18_a);
+    v18_free(v18_b);
+}
+/*- End of function --------------------------------------------------------*/
+#endif
+
+static int test_x_01(void)
+{
+    /* III.5.4.5.1 Baudot carrier timing and receiver disabling */
+    printf("Test not yet implemented\n");
+    return 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int test_x_02(void)
+{
+    /* III.5.4.5.2 Baudot bit rate confirmation */
+    printf("Test not yet implemented\n");
+    return 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int test_x_03(void)
+{
+    /* III.5.4.5.3 Baudot probe bit rate confirmation */
+    printf("Test not yet implemented\n");
+    return 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int test_x_04(void)
+{
+    const char *s;
+    const char *ref;
+    char result[1024];
+    char *t;
+    int ch;
+    int xx;
+    int yy;
+    v18_state_t *v18_state;
+
+    /* III.5.4.5.4 5 Bit to T.50 character conversion */
+    v18_state = v18_init(NULL, TRUE, V18_MODE_5BIT_45, NULL, NULL);
+    s = "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()";
+    printf("Original:\n%s\n", s);
+    t = result;
+    while ((ch = *s++))
+    {
+        xx = v18_encode_baudot(v18_state, ch);
+        if ((xx & 0x3E0))
+        {
+            yy = v18_decode_baudot(v18_state, (xx >> 5) & 0x1F);
+            if (yy)
+                *t++ = yy;
+        }
+        yy = v18_decode_baudot(v18_state, xx & 0x1F);
+        if (yy)
+            *t++ = yy;
+    }
+    *t = '\0';
+    v18_free(v18_state);
+    ref = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789#$*()";
+    printf("Result:\n%s\n", result);
+    printf("Reference result:\n%s\n", ref);
+    if (strcmp(result, ref) != 0)
+        return -1;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int test_x_06(void)
+{
+    char msg[128];
+    char dtmf[1024];
+    char result[1024];
+    const char *ref;
+    int len;
+    int i;
+
+    /* III.5.4.5.6 DTMF character conversion */
+    for (i = 0;  i < 127;  i++)
+        msg[i] = i + 1;
+    msg[127] = '\0';
+    printf("%s\n", msg);
+    
+    len = v18_encode_dtmf(NULL, dtmf, msg);
+    printf("%s\n", dtmf);
+
+    len = v18_decode_dtmf(NULL, result, dtmf);
+
+    ref = "\b \n\n\n?\n\n\n  %+().+,-.0123456789:;(=)"
+          "?XABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"
+          " abcdefghijklmnopqrstuvwxyzæøå \b";
+
+    printf("Result:\n%s\n", result);
+    printf("Reference result:\n%s\n", ref);
+    if (strcmp(result, ref) != 0)
+        return -1;
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int test_unimplemented(void)
+{
+    printf("Test not yet implemented\n");
+    return 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void put_v18_msg(void *user_data, const uint8_t *msg, int len)
+{
+    char buf[1024];
+    
+    memcpy(buf, msg, len);
+    buf[len] = '\0';
+    printf("Received (%d bytes) '%s'\n", len, buf);
+}
+/*- End of function --------------------------------------------------------*/
+
+static int decode_test_data_file(int mode, const char *filename)
+{
+    v18_state_t *v18_state;
+    int16_t amp[SAMPLES_PER_CHUNK];
+    AFfilehandle inhandle;
+    int len;
+
+    printf("Decoding as '%s'\n", v18_mode_to_str(mode));
+    /* We will decode the audio from a wave file. */
+    if ((inhandle = afOpenFile_telephony_read(decode_test_file, 1)) == AF_NULL_FILEHANDLE)
+    {
+        fprintf(stderr, "    Cannot open wave file '%s'\n", decode_test_file);
+        exit(2);
+    }
+    v18_state = v18_init(NULL, FALSE, mode, put_v18_msg, NULL);
+    for (;;)
+    {
+        len = afReadFrames(inhandle,
+                           AF_DEFAULT_TRACK,
+                           amp,
+                           SAMPLES_PER_CHUNK);
+        if (len == 0)
+            break;
+        v18_rx(v18_state, amp, len);
+    }
+    if (afCloseFile(inhandle) != 0)
+    {
+        fprintf(stderr, "    Cannot close wave file '%s'\n", decode_test_file);
+        exit(2);
+    }
+    v18_free(v18_state);
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+const struct
+{
+    const char *title;
+    int (*func)(void);
+} test_list[] =
+{
+    {"III.3.2.1 Operational requirements tests", NULL},
+    {"MISC-01         4 (1)       No Disconnection Test", test_unimplemented},
+    {"MISC-02         4 (2)       Automatic resumption of automoding", test_unimplemented},
+    {"MISC-03         4 (2)       Retention of selected mode on loss of signal", test_unimplemented},
+    {"MISC-04         4 (4)       Detection of BUSY tone", test_unimplemented},
+    {"MISC-05         4 (4)       Detection of RINGING", test_unimplemented},
+    {"MISC-06         4 (4)       LOSS OF CARRIER indication", test_unimplemented},
+    {"MISC-07         4 (4)       Call progress indication", test_unimplemented},
+    {"MISC-08         4 (5)       Circuit 135 test", test_unimplemented},
+    {"MISC-09                     Connection Procedures", test_unimplemented},
+
+    {"III.3.2.2 Automode originate tests", NULL},
+    {"ORG-01          5.1.1       CI & XCI Signal coding and cadence", test_unimplemented},
+    {"ORG-02          5.1.3       ANS Signal Detection", test_unimplemented},
+    {"ORG-03          5.2.3.1     End of ANS signal detection", test_unimplemented},
+    {"ORG-04          5.1.3.2     ANS tone followed by TXP", test_unimplemented},
+    {"ORG-05          5.1.3.3     ANS tone followed by 1650Hz", test_unimplemented},
+    {"ORG-06          5.1.3.4     ANS tone followed by 1300Hz", test_unimplemented},
+    {"ORG-07          5.1.3       ANS tone followed by no tone", test_unimplemented},
+    {"ORG-08          5.1.4       Bell 103 (2225Hz Signal) Detection", test_unimplemented},
+    {"ORG-09          5.1.5       V.21 (1650Hz Signal) Detection", test_unimplemented},
+    {"ORG-10          5.1.6       V.23 (1300Hz Signal) Detection", test_unimplemented},
+    {"ORG-11          5.1.7       V.23 (390Hz Signal) Detection", test_unimplemented},
+    {"ORG-12a to d    5.1.8       5 Bit Mode (Baudot) Detection Tests", test_unimplemented},
+    {"ORG-13          5.1.9       DTMF signal detection", test_unimplemented},
+    {"ORG-14          5.1.10      EDT Rate Detection", test_unimplemented},
+    {"ORG-15          5.1.10.1    Rate Detection Test", test_unimplemented},
+    {"ORG-16          5.1.10.2    980Hz Detection", test_unimplemented},
+    {"ORG-17          5.1.10.3    Loss of signal after 980Hz", test_unimplemented},
+    {"ORG-18          5.1.10.3    Tr Timer", test_unimplemented},
+    {"ORG-19          5.1.11      Bell 103 (1270Hz Signal) Detection", test_unimplemented},
+    {"ORG-20                      Immunity to Network Tones", test_unimplemented},
+    {"ORG-21a to b                Immunity to other non-textphone modems", test_unimplemented},
+    {"ORG-22                      Immunity to Fax Tones", test_unimplemented},
+    {"ORG-23                      Immunity to Voice", test_unimplemented},
+    {"ORG-24          5.1.2       ANSam detection", test_unimplemented},
+    {"ORG-25          6.1         V.8 originate call", test_unimplemented},
+
+    {"III.3.2.3 Automode answer tests", NULL},
+    {"ANS-01          5.2.1       Ta timer", test_unimplemented},
+    {"ANS-02          5.2.2       CI Signal Detection", test_unimplemented},
+    {"ANS-03          5.2.2.1     Early Termination of ANS tone", test_unimplemented},
+    {"ANS-04          5.2.2.2     Tt Timer", test_unimplemented},
+    {"ANS-05          5.2.3.2     ANS tone followed by 980Hz", test_unimplemented},
+    {"ANS-06          5.2.3.2     ANS tone followed by 1300Hz", test_unimplemented},
+    {"ANS-07          5.2.3.3     ANS tone followed by 1650Hz", test_unimplemented},
+    {"ANS-08          5.2.4.1     980Hz followed by 1650Hz", test_unimplemented},
+    {"ANS-09a to d    5.2.4.2     980Hz calling tone detection", test_unimplemented},
+    {"ANS-10          5.2.4.3     V.21 Detection by Timer", test_unimplemented},
+    {"ANS-11          5.2.4.4.1   EDT Detection by Rate", test_unimplemented},
+    {"ANS-12          5.2.4.4.2   V.21 Detection by Rate", test_unimplemented},
+    {"ANS-13          5.2.4.4.3   Tr Timer", test_unimplemented},
+    {"ANS-14          5.2.4.5     Te Timer", test_unimplemented},
+    {"ANS-15a to d    5.2.5       5 Bit Mode (Baudot) Detection Tests", test_unimplemented},
+    {"ANS-16          5.2.6       DTMF Signal Detection", test_unimplemented},
+    {"ANS-17          5.2.7       Bell 103 (1270Hz signal) detection", test_unimplemented},
+    {"ANS-18          5.2.8       Bell 103 (2225Hz signal) detection", test_unimplemented},
+    {"ANS-19          5.2.9       V.21 Reverse Mode (1650Hz) Detection", test_unimplemented},
+    {"ANS-20a to d    5.2.10      1300Hz Calling Tone Discrimination", test_unimplemented},
+    {"ANS-21          5.2.11      V.23 Reverse Mode (1300Hz) Detection", test_unimplemented},
+    {"ANS-22                      1300Hz with XCI Test", test_unimplemented},
+    {"ANS-23          5.2.12      Stimulate Mode Country Settings", test_unimplemented},
+    {"ANS-24          5.2.12.1    Stimulate Carrierless Mode Probe Message", test_unimplemented},
+    {"ANS-25          5.2.12.1.1  Interrupted Carrierless Mode Probe", test_unimplemented},
+    {"ANS-26          5.2.12.2    Stimulate Carrier Mode Probe Time", test_unimplemented},
+    {"ANS-27          5.2.12.2.1  V.23 Mode (390Hz) Detection", test_unimplemented},
+    {"ANS-28          5.2.12.2.2  Interrupted Carrier Mode Probe", test_unimplemented},
+    {"ANS-29          5.2.12.2.2  Stimulate Mode Response During Probe", test_unimplemented},
+    {"ANS-30                      Immunity to Network Tones", test_unimplemented},
+    {"ANS-31                      Immunity to Fax Calling Tones", test_unimplemented},
+    {"ANS-32                      Immunity to Voice", test_unimplemented},
+    {"ANS-33          5.2.2.1     V.8 CM detection and V.8 Answering", test_unimplemented},
+
+    {"III.3.2.4 Automode monitor tests", NULL},
+    {"MON-01 to -20   5.3         Repeat all answer mode tests excluding tests ANS-01, ANS-20 and ANS-23 to ANS-29", test_unimplemented},
+    {"MON-21          5.3         Automode Monitor Ta timer", test_unimplemented},
+    {"MON-22a to d    5.3         Automode Monitor 1300Hz Calling Tone Discrimination", test_unimplemented},
+    {"MON-23a to d    5.3         Automode Monitor 980Hz Calling Tone Discrimination", test_unimplemented},
+
+    {"III.3.2.5 ITU-T V.18 annexes tests", NULL},
+    {"X-01            A.1         Baudot carrier timing and receiver disabling", test_x_01},
+    {"X-02            A.2         Baudot bit rate confirmation", test_x_02},
+    {"X-03            A.3         Baudot probe bit rate confirmation", test_x_03},
+    {"X-04            A.4         5 Bit to T.50 Character Conversion", test_x_04},
+    {"X-05            B.1         DTMF receiver disabling", test_unimplemented},
+    {"X-06            B.2         DTMF character conversion", test_x_06},
+    {"X-07            C.1         EDT carrier timing and receiver disabling", test_unimplemented},
+    {"X-08            C.2-3       EDT bit rate and character structure", test_unimplemented},
+    {"X-09            E           V.23 calling mode character format", test_unimplemented},
+    {"X-10            E           V.23 answer mode character format", test_unimplemented},
+    {"X-11            F.4-5       V.21 character structure", test_unimplemented},
+    {"X-12            G.1-3       V.18 mode", test_unimplemented},
+
+    {"", NULL}
+};
+
+int main(int argc, char *argv[])
+{
+    int i;
+    int res;
+    int hit;
+    const char *match;
+    int test_standard;
+    int opt;
+
+    match = NULL;
+    test_standard = -1;
+    while ((opt = getopt(argc, argv, "d:ls:")) != -1)
+    {
+        switch (opt)
+        {
+        case 'd':
+            decode_test_file = optarg;
+            break;
+        case 'l':
+            log_audio = TRUE;
+            break;
+        case 's':
+            test_standard = atoi(optarg);
+            break;
+        default:
+            //usage();
+            exit(2);
+            break;
+        }
+    }
+    if (decode_test_file)
+    {
+        decode_test_data_file(test_standard, decode_test_file);
+        exit(0);
+    }
+    argc -= optind;
+    argv += optind;
+    if (argc > 0)
+        match = argv[0];
+
+    outhandle = AF_NULL_FILEHANDLE;
+    if (log_audio)
+    {
+        if ((outhandle = afOpenFile_telephony_write(OUTPUT_FILE_NAME, 1)) == AF_NULL_FILEHANDLE)
+        {
+            fprintf(stderr, "    Cannot create wave file '%s'\n", OUTPUT_FILE_NAME);
+            exit(2);
+        }
+    }
+
+    hit = FALSE;
+    for (i = 0;  test_list[i].title[0];  i++)
+    {
+        if (test_list[i].func
+            &&
+               (match == NULL
+                ||
+                   (strncmp(match, test_list[i].title, strlen(match)) == 0
+                    &&
+                    test_list[i].title[strlen(match)] == ' ')))
+        {
+            hit = TRUE;
+            printf("%s\n", test_list[i].title);
+            res = test_list[i].func();
+            if (res < 0)
+            {
+                printf("    Test failed\n");
+                exit(2);
+            }
+            if (res == 0)
+            {
+                printf("    Test passed\n");
+            }
+        }
+        else
+        {
+            if (match == NULL)
+                printf("%s\n", test_list[i].title);
+        }
+    }
+    if (!hit)
+    {
+        printf("Test not found\n");
+        exit(2);
+    }
+    basic_tests(V18_MODE_5BIT_45);
+    if (log_audio)
+    {
+        if (afCloseFile(outhandle) != 0)
+        {
+            fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_FILE_NAME);
+            exit(2);
+        }
+    }
+    printf("Tests passed\n");
+    return 0;
+
+    return 0;
+}
+/*- End of function --------------------------------------------------------*/
+/*- End of file ------------------------------------------------------------*/

Modified: freeswitch/trunk/libs/spandsp/tests/v22bis_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/v22bis_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/v22bis_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: v22bis_tests.c,v 1.54 2009/01/12 17:20:59 steveu Exp $
+ * $Id: v22bis_tests.c,v 1.58 2009/04/17 14:37:53 steveu Exp $
  */
 
 /*! \page v22bis_tests_page V.22bis modem tests
@@ -65,55 +65,67 @@
 #define IN_FILE_NAME    "v22bis_samp.wav"
 #define OUT_FILE_NAME   "v22bis.wav"
 
-int in_bit = 0;
-int out_bit = 0;
-
-int in_bit_no = 0;
-int out_bit_no = 0;
-
-uint8_t tx_buf[1000];
-int rx_ptr = 0;
-int tx_ptr = 0;
-
 int rx_bits = 0;
-int rx_bad_bits = 0;
 
 int use_gui = FALSE;
 
 both_ways_line_model_state_t *model;
 
-v22bis_state_t caller;
-v22bis_state_t answerer;
-
-struct qam_report_control_s
+typedef struct
 {
-    v22bis_state_t *s;
+    v22bis_state_t *v22bis;
+    bert_state_t bert_tx;
+    bert_state_t bert_rx;
+    bert_results_t latest_results;
 #if defined(ENABLE_GUI)
     qam_monitor_t *qam_monitor;
 #endif
     float smooth_power;
     int symbol_no;
-};
+} endpoint_t;
+
+endpoint_t endpoint[2];
 
-struct qam_report_control_s qam_caller;
-struct qam_report_control_s qam_answerer;
+static void reporter(void *user_data, int reason, bert_results_t *results)
+{
+    endpoint_t *s;
+    
+    s = (endpoint_t *) user_data;
+    switch (reason)
+    {
+    case BERT_REPORT_REGULAR:
+        printf("V.22bis rx %p BERT report regular - %d bits, %d bad bits, %d resyncs\n",
+               user_data,
+               results->total_bits,
+               results->bad_bits,
+               results->resyncs);
+        memcpy(&s->latest_results, results, sizeof(s->latest_results));
+        break;
+    default:
+        printf("V.22bis rx %p BERT report %s\n",
+               user_data,
+               bert_event_to_str(reason));
+        break;
+    }
+}
+/*- End of function --------------------------------------------------------*/
 
 static void v22bis_putbit(void *user_data, int bit)
 {
-    v22bis_state_t *s;
+    endpoint_t *s;
     int i;
     int len;
     complexf_t *coeffs;
     
-    s = (v22bis_state_t *) user_data;
+    s = (endpoint_t *) user_data;
     if (bit < 0)
     {
         /* Special conditions */
-        printf("V.22bis rx status is %s (%d)\n", signal_status_to_str(bit), bit);
+        printf("V.22bis rx %p status is %s (%d)\n", user_data, signal_status_to_str(bit), bit);
         switch (bit)
         {
         case SIG_STATUS_TRAINING_SUCCEEDED:
-            len = v22bis_equalizer_state(s, &coeffs);
+            len = v22bis_equalizer_state(s->v22bis, &coeffs);
             printf("Equalizer:\n");
             for (i = 0;  i < len;  i++)
                 printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
@@ -122,38 +134,18 @@
         return;
     }
 
-    if (bit != tx_buf[rx_ptr])
-    {
-        printf("Rx bit %d - %d\n", rx_bits, bit);
-        rx_bad_bits++;
-    }
-    rx_ptr++;
-    if (rx_ptr > 1000)
-        rx_ptr = 0;
-    rx_bits++;
-    if ((rx_bits % 100000) == 0)
-    {
-        printf("%d bits received, %d bad bits\r", rx_bits, rx_bad_bits);
-        fflush(stdout);
-    }
+    //printf("Rx bit %p - %d\n", user_data, bit);
+    bert_put_bit(&s->bert_rx, bit);
 }
 /*- End of function --------------------------------------------------------*/
 
 static int v22bis_getbit(void *user_data)
 {
+    endpoint_t *s;
     int bit;
-    static int tx_bits = 0;
 
-    bit = rand() & 1;
-    tx_buf[tx_ptr++] = bit;
-    if (tx_ptr > 1000)
-        tx_ptr = 0;
-    //printf("Tx bit %d\n", bit);
-    if (++tx_bits > 100000)
-    {
-        tx_bits = 0;
-        bit = 2;
-    }
+    s = (endpoint_t *) user_data;
+    bit = bert_get_bit(&s->bert_tx);
     return bit;
 }
 /*- End of function --------------------------------------------------------*/
@@ -164,23 +156,24 @@
     int len;
     complexf_t *coeffs;
     float fpower;
-    struct qam_report_control_s *s;
+    endpoint_t *s;
 
-    s = (struct qam_report_control_s *) user_data;
+    s = (endpoint_t *) user_data;
     if (constel)
     {
 #if defined(ENABLE_GUI)
         if (use_gui)
         {
             qam_monitor_update_constel(s->qam_monitor, constel);
-            qam_monitor_update_carrier_tracking(s->qam_monitor, v22bis_rx_carrier_frequency(s->s));
-            qam_monitor_update_symbol_tracking(s->qam_monitor, v22bis_symbol_timing_correction(s->s));
+            qam_monitor_update_carrier_tracking(s->qam_monitor, v22bis_rx_carrier_frequency(s->v22bis));
+            qam_monitor_update_symbol_tracking(s->qam_monitor, v22bis_symbol_timing_correction(s->v22bis));
         }
 #endif
         fpower = (constel->re - target->re)*(constel->re - target->re)
                + (constel->im - target->im)*(constel->im - target->im);
         s->smooth_power = 0.95f*s->smooth_power + 0.05f*fpower;
-        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f\n",
+
+        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %8.4f\n",
                s->symbol_no,
                constel->re,
                constel->im,
@@ -188,13 +181,14 @@
                target->im,
                symbol,
                fpower,
-               s->smooth_power);
+               s->smooth_power,
+               v22bis_rx_signal_power(s->v22bis));
         s->symbol_no++;
     }
     else
     {
         printf("Gardner step %d\n", symbol);
-        len = v22bis_equalizer_state(s->s, &coeffs);
+        len = v22bis_equalizer_state(s->v22bis, &coeffs);
         printf("Equalizer A:\n");
         for (i = 0;  i < len;  i++)
             printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
@@ -208,15 +202,14 @@
 
 int main(int argc, char *argv[])
 {
-    int16_t caller_amp[BLOCK_LEN];
-    int16_t answerer_amp[BLOCK_LEN];
-    int16_t caller_model_amp[BLOCK_LEN];
-    int16_t answerer_model_amp[BLOCK_LEN];
+    int16_t amp[2][BLOCK_LEN];
+    int16_t model_amp[2][BLOCK_LEN];
     int16_t out_amp[2*BLOCK_LEN];
     AFfilehandle outhandle;
     int outframes;
     int samples;
     int i;
+    int j;
     int test_bps;
     int line_model_no;
     int bits_per_test;
@@ -286,87 +279,81 @@
             exit(2);
         }
     }
-    v22bis_init(&caller, test_bps, 2, TRUE, v22bis_getbit, v22bis_putbit, &caller);
-    v22bis_tx_power(&caller, signal_level);
-    /* Move the carrier off a bit */
-    caller.tx.carrier_phase_rate = dds_phase_ratef(1207.0f);
-    v22bis_init(&answerer, test_bps, 2, FALSE, v22bis_getbit, v22bis_putbit, &answerer);
-    v22bis_tx_power(&answerer, signal_level);
-    answerer.tx.carrier_phase_rate = dds_phase_ratef(2407.0f);
-    v22bis_set_qam_report_handler(&caller, qam_report, (void *) &qam_caller);
-    v22bis_set_qam_report_handler(&answerer, qam_report, (void *) &qam_answerer);
-    span_log_set_level(&caller.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
-    span_log_set_tag(&caller.logging, "caller");
-    span_log_set_level(&answerer.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
-    span_log_set_tag(&answerer.logging, "answerer");
-
-    qam_caller.s = &caller;
-    qam_caller.smooth_power = 0.0f;
-    qam_caller.symbol_no = 0;
-
-    qam_answerer.s = &answerer;
-    qam_answerer.smooth_power = 0.0f;
-    qam_answerer.symbol_no = 0;
+    memset(endpoint, 0, sizeof(endpoint));
 
+    for (i = 0;  i < 2;  i++)
+    {
+        endpoint[i].v22bis = v22bis_init(NULL, test_bps, V22BIS_GUARD_TONE_1800HZ, (i == 0), v22bis_getbit, v22bis_putbit, &endpoint[i]);
+        v22bis_tx_power(endpoint[i].v22bis, signal_level);
+        /* Move the carrier off a bit */
+        endpoint[i].v22bis->tx.carrier_phase_rate = dds_phase_ratef((i == 0)  ?  1207.0f  :  2407.0f);
+        v22bis_set_qam_report_handler(endpoint[i].v22bis, qam_report, (void *) &endpoint[i]);
+        span_log_set_level(&endpoint[i].v22bis->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
+        span_log_set_tag(&endpoint[i].v22bis->logging, (i == 0)  ?  "caller"  :  "answerer");
+        endpoint[i].smooth_power = 0.0f;
+        endpoint[i].symbol_no = 0;
+        bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
+        bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
+        bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]);
+    }
+
+    
 #if defined(ENABLE_GUI)
     if (use_gui)
     {
-        qam_caller.qam_monitor = qam_monitor_init(6.0f, "Calling modem");
-        qam_answerer.qam_monitor = qam_monitor_init(6.0f, "Answering modem");
+        endpoint[0].qam_monitor = qam_monitor_init(6.0f, "Calling modem");
+        endpoint[1].qam_monitor = qam_monitor_init(6.0f, "Answering modem");
     }
 #endif
-
     if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec, 0)) == NULL)
     {
         fprintf(stderr, "    Failed to create line model\n");
         exit(2);
     }
+    samples = 0;
     for (;;)
     {
-        samples = v22bis_tx(&caller, caller_amp, BLOCK_LEN);
-#if defined(ENABLE_GUI)
-        if (use_gui)
-            qam_monitor_update_audio_level(qam_caller.qam_monitor, caller_amp, samples);
-#endif
-        if (samples == 0)
+        for (i = 0;  i < 2;  i++)
         {
-            printf("Restarting on zero output\n");
-            v22bis_restart(&caller, test_bps);
-            rx_ptr = 0;
-            tx_ptr = 0;
-        }
-
-        samples = v22bis_tx(&answerer, answerer_amp, BLOCK_LEN);
+            samples = v22bis_tx(endpoint[i].v22bis, amp[i], BLOCK_LEN);
 #if defined(ENABLE_GUI)
-        if (use_gui)
-            qam_monitor_update_audio_level(qam_answerer.qam_monitor, answerer_amp, samples);
+            if (use_gui)
+                qam_monitor_update_audio_level(endpoint[i].qam_monitor, amp[i], samples);
 #endif
-        if (samples == 0)
-        {
-            printf("Restarting on zero output\n");
-            v22bis_restart(&answerer, test_bps);
-            rx_ptr = 0;
-            tx_ptr = 0;
+            if (samples == 0)
+            {
+                /* Note that we might get a few bad bits as the carrier shuts down. */
+                bert_result(&endpoint[i].bert_rx, &endpoint[i].latest_results);
+
+                bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
+                bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
+                bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]);
+
+                printf("Restarting on zero output\n");
+                v22bis_restart(endpoint[i].v22bis, test_bps);
+            }
         }
 
+#if 0
         both_ways_line_model(model, 
-                             caller_model_amp,
-                             caller_amp,
-                             answerer_model_amp,
-                             answerer_amp,
+                             model_amp[0],
+                             amp[0],
+                             model_amp[1],
+                             amp[1],
                              samples);
-
-        v22bis_rx(&answerer, caller_model_amp, samples);
-        for (i = 0;  i < samples;  i++)
-            out_amp[2*i] = caller_model_amp[i];
-        for (  ;  i < BLOCK_LEN;  i++)
-            out_amp[2*i] = 0;
-
-        v22bis_rx(&caller, answerer_model_amp, samples);
-        for (i = 0;  i < samples;  i++)
-            out_amp[2*i + 1] = answerer_model_amp[i];
-        for (  ;  i < BLOCK_LEN;  i++)
-            out_amp[2*i + 1] = 0;
+#else
+        vec_copyi16(model_amp[0], amp[0], samples);
+        vec_copyi16(model_amp[1], amp[1], samples);
+#endif
+        for (i = 0;  i < 2;  i++)
+        {
+            span_log_bump_samples(&endpoint[i].v22bis->logging, samples);
+            v22bis_rx(endpoint[i ^ 1].v22bis, model_amp[i], samples);
+            for (j = 0;  j < samples;  j++)
+                out_amp[2*j + i] = model_amp[i][j];
+            for (  ;  j < BLOCK_LEN;  j++)
+                out_amp[2*j + i] = 0;
+        }
 
         if (log_audio)
         {

Modified: freeswitch/trunk/libs/spandsp/tests/v27ter_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/v27ter_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/v27ter_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: v27ter_tests.c,v 1.101 2009/02/12 14:21:16 steveu Exp $
+ * $Id: v27ter_tests.c,v 1.103 2009/03/15 09:09:21 steveu Exp $
  */
 
 /*! \page v27ter_tests_page V.27ter modem tests
@@ -171,7 +171,7 @@
 #endif
         error = constel->im*target->re - constel->re*target->im;
         printf("Tracking error %f %f %f %f %f %f\n", error, v27ter_rx_carrier_frequency(rx), constel->re, constel->im, target->re, target->im);
-        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.2f\n",
+        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.4f\n",
                symbol_no,
                constel->re,
                constel->im,
@@ -235,7 +235,7 @@
     int signal_level;
     int bits_per_test;
     int line_model_no;
-    int block;
+    int block_no;
     int log_audio;
     int channel_codec;
     int rbs_pattern;
@@ -368,7 +368,7 @@
 #endif
 
     memset(&latest_results, 0, sizeof(latest_results));
-    for (block = 0;  ;  block++)
+    for (block_no = 0;  ;  block_no++)
     {
         if (decode_test_file)
         {

Modified: freeswitch/trunk/libs/spandsp/tests/v29_tests.c
==============================================================================
--- freeswitch/trunk/libs/spandsp/tests/v29_tests.c	(original)
+++ freeswitch/trunk/libs/spandsp/tests/v29_tests.c	Mon Apr 20 13:33:33 2009
@@ -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: v29_tests.c,v 1.115 2009/02/12 14:21:16 steveu Exp $
+ * $Id: v29_tests.c,v 1.117 2009/03/15 09:09:21 steveu Exp $
  */
 
 /*! \page v29_tests_page V.29 modem tests
@@ -201,7 +201,7 @@
             qam_monitor_update_symbol_tracking(qam_monitor, v29_rx_symbol_timing_correction(rx));
         }
 #endif
-        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.2f\n",
+        printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.4f\n",
                symbol_no,
                constel->re,
                constel->im,
@@ -258,7 +258,7 @@
     int signal_level;
     int bits_per_test;
     int line_model_no;
-    int block;
+    int block_no;
     int log_audio;
     int channel_codec;
     int rbs_pattern;
@@ -398,7 +398,7 @@
 #endif
 
     memset(&latest_results, 0, sizeof(latest_results));
-    for (block = 0;  ;  block++)
+    for (block_no = 0;  ;  block_no++)
     {
         if (decode_test_file)
         {



More information about the Freeswitch-svn mailing list