update spandsp to snapshot spandsp-20091228

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16071 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris 2009-12-29 01:58:30 +00:00
parent 3f9c5d028a
commit 4809a944a0
22 changed files with 1977 additions and 311 deletions

View File

@ -1 +1 @@
Wed Dec 23 11:53:35 EST 2009 Mon Dec 28 20:58:04 EST 2009

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: bitstream.c,v 1.18 2009/02/10 13:06:46 steveu Exp $ * $Id: bitstream.c,v 1.18.4.1 2009/12/28 12:20:46 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -44,88 +44,81 @@
SPAN_DECLARE(void) bitstream_put(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits) SPAN_DECLARE(void) bitstream_put(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits)
{ {
value &= ((1 << bits) - 1); value &= ((1 << bits) - 1);
if (s->residue + bits <= 32) if (s->lsb_first)
{ {
s->bitstream |= (value << s->residue); if (s->residue + bits <= 32)
s->residue += bits; {
s->bitstream |= (value << s->residue);
s->residue += bits;
}
while (s->residue >= 8)
{
s->residue -= 8;
*(*c)++ = (uint8_t) (s->bitstream & 0xFF);
s->bitstream >>= 8;
}
} }
while (s->residue >= 8) else
{ {
s->residue -= 8; if (s->residue + bits <= 32)
*(*c)++ = (uint8_t) (s->bitstream & 0xFF); {
s->bitstream >>= 8; s->bitstream = (s->bitstream << bits) | value;
s->residue += bits;
}
while (s->residue >= 8)
{
s->residue -= 8;
*(*c)++ = (uint8_t) ((s->bitstream >> s->residue) & 0xFF);
}
} }
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) bitstream_put2(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits)
{
value &= ((1 << bits) - 1);
if (s->residue + bits <= 32)
{
s->bitstream = (s->bitstream << bits) | value;
s->residue += bits;
}
while (s->residue >= 8)
{
s->residue -= 8;
*(*c)++ = (uint8_t) ((s->bitstream >> s->residue) & 0xFF);
}
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(uint32_t) bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits)
{
uint32_t x;
while (s->residue < bits)
{
s->bitstream |= (((uint32_t) *(*c)++) << s->residue);
s->residue += 8;
}
s->residue -= bits;
x = s->bitstream & ((1 << bits) - 1);
s->bitstream >>= bits;
return x;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(uint32_t) bitstream_get2(bitstream_state_t *s, const uint8_t **c, int bits)
{
uint32_t x;
while (s->residue < bits)
{
s->bitstream = (s->bitstream << 8) | ((uint32_t) *(*c)++);
s->residue += 8;
}
s->residue -= bits;
x = (s->bitstream >> s->residue) & ((1 << bits) - 1);
return x;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) bitstream_flush(bitstream_state_t *s, uint8_t **c) SPAN_DECLARE(void) bitstream_flush(bitstream_state_t *s, uint8_t **c)
{ {
if (s->residue > 0) if (s->residue > 0)
{ {
*(*c)++ = (uint8_t) ((s->bitstream << (8 - s->residue)) & 0xFF); s->bitstream &= ((1 << s->residue) - 1);
if (s->lsb_first)
*(*c)++ = (uint8_t) s->bitstream;
else
*(*c)++ = (uint8_t) (s->bitstream << (8 - s->residue));
s->residue = 0; s->residue = 0;
} }
s->bitstream = 0;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) bitstream_flush2(bitstream_state_t *s, uint8_t **c) SPAN_DECLARE(uint32_t) bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits)
{ {
if (s->residue > 0) uint32_t x;
if (s->lsb_first)
{ {
*(*c)++ = (uint8_t) ((s->bitstream << (8 - s->residue)) & 0xFF); while (s->residue < bits)
s->residue = 0; {
s->bitstream |= (((uint32_t) *(*c)++) << s->residue);
s->residue += 8;
}
s->residue -= bits;
x = s->bitstream & ((1 << bits) - 1);
s->bitstream >>= bits;
} }
else
{
while (s->residue < bits)
{
s->bitstream = (s->bitstream << 8) | ((uint32_t) *(*c)++);
s->residue += 8;
}
s->residue -= bits;
x = (s->bitstream >> s->residue) & ((1 << bits) - 1);
}
return x;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(bitstream_state_t *) bitstream_init(bitstream_state_t *s) SPAN_DECLARE(bitstream_state_t *) bitstream_init(bitstream_state_t *s, int lsb_first)
{ {
if (s == NULL) if (s == NULL)
{ {
@ -134,6 +127,7 @@ SPAN_DECLARE(bitstream_state_t *) bitstream_init(bitstream_state_t *s)
} }
s->bitstream = 0; s->bitstream = 0;
s->residue = 0; s->residue = 0;
s->lsb_first = lsb_first;
return s; return s;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -48,7 +48,7 @@
* 2550 Garcia Avenue * 2550 Garcia Avenue
* Mountain View, California 94043 * Mountain View, California 94043
* *
* $Id: g726.c,v 1.28 2009/02/10 13:06:46 steveu Exp $ * $Id: g726.c,v 1.28.4.1 2009/12/28 12:20:46 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -1052,7 +1052,7 @@ SPAN_DECLARE(g726_state_t *) g726_init(g726_state_t *s, int bit_rate, int ext_co
s->bits_per_sample = 5; s->bits_per_sample = 5;
break; break;
} }
bitstream_init(&s->bs); bitstream_init(&s->bs, (s->packing != G726_PACKING_LEFT));
return s; return s;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/

View File

@ -25,7 +25,7 @@
* This code is based on the widely used GSM 06.10 code available from * This code is based on the widely used GSM 06.10 code available from
* http://kbs.cs.tu-berlin.de/~jutta/toast.html * http://kbs.cs.tu-berlin.de/~jutta/toast.html
* *
* $Id: gsm0610_rpe.c,v 1.25.4.1 2009/12/19 09:47:56 steveu Exp $ * $Id: gsm0610_rpe.c,v 1.25.4.2 2009/12/28 11:54:58 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -45,6 +45,8 @@
#include "floating_fudge.h" #include "floating_fudge.h"
#include <stdlib.h> #include <stdlib.h>
#include "mmx_sse_decs.h"
#include "spandsp/telephony.h" #include "spandsp/telephony.h"
#include "spandsp/fast_convert.h" #include "spandsp/fast_convert.h"
#include "spandsp/bitstream.h" #include "spandsp/bitstream.h"
@ -55,26 +57,72 @@
/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION */ /* 4.2.13 .. 4.2.17 RPE ENCODING SECTION */
#if defined(__GNUC__) && defined(__i386__)
#define SPANDSP_USE_I386_ASM
#if (defined(__APPLE__) || defined(macintosh)) && defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
#undef SPANDSP_USE_I386_ASM
#endif
#endif
#endif
/* 4.2.13 */ /* 4.2.13 */
static void weighting_filter(const int16_t *e, // signal [-5..0.39.44] IN static void weighting_filter(int16_t x[40],
int16_t x[40]) const int16_t *e) // signal [-5..0.39.44] IN)
{ {
#if defined(SPANDSP_USE_I386_ASM) #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__x86_64__)
/* Table 4.4 Coefficients of the weighting filter */ /* Table 4.4 Coefficients of the weighting filter */
/* This must be padded to a multiple of 4 for MMX to work */ /* This must be padded to a multiple of 4 for MMX to work */
static const union static const union
{ {
int16_t gsm_H[12]; int16_t gsm_H[12];
uint64_t x[3]; __m64 x[3];
} gsm_H =
{
{
-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134, 0
}
};
__asm__ __volatile__(
" emms;\n"
" addq $-10,%%rcx;\n"
" leaq %[gsm_H],%%rax;\n"
" movq (%%rax),%%mm1;\n"
" movq 8(%%rax),%%mm2;\n"
" movq 16(%%rax),%%mm3;\n"
" movq $0x1000,%%rax;\n"
" movq %%rax,%%mm5;\n" /* For rounding */
" xorq %%rsi,%%rsi;\n"
" .p2align 2;\n"
"1:\n"
" movq (%%rcx,%%rsi,2),%%mm0;\n"
" pmaddwd %%mm1,%%mm0;\n"
" movq 8(%%rcx,%%rsi,2),%%mm4;\n"
" pmaddwd %%mm2,%%mm4;\n"
" paddd %%mm4,%%mm0;\n"
" movq 16(%%rcx,%%rsi,2),%%mm4;\n"
" pmaddwd %%mm3,%%mm4;\n"
" paddd %%mm4,%%mm0;\n"
" movq %%mm0,%%mm4;\n"
" punpckhdq %%mm0,%%mm4;\n" /* mm4 has high int32 of mm0 dup'd */
" paddd %%mm4,%%mm0;\n"
" paddd %%mm5,%%mm0;\n" /* Add for roundoff */
" psrad $13,%%mm0;\n"
" packssdw %%mm0,%%mm0;\n"
" movd %%mm0,%%eax;\n" /* eax has result */
" movw %%ax,(%%rdi,%%rsi,2);\n"
" incq %%rsi;\n"
" cmpq $39,%%rsi;\n"
" jle 1b;\n"
" emms;\n"
:
: "c" (e), "D" (x), [gsm_H] "X" (gsm_H)
: "rax", "rdx", "rsi", "memory"
);
#elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__)
/* Table 4.4 Coefficients of the weighting filter */
/* This must be padded to a multiple of 4 for MMX to work */
static const union
{
int16_t gsm_H[12];
__m64_t x[3];
} gsm_H = } gsm_H =
{ {
{ {
@ -86,11 +134,12 @@ static void weighting_filter(const int16_t *e, // signal [-5..0.39.44] IN
__asm__ __volatile__( __asm__ __volatile__(
" emms;\n" " emms;\n"
" addl $-10,%%ecx;\n" " addl $-10,%%ecx;\n"
" leal %[gsm_H],%%eax;\n"
" movq (%%eax),%%mm1;\n"
" movq 8(%%eax),%%mm2;\n"
" movq 16(%%eax),%%mm3;\n"
" movl $0x1000,%%eax;\n" " movl $0x1000,%%eax;\n"
" movd %%eax,%%mm5;\n" /* For rounding */ " movd %%eax,%%mm5;\n" /* For rounding */
" movq %[gsm_H],%%mm1;\n"
" movq %[gsm_H8],%%mm2;\n"
" movq %[gsm_H16],%%mm3;\n"
" xorl %%esi,%%esi;\n" " xorl %%esi,%%esi;\n"
" .p2align 2;\n" " .p2align 2;\n"
"1:\n" "1:\n"
@ -119,8 +168,8 @@ static void weighting_filter(const int16_t *e, // signal [-5..0.39.44] IN
" jle 1b;\n" " jle 1b;\n"
" emms;\n" " emms;\n"
: :
: "c" (e), "D" (x), [gsm_H] "X" (gsm_H.x[0]), [gsm_H8] "X" (gsm_H.x[1]), [gsm_H16] "X" (gsm_H.x[2]) : "c" (e), "D" (x), [gsm_H] "X" (gsm_H)
: "eax", "edx", "esi" : "eax", "edx", "esi", "memory"
); );
#else #else
int32_t L_result; int32_t L_result;
@ -163,13 +212,13 @@ static void weighting_filter(const int16_t *e, // signal [-5..0.39.44] IN
*/ */
L_result += STEP( 0, -134); L_result += STEP( 0, -134);
L_result += STEP( 1, -374); L_result += STEP( 1, -374);
// += STEP( 2, 0 ); /* += STEP( 2, 0 ); */
L_result += STEP( 3, 2054); L_result += STEP( 3, 2054);
L_result += STEP( 4, 5741); L_result += STEP( 4, 5741);
L_result += STEP( 5, 8192); L_result += STEP( 5, 8192);
L_result += STEP( 6, 5741); L_result += STEP( 6, 5741);
L_result += STEP( 7, 2054); L_result += STEP( 7, 2054);
// += STEP( 8, 0 ); /* += STEP( 8, 0 ); */
L_result += STEP( 9, -374); L_result += STEP( 9, -374);
L_result += STEP(10, -134); L_result += STEP(10, -134);
@ -523,7 +572,7 @@ void gsm0610_rpe_encoding(gsm0610_state_t *s,
int16_t mant; int16_t mant;
int16_t exp; int16_t exp;
weighting_filter(e, x); weighting_filter(x, e);
rpe_grid_selection(x, xM, Mc); rpe_grid_selection(x, xM, Mc);
apcm_quantization(xM, xMc, &mant, &exp, xmaxc); apcm_quantization(xM, xMc, &mant, &exp, xmaxc);

View File

@ -26,7 +26,7 @@
* implementation of the LPC-10 2400 bps Voice Coder. They do not * implementation of the LPC-10 2400 bps Voice Coder. They do not
* exert copyright claims on their code, and it may be freely used. * exert copyright claims on their code, and it may be freely used.
* *
* $Id: lpc10_decode.c,v 1.27 2009/02/10 13:06:46 steveu Exp $ * $Id: lpc10_decode.c,v 1.27.4.1 2009/12/24 17:00:19 steveu Exp $
*/ */
#if defined(HAVE_CONFIG_H) #if defined(HAVE_CONFIG_H)
@ -446,8 +446,7 @@ static int pitsyn(lpc10_decode_state_t *s,
xxy = expf(xxy); xxy = expf(xxy);
rci[j + *nout*rci_dim1 + 1] = (xxy - 1.0f)/(xxy + 1.0f); rci[j + *nout*rci_dim1 + 1] = (xxy - 1.0f)/(xxy + 1.0f);
} }
rmsi[*nout - 1] = logf(s->rmso) + prop*(logf(*rms) - logf(s->rmso)); rmsi[*nout - 1] = expf(logf(s->rmso) + prop*(logf(*rms) - logf(s->rmso)));
rmsi[*nout - 1] = expf(rmsi[*nout - 1]);
} }
} }
if (vflag != 1) if (vflag != 1)

View File

@ -23,7 +23,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: make_modem_filter.c,v 1.17 2009/10/03 04:37:25 steveu Exp $ * $Id: make_modem_filter.c,v 1.17.4.1 2009/12/28 12:20:46 steveu Exp $
*/ */
#if defined(HAVE_CONFIG_H) #if defined(HAVE_CONFIG_H)
@ -356,7 +356,7 @@ int main(int argc, char **argv)
break; break;
} }
} }
if (strcmp(modem, "V.17") == 0) if (strcmp(modem, "V.17") == 0 || strcmp(modem, "V.32bis") == 0)
{ {
/* This applies to V.32bis as well as V.17 */ /* This applies to V.32bis as well as V.17 */
rx_coeff_sets = 192; rx_coeff_sets = 192;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: bitstream.h,v 1.14 2009/02/10 13:06:47 steveu Exp $ * $Id: bitstream.h,v 1.14.4.1 2009/12/28 12:20:47 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -39,7 +39,6 @@
/*! Bitstream handler state */ /*! Bitstream handler state */
typedef struct bitstream_state_s bitstream_state_t; typedef struct bitstream_state_s bitstream_state_t;
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" extern "C"
{ {
@ -52,8 +51,6 @@ extern "C"
\param bits The number of bits of value to be pushed. 1 to 25 bits is valid. */ \param bits The number of bits of value to be pushed. 1 to 25 bits is valid. */
SPAN_DECLARE(void) bitstream_put(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits); SPAN_DECLARE(void) bitstream_put(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits);
SPAN_DECLARE(void) bitstream_put2(bitstream_state_t *s, uint8_t **c, uint32_t value, int bits);
/*! \brief Get a chunk of bits from the input buffer. /*! \brief Get a chunk of bits from the input buffer.
\param s A pointer to the bitstream context. \param s A pointer to the bitstream context.
\param c A pointer to the bitstream input buffer. \param c A pointer to the bitstream input buffer.
@ -61,19 +58,16 @@ SPAN_DECLARE(void) bitstream_put2(bitstream_state_t *s, uint8_t **c, uint32_t va
\return The value retrieved from the input buffer. */ \return The value retrieved from the input buffer. */
SPAN_DECLARE(uint32_t) bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits); SPAN_DECLARE(uint32_t) bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits);
SPAN_DECLARE(uint32_t) bitstream_get2(bitstream_state_t *s, const uint8_t **c, int bits);
/*! \brief Flush any residual bit to the output buffer. /*! \brief Flush any residual bit to the output buffer.
\param s A pointer to the bitstream context. \param s A pointer to the bitstream context.
\param c A pointer to the bitstream output buffer. */ \param c A pointer to the bitstream output buffer. */
SPAN_DECLARE(void) bitstream_flush(bitstream_state_t *s, uint8_t **c); SPAN_DECLARE(void) bitstream_flush(bitstream_state_t *s, uint8_t **c);
SPAN_DECLARE(void) bitstream_flush2(bitstream_state_t *s, uint8_t **c);
/*! \brief Initialise a bitstream context. /*! \brief Initialise a bitstream context.
\param s A pointer to the bitstream context. \param s A pointer to the bitstream context.
\param lsb_first TRUE if the bit stream is LSB first, else its MSB first.
\return A pointer to the bitstream context. */ \return A pointer to the bitstream context. */
SPAN_DECLARE(bitstream_state_t *) bitstream_init(bitstream_state_t *s); SPAN_DECLARE(bitstream_state_t *) bitstream_init(bitstream_state_t *s, int direction);
SPAN_DECLARE(int) bitstream_release(bitstream_state_t *s); SPAN_DECLARE(int) bitstream_release(bitstream_state_t *s);

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: bitstream.h,v 1.1 2008/11/30 12:45:09 steveu Exp $ * $Id: bitstream.h,v 1.1.4.1 2009/12/28 12:20:47 steveu Exp $
*/ */
#if !defined(_SPANDSP_PRIVATE_BITSTREAM_H_) #if !defined(_SPANDSP_PRIVATE_BITSTREAM_H_)
@ -35,6 +35,8 @@ struct bitstream_state_s
uint32_t bitstream; uint32_t bitstream;
/*! The residual bits in bitstream. */ /*! The residual bits in bitstream. */
int residue; int residue;
/*! TRUE if the stream is LSB first, else MSB first */
int lsb_first;
}; };

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v17rx.h,v 1.2 2009/07/09 13:52:09 steveu Exp $ * $Id: v17rx.h,v 1.2.4.1 2009/12/24 16:52:30 steveu Exp $
*/ */
#if !defined(_SPANDSP_PRIVATE_V17RX_H_) #if !defined(_SPANDSP_PRIVATE_V17RX_H_)
@ -84,7 +84,10 @@ struct v17_rx_state_s
/*! \brief The state of the differential decoder */ /*! \brief The state of the differential decoder */
int diff; int diff;
/*! \brief The register for the data scrambler. */ /*! \brief The register for the data scrambler. */
unsigned int scramble_reg; uint32_t scramble_reg;
/*! \brief Scrambler tap */
//int scrambler_tap;
/*! \brief TRUE if the short training sequence is to be used. */ /*! \brief TRUE if the short training sequence is to be used. */
int short_train; int short_train;
/*! \brief The section of the training data we are currently in. */ /*! \brief The section of the training data we are currently in. */

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v17tx.h,v 1.2 2009/07/09 13:52:09 steveu Exp $ * $Id: v17tx.h,v 1.2.4.1 2009/12/24 16:52:30 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -71,9 +71,13 @@ struct v17_tx_state_s
int diff; int diff;
/*! \brief The current state of the convolutional encoder. */ /*! \brief The current state of the convolutional encoder. */
int convolution; int convolution;
/*! \brief The code number for the current position in the constellation. */
int constellation_state;
/*! \brief The register for the data scrambler. */ /*! \brief The register for the data scrambler. */
unsigned int scramble_reg; uint32_t scramble_reg;
/*! \brief Scrambler tap */
//int scrambler_tap;
/*! \brief TRUE if transmitting the training sequence. FALSE if transmitting user data. */ /*! \brief TRUE if transmitting the training sequence. FALSE if transmitting user data. */
int in_training; int in_training;
/*! \brief TRUE if the short training sequence is to be used. */ /*! \brief TRUE if the short training sequence is to be used. */
@ -87,8 +91,6 @@ struct v17_tx_state_s
int32_t carrier_phase_rate; int32_t carrier_phase_rate;
/*! \brief The current fractional phase of the baud timing. */ /*! \brief The current fractional phase of the baud timing. */
int baud_phase; int baud_phase;
/*! \brief The code number for the current position in the constellation. */
int constellation_state;
/*! \brief A pointer to the constellation currently in use. */ /*! \brief A pointer to the constellation currently in use. */
#if defined(SPANDSP_USE_FIXED_POINT) #if defined(SPANDSP_USE_FIXED_POINT)

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v8.h,v 1.3 2009/11/04 15:52:06 steveu Exp $ * $Id: v8.h,v 1.3.4.1 2009/12/28 12:20:47 steveu Exp $
*/ */
#if !defined(_SPANDSP_PRIVATE_V8_H_) #if !defined(_SPANDSP_PRIVATE_V8_H_)
@ -50,10 +50,10 @@ struct v8_state_s
modem_connect_tones_rx_state_t ansam_rx; modem_connect_tones_rx_state_t ansam_rx;
/*! \brief Modulation schemes available at this end. */ /*! \brief Modulation schemes available at this end. */
int local_end_modulations; unsigned int far_end_modulations;
int common_modulations;
v8_result_t result; v8_parms_t parms;
v8_parms_t result;
/* V.8 data parsing */ /* V.8 data parsing */
uint32_t bit_stream; uint32_t bit_stream;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v17tx.h,v 1.43 2009/07/09 13:52:09 steveu Exp $ * $Id: v17tx.h,v 1.43.4.1 2009/12/24 16:52:30 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -102,12 +102,12 @@ SPAN_DECLARE(void) v17_tx_power(v17_tx_state_t *s, float power);
use of the context, to initialise its contents. use of the context, to initialise its contents.
\brief Initialise a V.17 modem transmit context. \brief Initialise a V.17 modem transmit context.
\param s The modem context. \param s The modem context.
\param rate The bit rate of the modem. Valid values are 7200, 9600, 12000 and 14400. \param bit_rate The bit rate of the modem. Valid values are 7200, 9600, 12000 and 14400.
\param tep TRUE is the optional TEP tone is to be transmitted. \param tep TRUE is the optional TEP tone is to be transmitted.
\param get_bit The callback routine used to get the data to be transmitted. \param get_bit The callback routine used to get the data to be transmitted.
\param user_data An opaque pointer. \param user_data An opaque pointer.
\return A pointer to the modem context, or NULL if there was a problem. */ \return A pointer to the modem context, or NULL if there was a problem. */
SPAN_DECLARE(v17_tx_state_t *) v17_tx_init(v17_tx_state_t *s, int rate, int tep, get_bit_func_t get_bit, void *user_data); SPAN_DECLARE(v17_tx_state_t *) v17_tx_init(v17_tx_state_t *s, int bit_rate, int tep, get_bit_func_t get_bit, void *user_data);
/*! Reinitialise an existing V.17 modem transmit context, so it may be reused. /*! Reinitialise an existing V.17 modem transmit context, so it may be reused.
\brief Reinitialise an existing V.17 modem transmit context. \brief Reinitialise an existing V.17 modem transmit context.

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v8.h,v 1.31 2009/11/04 16:10:14 steveu Exp $ * $Id: v8.h,v 1.31.4.1 2009/12/28 12:20:47 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -43,9 +43,9 @@ being negotiating and training with their chosen modem standard.
#if !defined(_SPANDSP_V8_H_) #if !defined(_SPANDSP_V8_H_)
#define _SPANDSP_V8_H_ #define _SPANDSP_V8_H_
typedef struct v8_result_s v8_result_t; typedef struct v8_parms_s v8_parms_t;
typedef void (v8_result_handler_t)(void *user_data, v8_result_t *result); typedef void (v8_result_handler_t)(void *user_data, v8_parms_t *result);
enum v8_call_function_e enum v8_call_function_e
{ {
@ -102,18 +102,15 @@ enum v8_pcm_modem_availability_e
typedef struct v8_state_s v8_state_t; typedef struct v8_state_s v8_state_t;
struct v8_result_s struct v8_parms_s
{ {
int modem_connect_tone_detected; int modem_connect_tone;
int call_function; int call_function;
int far_end_modulations; unsigned int modulations;
int negotiated_modulation;
int protocol; int protocol;
int pstn_access; int pstn_access;
int nsf_seen;
int nsf;
int pcm_modem_availability; int pcm_modem_availability;
int t66_seen; int nsf;
int t66; int t66;
}; };
@ -122,20 +119,21 @@ extern "C"
{ {
#endif #endif
SPAN_DECLARE(int) v8_restart(v8_state_t *s,
int calling_party,
v8_parms_t *parms);
/*! Initialise a V.8 context. /*! Initialise a V.8 context.
\brief Initialise a V.8 context. \brief Initialise a V.8 context.
\param s The V.8 context. \param s The V.8 context.
\param calling_party TRUE if caller mode, else answerer mode. \param calling_party TRUE if caller mode, else answerer mode.
\param use_ansam_pr TRUE if ANSam/ is to be used, else ANSam will be used. \param parms The allowed parameters for the call.
\param available_modulations A bitwise list of the modulation schemes to be
advertised as available here.
\param result_handler The callback routine used to handle the results of negotiation. \param result_handler The callback routine used to handle the results of negotiation.
\param user_data An opaque pointer passed to the result_handler routine. \param user_data An opaque pointer passed to the result_handler routine.
\return A pointer to the V.8 context, or NULL if there was a problem. */ \return A pointer to the V.8 context, or NULL if there was a problem. */
SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s, SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s,
int calling_party, int calling_party,
int use_ansam_pr, v8_parms_t *parms,
int available_modulations,
v8_result_handler_t *result_handler, v8_result_handler_t *result_handler,
void *user_data); void *user_data);

View File

@ -30,9 +30,9 @@
/* The date and time of the version are in UTC form. */ /* The date and time of the version are in UTC form. */
#define SPANDSP_RELEASE_DATE 20091223 #define SPANDSP_RELEASE_DATE 20091228
#define SPANDSP_RELEASE_TIME 143600 #define SPANDSP_RELEASE_TIME 123351
#define SPANDSP_RELEASE_DATETIME_STRING "20091223 143600" #define SPANDSP_RELEASE_DATETIME_STRING "20091228 123351"
#endif #endif
/*- End of file ------------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v17_v32bis_tx_constellation_maps.h,v 1.1 2009/06/02 11:51:57 steveu Exp $ * $Id: v17_v32bis_tx_constellation_maps.h,v 1.1.4.1 2009/12/24 16:52:30 steveu Exp $
*/ */
#if defined(SPANDSP_USE_FIXED_POINTx) #if defined(SPANDSP_USE_FIXED_POINTx)
@ -299,16 +299,30 @@ static const complexf_t v17_v32bis_7200_constellation[16] =
{-2, -2} /* 0x0F */ {-2, -2} /* 0x0F */
}; };
/* This one does not exist in V.17 as a data constellation. It is only
the equaliser training constellation. In V.32/V.32bis it is a data mode. */
#if defined(SPANDSP_USE_FIXED_POINTx) #if defined(SPANDSP_USE_FIXED_POINTx)
static const complexi16_t v17_v32bis_4800_constellation[4] = static const complexi16_t v17_v32bis_4800_constellation[4] =
#else #else
static const complexf_t v17_v32bis_4800_constellation[4] = static const complexf_t v17_v32bis_4800_constellation[4] =
#endif #endif
{ {
{-6, -2}, {-6, -2}, /* 0x00 */
{ 2, -6}, {-2, 6}, /* 0x01 */
{ 6, 2}, { 2, -6}, /* 0x02 */
{-2, 6} { 6, 2} /* 0x03 */
};
#if defined(SPANDSP_USE_FIXED_POINTx)
static const complexi16_t v17_v32bis_abcd_constellation[4] =
#else
static const complexf_t v17_v32bis_abcd_constellation[4] =
#endif
{
{-6, -2}, /* A */
{ 2, -6}, /* B */
{ 6, 2}, /* C */
{-2, 6} /* D */
}; };
/*- End of file ------------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v17rx.c,v 1.153.4.4 2009/12/19 14:18:13 steveu Exp $ * $Id: v17rx.c,v 1.153.4.6 2009/12/28 12:20:46 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -297,7 +297,8 @@ static int descramble(v17_rx_state_t *s, int in_bit)
{ {
int out_bit; int out_bit;
out_bit = (in_bit ^ (s->scramble_reg >> 17) ^ (s->scramble_reg >> 22)) & 1; //out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
out_bit = (in_bit ^ (s->scramble_reg >> (18 - 1)) ^ (s->scramble_reg >> (23 - 1))) & 1;
s->scramble_reg <<= 1; s->scramble_reg <<= 1;
if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION && s->training_stage < TRAINING_STAGE_TCM_WINDUP) if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION && s->training_stage < TRAINING_STAGE_TCM_WINDUP)
s->scramble_reg |= out_bit; s->scramble_reg |= out_bit;
@ -361,11 +362,21 @@ static __inline__ float dist_sq(const complexf_t *x, const complexf_t *y)
static int decode_baud(v17_rx_state_t *s, complexf_t *z) static int decode_baud(v17_rx_state_t *s, complexf_t *z)
{ {
static const int diff_code[16] = static const uint8_t v32bis_4800_differential_decoder[4][4] =
{ {
0, 3, 2, 1, 1, 0, 3, 2, 2, 1, 0, 3, 3, 2, 1, 0 {2, 3, 0, 1},
{0, 2, 1, 3},
{3, 1, 2, 0},
{1, 0, 3, 2}
}; };
static const int tcm_paths[8][4] = static const uint8_t v17_differential_decoder[4][4] =
{
{0, 1, 2, 3},
{3, 0, 1, 2},
{2, 3, 0, 1},
{1, 2, 3, 0}
};
static const uint8_t tcm_paths[8][4] =
{ {
{0, 6, 2, 4}, {0, 6, 2, 4},
{6, 0, 4, 2}, {6, 0, 4, 2},
@ -408,6 +419,17 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
else if (im < 0) else if (im < 0)
im = 0; im = 0;
if (s->bits_per_symbol == 2)
{
/* 4800bps V.32bis mode, without trellis coding */
nearest = constel_map_4800[re][im];
raw = v32bis_4800_differential_decoder[s->diff][nearest];
s->diff = nearest;
put_bit(s, raw);
put_bit(s, raw >> 1);
return nearest;
}
/* Find a set of 8 candidate constellation positions, that are the closest /* Find a set of 8 candidate constellation positions, that are the closest
to the target, with different patterns in the last 3 bits. */ to the target, with different patterns in the last 3 bits. */
#if defined(SPANDSP_USE_FIXED_POINTx) #if defined(SPANDSP_USE_FIXED_POINTx)
@ -515,7 +537,7 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
nearest = s->full_path_to_past_state_locations[j][k] >> 1; nearest = s->full_path_to_past_state_locations[j][k] >> 1;
/* Differentially decode */ /* Differentially decode */
raw = (nearest & 0x3C) | diff_code[((nearest & 0x03) << 2) | s->diff]; raw = (nearest & 0x3C) | v17_differential_decoder[s->diff][nearest & 0x03];
s->diff = nearest & 0x03; s->diff = nearest & 0x03;
for (i = 0; i < s->bits_per_symbol; i++) for (i = 0; i < s->bits_per_symbol; i++)
{ {
@ -555,7 +577,7 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
p = v - s->symbol_sync_dc_filter[1]; 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[1] = s->symbol_sync_dc_filter[0];
s->symbol_sync_dc_filter[0] = v; s->symbol_sync_dc_filter[0] = v;
/* A little integration will now filter away much of the noise */ /* A little integration will now filter away much of the HF noise */
s->baud_phase -= p; s->baud_phase -= p;
if (abs(s->baud_phase) > 100*FP_FACTOR) if (abs(s->baud_phase) > 100*FP_FACTOR)
{ {
@ -563,7 +585,6 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
i = (s->baud_phase > 1000*FP_FACTOR) ? 15 : 1; i = (s->baud_phase > 1000*FP_FACTOR) ? 15 : 1;
else else
i = (s->baud_phase < -1000*FP_FACTOR) ? -15 : -1; i = (s->baud_phase < -1000*FP_FACTOR) ? -15 : -1;
//printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction); //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->eq_put_step += i;
s->total_baud_timing_correction += i; s->total_baud_timing_correction += i;
@ -573,14 +594,12 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
v = s->symbol_sync_low[1]*s->symbol_sync_high[0]*SYNC_LOW_BAND_EDGE_COEFF_2 v = s->symbol_sync_low[1]*s->symbol_sync_high[0]*SYNC_LOW_BAND_EDGE_COEFF_2
- s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_2 - s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_2
+ s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_MIXED_EDGES_COEFF_3; + s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_MIXED_EDGES_COEFF_3;
/* Filter away any DC component */ /* Filter away any DC component */
p = v - s->symbol_sync_dc_filter[1]; 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[1] = s->symbol_sync_dc_filter[0];
s->symbol_sync_dc_filter[0] = v; s->symbol_sync_dc_filter[0] = v;
/* A little integration will now filter away much of the HF noise */ /* A little integration will now filter away much of the HF noise */
s->baud_phase -= p; s->baud_phase -= p;
if (fabsf(s->baud_phase) > 100.0f) if (fabsf(s->baud_phase) > 100.0f)
{ {
if (s->baud_phase > 0.0f) if (s->baud_phase > 0.0f)
@ -588,7 +607,6 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
else else
i = (s->baud_phase < -1000.0f) ? -15 : -1; i = (s->baud_phase < -1000.0f) ? -15 : -1;
//printf("v = %10.5f %5d - %f %f %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction); //printf("v = %10.5f %5d - %f %f %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
s->eq_put_step += i; s->eq_put_step += i;
s->total_baud_timing_correction += i; s->total_baud_timing_correction += i;
} }
@ -624,8 +642,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
/* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. */ /* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. */
/* Add a sample to the equalizer's circular buffer, but don't calculate anything /* Add a sample to the equalizer's circular buffer, but don't calculate anything at this time. */
at this time. */
s->eq_buf[s->eq_step] = *sample; s->eq_buf[s->eq_step] = *sample;
if (++s->eq_step >= V17_EQUALIZER_LEN) if (++s->eq_step >= V17_EQUALIZER_LEN)
s->eq_step = 0; s->eq_step = 0;
@ -880,7 +897,18 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
{ {
s->training_count = 0; s->training_count = 0;
s->training_error = 0.0f; s->training_error = 0.0f;
s->training_stage = TRAINING_STAGE_TCM_WINDUP; if (s->bits_per_symbol == 2)
{
/* Restart the differential decoder */
/* There is no trellis, so go straight to processing decoded data */
s->diff = (s->short_train) ? 0 : 1;
s->training_stage = TRAINING_STAGE_TEST_ONES;
}
else
{
/* Wait for the trellis to wind up */
s->training_stage = TRAINING_STAGE_TCM_WINDUP;
}
} }
break; break;
case TRAINING_STAGE_SHORT_WAIT_FOR_CDBA: case TRAINING_STAGE_SHORT_WAIT_FOR_CDBA:
@ -937,7 +965,19 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*4.0f*constellation_spacing[s->space_map]) if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*4.0f*constellation_spacing[s->space_map])
{ {
s->training_count = 0; s->training_count = 0;
s->training_stage = TRAINING_STAGE_TCM_WINDUP; if (s->bits_per_symbol == 2)
{
/* There is no trellis, so go straight to processing decoded data */
/* Restart the differential decoder */
s->diff = (s->short_train) ? 0 : 1;
s->training_error = 0.0f;
s->training_stage = TRAINING_STAGE_TEST_ONES;
}
else
{
/* Wait for the trellis to wind up */
s->training_stage = TRAINING_STAGE_TCM_WINDUP;
}
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS); report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
} }
else else
@ -1254,6 +1294,13 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
s->space_map = 3; s->space_map = 3;
s->bits_per_symbol = 3; s->bits_per_symbol = 3;
break; break;
case 4800:
/* This does not exist in the V.17 spec as a valid mode of operation.
However, it does exist in V.32bis, so it is here for completeness. */
s->constellation = v17_v32bis_4800_constellation;
s->space_map = 0;
s->bits_per_symbol = 2;
break;
default: default:
return -1; return -1;
} }
@ -1306,28 +1353,50 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
s->agc_scaling = s->agc_scaling_save; s->agc_scaling = s->agc_scaling_save;
equalizer_restore(s); equalizer_restore(s);
/* Don't allow any frequency correction at all, until we start to pull the phase in. */ /* Don't allow any frequency correction at all, until we start to pull the phase in. */
#if defined(SPANDSP_USE_FIXED_POINTx)
s->carrier_track_i = 0;
s->carrier_track_p = 40000;
#else
s->carrier_track_i = 0.0f; s->carrier_track_i = 0.0f;
s->carrier_track_p = 40000.0f; s->carrier_track_p = 40000.0f;
#endif
} }
else else
{ {
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ); s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
equalizer_reset(s);
#if defined(SPANDSP_USE_FIXED_POINTx)
s->agc_scaling_save = 0;
s->agc_scaling = (float) FP_FACTOR*32768.0f*0.0017f/RX_PULSESHAPER_GAIN;
s->carrier_track_i = 5000;
s->carrier_track_p = 40000;
#else
s->agc_scaling_save = 0.0f; s->agc_scaling_save = 0.0f;
s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN; s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN;
equalizer_reset(s);
s->carrier_track_i = 5000.0f; s->carrier_track_i = 5000.0f;
s->carrier_track_p = 40000.0f; s->carrier_track_p = 40000.0f;
#endif
} }
s->last_sample = 0; s->last_sample = 0;
/* Initialise the working data for symbol timing synchronisation */ /* Initialise the working data for symbol timing synchronisation */
s->symbol_sync_low[0] = 0.0f; #if defined(SPANDSP_USE_FIXED_POINTx)
s->symbol_sync_low[1] = 0.0f; for (i = 0; i < 2; i++)
s->symbol_sync_high[0] = 0.0f; {
s->symbol_sync_high[1] = 0.0f; s->symbol_sync_low[i] = 0;
s->symbol_sync_dc_filter[0] = 0.0f; s->symbol_sync_high[i] = 0;
s->symbol_sync_dc_filter[1] = 0.0f; s->symbol_sync_dc_filter[i] = 0;
}
s->baud_phase = 0;
#else
for (i = 0; i < 2; i++)
{
s->symbol_sync_low[i] = 0.0f;
s->symbol_sync_high[i] = 0.0f;
s->symbol_sync_dc_filter[i] = 0.0f;
}
s->baud_phase = 0.0f; s->baud_phase = 0.0f;
#endif
s->baud_half = 0; s->baud_half = 0;
s->total_baud_timing_correction = 0; s->total_baud_timing_correction = 0;
@ -1344,6 +1413,8 @@ SPAN_DECLARE(v17_rx_state_t *) v17_rx_init(v17_rx_state_t *s, int bit_rate, put_
case 12000: case 12000:
case 9600: case 9600:
case 7200: case 7200:
case 4800:
/* 4800 is an extension of V.17, to provide full converage of the V.32bis modes */
break; break;
default: default:
return NULL; return NULL;
@ -1359,11 +1430,11 @@ SPAN_DECLARE(v17_rx_state_t *) v17_rx_init(v17_rx_state_t *s, int bit_rate, put_
s->put_bit = put_bit; s->put_bit = put_bit;
s->put_bit_user_data = user_data; s->put_bit_user_data = user_data;
s->short_train = FALSE; s->short_train = FALSE;
//s->scrambler_tap = 18 - 1;
v17_rx_signal_cutoff(s, -45.5f); v17_rx_signal_cutoff(s, -45.5f);
s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN; s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN;
s->agc_scaling_save = 0.0f; s->agc_scaling_save = 0.0f;
s->carrier_phase_rate_save = dds_phase_ratef(CARRIER_NOMINAL_FREQ); s->carrier_phase_rate_save = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
v17_rx_restart(s, bit_rate, s->short_train); v17_rx_restart(s, bit_rate, s->short_train);
return s; return s;
} }

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v17tx.c,v 1.75 2009/06/02 16:03:56 steveu Exp $ * $Id: v17tx.c,v 1.75.4.1 2009/12/24 16:52:30 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -100,7 +100,8 @@ static __inline__ int scramble(v17_tx_state_t *s, int in_bit)
{ {
int out_bit; int out_bit;
out_bit = (in_bit ^ (s->scramble_reg >> 17) ^ (s->scramble_reg >> 22)) & 1; //out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
out_bit = (in_bit ^ (s->scramble_reg >> (18 - 1)) ^ (s->scramble_reg >> (23 - 1))) & 1;
s->scramble_reg = (s->scramble_reg << 1) | out_bit; s->scramble_reg = (s->scramble_reg << 1) | out_bit;
return out_bit; return out_bit;
} }
@ -135,7 +136,7 @@ static __inline__ complexf_t training_get(v17_tx_state_t *s)
if (s->training_step <= V17_TRAINING_SEG_TEP_B) if (s->training_step <= V17_TRAINING_SEG_TEP_B)
{ {
/* Optional segment: Unmodulated carrier (talker echo protection) */ /* Optional segment: Unmodulated carrier (talker echo protection) */
return v17_v32bis_4800_constellation[0]; return v17_v32bis_abcd_constellation[0];
} }
if (s->training_step <= V17_TRAINING_SEG_1) if (s->training_step <= V17_TRAINING_SEG_1)
{ {
@ -143,7 +144,7 @@ static __inline__ complexf_t training_get(v17_tx_state_t *s)
return zero; return zero;
} }
/* Segment 1: ABAB... */ /* Segment 1: ABAB... */
return v17_v32bis_4800_constellation[(s->training_step & 1) ^ 1]; return v17_v32bis_abcd_constellation[(s->training_step & 1) ^ 1];
} }
/* Segment 2: CDBA... */ /* Segment 2: CDBA... */
/* Apply the scrambler */ /* Apply the scrambler */
@ -155,7 +156,7 @@ static __inline__ complexf_t training_get(v17_tx_state_t *s)
/* Go straight to the ones test. */ /* Go straight to the ones test. */
s->training_step = V17_TRAINING_SEG_4; s->training_step = V17_TRAINING_SEG_4;
} }
return v17_v32bis_4800_constellation[s->constellation_state]; return v17_v32bis_abcd_constellation[s->constellation_state];
} }
/* Segment 3: Bridge... */ /* Segment 3: Bridge... */
shift = ((s->training_step - V17_TRAINING_SEG_3 - 1) & 0x7) << 1; shift = ((s->training_step - V17_TRAINING_SEG_3 - 1) & 0x7) << 1;
@ -163,30 +164,53 @@ static __inline__ complexf_t training_get(v17_tx_state_t *s)
bits = scramble(s, V17_BRIDGE_WORD >> shift); bits = scramble(s, V17_BRIDGE_WORD >> shift);
bits = (bits << 1) | scramble(s, V17_BRIDGE_WORD >> (shift + 1)); bits = (bits << 1) | scramble(s, V17_BRIDGE_WORD >> (shift + 1));
s->constellation_state = (s->constellation_state + dibit_to_step[bits]) & 3; s->constellation_state = (s->constellation_state + dibit_to_step[bits]) & 3;
return v17_v32bis_4800_constellation[s->constellation_state]; return v17_v32bis_abcd_constellation[s->constellation_state];
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static __inline__ int diff_and_convolutional_encode(v17_tx_state_t *s, int q) static __inline__ int diff_and_convolutional_encode(v17_tx_state_t *s, int q)
{ {
static const int diff_code[16] = static const uint8_t v32bis_4800_differential_encoder[4][4] =
{ {
0, 1, 2, 3, 1, 2, 3, 0, 2, 3, 0, 1, 3, 0, 1, 2 {2, 3, 0, 1},
{0, 2, 1, 3},
{3, 1, 2, 0},
{1, 0, 3, 2}
};
static const uint8_t v17_differential_encoder[4][4] =
{
{0, 1, 2, 3},
{1, 2, 3, 0},
{2, 3, 0, 1},
{3, 0, 1, 2}
};
static const uint8_t v17_convolutional_coder[8][4] =
{
{0, 2, 3, 1},
{4, 7, 5, 6},
{1, 3, 2, 0},
{7, 4, 6, 5},
{2, 0, 1, 3},
{6, 5, 7, 4},
{3, 1, 0, 2},
{5, 6, 4, 7}
}; };
int y1;
int y2;
int this1;
int this2;
if (s->bits_per_symbol == 2)
{
/* 4800bps mode for V.32bis */
/* There is no trellis. We just differentially encode. */
s->diff = v32bis_4800_differential_encoder[s->diff][q & 0x03];
return s->diff;
}
/* Differentially encode */ /* Differentially encode */
s->diff = diff_code[((q & 0x03) << 2) | s->diff]; s->diff = v17_differential_encoder[s->diff][q & 0x03];
/* Convolutionally encode the redundant bit */ /* Convolutionally encode the redundant bit */
y2 = s->diff >> 1; s->convolution = v17_convolutional_coder[s->convolution][s->diff];
y1 = s->diff;
this2 = y2 ^ y1 ^ (s->convolution >> 2) ^ ((y2 ^ (s->convolution >> 1)) & s->convolution); /* The final result is the combination of some uncoded bits, 2 differentially
this1 = y2 ^ (s->convolution >> 1) ^ (y1 & s->convolution); encoded bits, and the convolutionally encoded redundant bit. */
s->convolution = ((s->convolution & 1) << 2) | ((this2 & 1) << 1) | (this1 & 1);
return ((q << 1) & 0x78) | (s->diff << 1) | ((s->convolution >> 2) & 1); return ((q << 1) & 0x78) | (s->diff << 1) | ((s->convolution >> 2) & 1);
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -373,12 +397,18 @@ SPAN_DECLARE(int) v17_tx_restart(v17_tx_state_t *s, int bit_rate, int tep, int s
s->bits_per_symbol = 3; s->bits_per_symbol = 3;
s->constellation = v17_v32bis_7200_constellation; s->constellation = v17_v32bis_7200_constellation;
break; break;
case 4800:
/* This does not exist in the V.17 spec as a valid mode of operation.
However, it does exist in V.32bis, so it is here for completeness. */
s->bits_per_symbol = 2;
s->constellation = v17_v32bis_4800_constellation;
break;
default: default:
return -1; return -1;
} }
s->bit_rate = bit_rate;
/* NB: some modems seem to use 3 instead of 1 for long training */ /* NB: some modems seem to use 3 instead of 1 for long training */
s->diff = (short_train) ? 0 : 1; s->diff = (short_train) ? 0 : 1;
s->bit_rate = bit_rate;
#if defined(SPANDSP_USE_FIXED_POINT) #if defined(SPANDSP_USE_FIXED_POINT)
memset(s->rrc_filter, 0, sizeof(s->rrc_filter)); memset(s->rrc_filter, 0, sizeof(s->rrc_filter));
#else #else
@ -406,6 +436,8 @@ SPAN_DECLARE(v17_tx_state_t *) v17_tx_init(v17_tx_state_t *s, int bit_rate, int
case 12000: case 12000:
case 9600: case 9600:
case 7200: case 7200:
case 4800:
/* 4800 is an extension of V.17, to provide full converage of the V.32bis modes */
break; break;
default: default:
return NULL; return NULL;
@ -420,6 +452,7 @@ SPAN_DECLARE(v17_tx_state_t *) v17_tx_init(v17_tx_state_t *s, int bit_rate, int
span_log_set_protocol(&s->logging, "V.17 TX"); span_log_set_protocol(&s->logging, "V.17 TX");
s->get_bit = get_bit; s->get_bit = get_bit;
s->get_bit_user_data = user_data; s->get_bit_user_data = user_data;
//s->scrambler_tap = 18 - 1;
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ); s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
v17_tx_power(s, -14.0f); v17_tx_power(s, -14.0f);
v17_tx_restart(s, bit_rate, tep, FALSE); v17_tx_restart(s, bit_rate, tep, FALSE);

View File

@ -23,7 +23,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v29rx.c,v 1.167.4.4 2009/12/19 14:18:13 steveu Exp $ * $Id: v29rx.c,v 1.167.4.5 2009/12/28 12:20:47 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -511,7 +511,7 @@ static __inline__ void symbol_sync(v29_rx_state_t *s)
p = v - s->symbol_sync_dc_filter[1]; 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[1] = s->symbol_sync_dc_filter[0];
s->symbol_sync_dc_filter[0] = v; s->symbol_sync_dc_filter[0] = v;
/* A little integration will now filter away much of the noise */ /* A little integration will now filter away much of the HF noise */
s->baud_phase -= p; s->baud_phase -= p;
if (abs(s->baud_phase) > 30*FP_FACTOR) if (abs(s->baud_phase) > 30*FP_FACTOR)
{ {
@ -519,7 +519,6 @@ static __inline__ void symbol_sync(v29_rx_state_t *s)
i = (s->baud_phase > 1000*FP_FACTOR) ? 5 : 1; i = (s->baud_phase > 1000*FP_FACTOR) ? 5 : 1;
else else
i = (s->baud_phase < -1000*FP_FACTOR) ? -5 : -1; 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); //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->eq_put_step += i;
s->total_baud_timing_correction += i; s->total_baud_timing_correction += i;
@ -533,19 +532,14 @@ static __inline__ void symbol_sync(v29_rx_state_t *s)
p = v - s->symbol_sync_dc_filter[1]; 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[1] = s->symbol_sync_dc_filter[0];
s->symbol_sync_dc_filter[0] = v; s->symbol_sync_dc_filter[0] = v;
/* A little integration will now filter away much of the noise */ /* A little integration will now filter away much of the HF noise */
s->baud_phase -= p; s->baud_phase -= p;
#if 0
if (fabsf(s->baud_phase) > 100.0f)
#else
if (fabsf(s->baud_phase) > 30.0f) if (fabsf(s->baud_phase) > 30.0f)
#endif
{ {
if (s->baud_phase > 0.0f) if (s->baud_phase > 0.0f)
i = (s->baud_phase > 1000.0f) ? 5 : 1; i = (s->baud_phase > 1000.0f) ? 5 : 1;
else else
i = (s->baud_phase < -1000.0f) ? -5 : -1; i = (s->baud_phase < -1000.0f) ? -5 : -1;
//printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction); //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->eq_put_step += i;
s->total_baud_timing_correction += i; s->total_baud_timing_correction += i;
@ -586,8 +580,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
/* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. */ /* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. */
/* Add a sample to the equalizer's circular buffer, but don't calculate anything /* Add a sample to the equalizer's circular buffer, but don't calculate anything at this time. */
at this time. */
s->eq_buf[s->eq_step] = *sample; s->eq_buf[s->eq_step] = *sample;
if (++s->eq_step >= V29_EQUALIZER_LEN) if (++s->eq_step >= V29_EQUALIZER_LEN)
s->eq_step = 0; s->eq_step = 0;
@ -1082,6 +1075,8 @@ SPAN_DECLARE(logging_state_t *) v29_rx_get_logging_state(v29_rx_state_t *s)
SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train) SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
{ {
int i;
switch (bit_rate) switch (bit_rate)
{ {
case 9600: case 9600:
@ -1153,20 +1148,20 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
/* Initialise the working data for symbol timing synchronisation */ /* Initialise the working data for symbol timing synchronisation */
#if defined(SPANDSP_USE_FIXED_POINT) #if defined(SPANDSP_USE_FIXED_POINT)
s->symbol_sync_low[0] = 0; for (i = 0; i < 2; i++)
s->symbol_sync_low[1] = 0; {
s->symbol_sync_high[0] = 0; s->symbol_sync_low[i] = 0;
s->symbol_sync_high[1] = 0; s->symbol_sync_high[i] = 0;
s->symbol_sync_dc_filter[0] = 0; s->symbol_sync_dc_filter[i] = 0;
s->symbol_sync_dc_filter[1] = 0; }
s->baud_phase = 0; s->baud_phase = 0;
#else #else
s->symbol_sync_low[0] = 0.0f; for (i = 0; i < 2; i++)
s->symbol_sync_low[1] = 0.0f; {
s->symbol_sync_high[0] = 0.0f; s->symbol_sync_low[i] = 0.0f;
s->symbol_sync_high[1] = 0.0f; s->symbol_sync_high[i] = 0.0f;
s->symbol_sync_dc_filter[0] = 0.0f; s->symbol_sync_dc_filter[i] = 0.0f;
s->symbol_sync_dc_filter[1] = 0.0f; }
s->baud_phase = 0.0f; s->baud_phase = 0.0f;
#endif #endif
s->baud_half = 0; s->baud_half = 0;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v8.c,v 1.42.4.1 2009/12/23 14:23:49 steveu Exp $ * $Id: v8.c,v 1.42.4.3 2009/12/28 12:20:47 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -298,7 +298,7 @@ static const uint8_t *process_call_function(v8_state_t *s, const uint8_t *p)
static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p) static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
{ {
int far_end_modulations; unsigned int far_end_modulations;
/* Modulation mode octet */ /* Modulation mode octet */
far_end_modulations = 0; far_end_modulations = 0;
@ -338,8 +338,9 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
far_end_modulations |= V8_MOD_V26TER; far_end_modulations |= V8_MOD_V26TER;
} }
} }
s->result.far_end_modulations = far_end_modulations; s->far_end_modulations =
v8_log_supported_modulations(s, s->result.far_end_modulations); s->result.modulations = far_end_modulations;
v8_log_supported_modulations(s, far_end_modulations);
return ++p; return ++p;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -363,7 +364,6 @@ static const uint8_t *process_pstn_access(v8_state_t *s, const uint8_t *p)
static const uint8_t *process_non_standard_facilities(v8_state_t *s, const uint8_t *p) static const uint8_t *process_non_standard_facilities(v8_state_t *s, const uint8_t *p)
{ {
s->result.nsf = (*p >> 5) & 0x07; s->result.nsf = (*p >> 5) & 0x07;
s->result.nsf_seen = TRUE;
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s\n", v8_nsf_to_str(s->result.nsf)); span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s\n", v8_nsf_to_str(s->result.nsf));
return p; return p;
} }
@ -380,7 +380,6 @@ static const uint8_t *process_pcm_modem_availability(v8_state_t *s, const uint8_
static const uint8_t *process_t66(v8_state_t *s, const uint8_t *p) static const uint8_t *process_t66(v8_state_t *s, const uint8_t *p)
{ {
s->result.t66 = (*p >> 5) & 0x07; s->result.t66 = (*p >> 5) & 0x07;
s->result.t66_seen = TRUE;
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s\n", v8_t66_to_str(s->result.t66)); span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s\n", v8_t66_to_str(s->result.t66));
return ++p; return ++p;
} }
@ -420,7 +419,7 @@ static void cm_jm_decode(v8_state_t *s)
/* Zero indicates the end */ /* Zero indicates the end */
s->cm_jm_data[s->cm_jm_len] = 0; s->cm_jm_data[s->cm_jm_len] = 0;
s->result.far_end_modulations = 0; s->result.modulations = 0;
p = s->cm_jm_data; p = s->cm_jm_data;
while (*p) while (*p)
@ -585,6 +584,7 @@ static void v8_decode_init(v8_state_t *s)
FSK_FRAME_MODE_ASYNC, FSK_FRAME_MODE_ASYNC,
put_bit, put_bit,
s); s);
fsk_rx_signal_cutoff(&s->v21rx, -45.5f);
s->preamble_type = V8_SYNC_UNKNOWN; s->preamble_type = V8_SYNC_UNKNOWN;
s->bit_stream = 0; s->bit_stream = 0;
s->cm_jm_len = 0; s->cm_jm_len = 0;
@ -635,72 +635,64 @@ static void v8_put_byte(v8_state_t *s, int data)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void send_cm_jm(v8_state_t *s, int mod_mask) static void send_cm_jm(v8_state_t *s)
{ {
int val; int val;
unsigned int offered_modulations;
offered_modulations = s->parms.modulations & s->far_end_modulations;
/* Send a CM, or a JM as appropriate */ /* Send a CM, or a JM as appropriate */
v8_put_preamble(s); v8_put_preamble(s);
v8_put_byte(s, V8_CM_JM_SYNC_OCTET); v8_put_byte(s, V8_CM_JM_SYNC_OCTET);
/* Data call */ /* Data call */
v8_put_byte(s, (V8_CALL_V_SERIES << 5) | V8_CALL_FUNCTION_TAG); v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG);
/* Supported modulations */ /* Supported modulations */
val = 0x05; val = 0x05;
if (mod_mask & V8_MOD_V90) if (offered_modulations & V8_MOD_V90)
val |= 0x20; val |= 0x20;
if (mod_mask & V8_MOD_V34) if (offered_modulations & V8_MOD_V34)
val |= 0x40; val |= 0x40;
v8_put_byte(s, val); v8_put_byte(s, val);
val = 0x10; val = 0x10;
if (mod_mask & V8_MOD_V32) if (offered_modulations & V8_MOD_V32)
val |= 0x01; val |= 0x01;
if (mod_mask & V8_MOD_V22) if (offered_modulations & V8_MOD_V22)
val |= 0x02; val |= 0x02;
if (mod_mask & V8_MOD_V17) if (offered_modulations & V8_MOD_V17)
val |= 0x04; val |= 0x04;
if (mod_mask & V8_MOD_V29) if (offered_modulations & V8_MOD_V29)
val |= 0x40; val |= 0x40;
if (mod_mask & V8_MOD_V27TER) if (offered_modulations & V8_MOD_V27TER)
val |= 0x80; val |= 0x80;
v8_put_byte(s, val); v8_put_byte(s, val);
val = 0x10; val = 0x10;
if (mod_mask & V8_MOD_V26TER) if (offered_modulations & V8_MOD_V26TER)
val |= 0x01; val |= 0x01;
if (mod_mask & V8_MOD_V26BIS) if (offered_modulations & V8_MOD_V26BIS)
val |= 0x02; val |= 0x02;
if (mod_mask & V8_MOD_V23) if (offered_modulations & V8_MOD_V23)
val |= 0x04; val |= 0x04;
if (mod_mask & V8_MOD_V23HALF) if (offered_modulations & V8_MOD_V23HALF)
val |= 0x40; val |= 0x40;
if (mod_mask & V8_MOD_V21) if (offered_modulations & V8_MOD_V21)
val |= 0x80; val |= 0x80;
v8_put_byte(s, val); v8_put_byte(s, val);
v8_put_byte(s, (0 << 5) | V8_PCM_MODEM_AVAILABILITY_TAG); if (s->parms.protocol)
v8_put_byte(s, (s->parms.protocol << 5) | V8_PROTOCOLS_TAG);
if (s->parms.pcm_modem_availability)
v8_put_byte(s, (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG);
if (s->parms.pstn_access)
v8_put_byte(s, (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG);
if (s->parms.t66 >= 0)
v8_put_byte(s, (s->parms.t66 << 5) | V8_T66_TAG);
v8_put_byte(s, (V8_PROTOCOL_LAPM_V42 << 5) | V8_PROTOCOLS_TAG); /* No NSF */
//v8_put_byte(s, (0 << 5) | V8_NSF_TAG);
/* No cellular right now */
v8_put_byte(s, (0 << 5) | V8_PSTN_ACCESS_TAG);
}
/*- End of function --------------------------------------------------------*/
static int select_modulation(int mask)
{
if (mask & V8_MOD_V90)
return V8_MOD_V90;
if (mask & V8_MOD_V34)
return V8_MOD_V34;
if (mask & V8_MOD_V32)
return V8_MOD_V32;
if (mask & V8_MOD_V23)
return V8_MOD_V23;
if (mask & V8_MOD_V21)
return V8_MOD_V21;
return V8_MOD_FAILED;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -724,6 +716,7 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
} }
else else
{ {
/* Send the 75ms of silence after the ANSam tone */
if (max_len > s->modem_connect_tone_tx_on) if (max_len > s->modem_connect_tone_tx_on)
len = s->modem_connect_tone_tx_on; len = s->modem_connect_tone_tx_on;
else else
@ -755,14 +748,14 @@ static void v8_send_ci(v8_state_t *s)
{ {
v8_put_preamble(s); v8_put_preamble(s);
v8_put_byte(s, V8_CI_SYNC_OCTET); v8_put_byte(s, V8_CI_SYNC_OCTET);
v8_put_byte(s, (V8_CALL_V_SERIES << 5) | V8_CALL_FUNCTION_TAG); v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG);
} }
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
static void handle_modem_connect_tone(v8_state_t *s, int tone) static void handle_modem_connect_tone(v8_state_t *s, int tone)
{ {
s->result.modem_connect_tone_detected = tone; s->result.modem_connect_tone = tone;
span_log(&s->logging, SPAN_LOG_FLOW, "'%s' recognised\n", modem_connect_tone_to_str(tone)); span_log(&s->logging, SPAN_LOG_FLOW, "'%s' recognised\n", modem_connect_tone_to_str(tone));
if (tone == MODEM_CONNECT_TONES_ANSAM if (tone == MODEM_CONNECT_TONES_ANSAM
|| ||
@ -856,7 +849,7 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
v8_decode_init(s); v8_decode_init(s);
s->negotiation_timer = ms_to_samples(5000); s->negotiation_timer = ms_to_samples(5000);
fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]); fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
send_cm_jm(s, s->local_end_modulations); send_cm_jm(s);
s->state = V8_CM_ON; s->state = V8_CM_ON;
s->fsk_tx_on = TRUE; s->fsk_tx_on = TRUE;
} }
@ -868,8 +861,6 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
span_log(&s->logging, SPAN_LOG_FLOW, "JM recognised\n"); span_log(&s->logging, SPAN_LOG_FLOW, "JM recognised\n");
/* Now JM has been detected, we send CJ and wait for 75 ms /* Now JM has been detected, we send CJ and wait for 75 ms
before finishing the V.8 analysis. */ before finishing the V.8 analysis. */
s->result.negotiated_modulation = select_modulation(s->result.far_end_modulations);
fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]); fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
v8_put_byte(s, 0); v8_put_byte(s, 0);
@ -888,7 +879,7 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
if (queue_contents(s->tx_queue) < 10) if (queue_contents(s->tx_queue) < 10)
{ {
/* Send CM again */ /* Send CM again */
send_cm_jm(s, s->local_end_modulations); send_cm_jm(s);
} }
break; break;
case V8_CJ_ON: case V8_CJ_ON:
@ -914,14 +905,15 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
if (s->got_cm_jm) if (s->got_cm_jm)
{ {
span_log(&s->logging, SPAN_LOG_FLOW, "CM recognised\n"); span_log(&s->logging, SPAN_LOG_FLOW, "CM recognised\n");
/* TODO: negotiate if the call function is acceptable */
/* Stop sending ANSam or ANSam/ and send JM instead */ /* Stop sending ANSam or ANSam/ and send JM instead */
fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH2], get_bit, s); fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH2], get_bit, s);
/* Set the timeout for JM */ /* Set the timeout for JM */
s->negotiation_timer = ms_to_samples(5000); s->negotiation_timer = ms_to_samples(5000);
s->state = V8_JM_ON; s->state = V8_JM_ON;
s->common_modulations = s->local_end_modulations & s->result.far_end_modulations; send_cm_jm(s);
s->result.negotiated_modulation = select_modulation(s->common_modulations);
send_cm_jm(s, s->common_modulations);
s->modem_connect_tone_tx_on = ms_to_samples(75); s->modem_connect_tone_tx_on = ms_to_samples(75);
s->fsk_tx_on = TRUE; s->fsk_tx_on = TRUE;
break; break;
@ -958,7 +950,7 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
if (queue_contents(s->tx_queue) < 10) if (queue_contents(s->tx_queue) < 10)
{ {
/* Send JM */ /* Send JM */
send_cm_jm(s, s->common_modulations); send_cm_jm(s);
} }
break; break;
case V8_SIGA: case V8_SIGA:
@ -985,24 +977,16 @@ SPAN_DECLARE(logging_state_t *) v8_get_logging_state(v8_state_t *s)
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s, SPAN_DECLARE(int) v8_restart(v8_state_t *s,
int calling_party, int calling_party,
int use_ansam_pr, v8_parms_t *parms)
int available_modulations,
v8_result_handler_t *result_handler,
void *user_data)
{ {
if (s == NULL) memcpy(&s->parms, parms, sizeof(s->parms));
{ memset(&s->result, 0, sizeof(s->result));
if ((s = (v8_state_t *) malloc(sizeof(*s))) == NULL)
return NULL; s->result.call_function = s->parms.call_function;
} s->result.nsf = -1;
memset(s, 0, sizeof(*s)); s->result.t66 = -1;
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
span_log_set_protocol(&s->logging, "V.8");
s->local_end_modulations = available_modulations;
s->result_handler = result_handler;
s->result_handler_user_data = user_data;
s->ci_timer = 0; s->ci_timer = 0;
if (calling_party) if (calling_party)
@ -1018,15 +1002,68 @@ SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s,
{ {
/* Send the ANSam or ANSam/ tone */ /* Send the ANSam or ANSam/ tone */
s->calling_party = FALSE; s->calling_party = FALSE;
modem_connect_tones_tx_init(&s->ansam_tx, modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
(use_ansam_pr) ? MODEM_CONNECT_TONES_ANSAM_PR : MODEM_CONNECT_TONES_ANSAM);
v8_decode_init(s); v8_decode_init(s);
s->state = V8_CM_WAIT; s->state = V8_CM_WAIT;
s->negotiation_timer = ms_to_samples(200 + 5000); s->negotiation_timer = ms_to_samples(200 + 5000);
s->modem_connect_tone_tx_on = ms_to_samples(75) + 1; s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
} }
s->result.modem_connect_tone_detected = MODEM_CONNECT_TONES_NONE; s->result.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
if ((s->tx_queue = queue_init(NULL, 1024, 0)) == NULL)
return -1;
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s,
int calling_party,
v8_parms_t *parms,
v8_result_handler_t *result_handler,
void *user_data)
{
if (s == NULL)
{
if ((s = (v8_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
span_log_set_protocol(&s->logging, "V.8");
s->result_handler = result_handler;
s->result_handler_user_data = user_data;
v8_restart(s, calling_party, parms);
memcpy(&s->parms, parms, sizeof(s->parms));
s->result.call_function = s->parms.call_function;
s->result.nsf = -1;
s->result.t66 = -1;
s->ci_timer = 0;
if (calling_party)
{
s->calling_party = TRUE;
s->state = V8_WAIT_1S;
s->negotiation_timer = ms_to_samples(1000);
s->ci_count = 0;
modem_connect_tones_rx_init(&s->ansam_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH1], get_bit, s);
}
else
{
/* Send the ANSam or ANSam/ tone */
s->calling_party = FALSE;
modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
v8_decode_init(s);
s->state = V8_CM_WAIT;
s->negotiation_timer = ms_to_samples(200 + 5000);
s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
}
s->result.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
if ((s->tx_queue = queue_init(NULL, 1024, 0)) == NULL) if ((s->tx_queue = queue_init(NULL, 1024, 0)) == NULL)
return NULL; return NULL;

View File

@ -22,7 +22,7 @@
* License along with this program; if not, write to the Free Software * License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: vector_int.c,v 1.26 2009/07/12 09:23:09 steveu Exp $ * $Id: vector_int.c,v 1.26.4.1 2009/12/28 11:54:59 steveu Exp $
*/ */
/*! \file */ /*! \file */
@ -53,8 +53,7 @@ SPAN_DECLARE(int32_t) vec_dot_prodi16(const int16_t x[], const int16_t y[], int
{ {
int32_t z; int32_t z;
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX) #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__x86_64__)
#if defined(__x86_64__)
__asm__ __volatile__( __asm__ __volatile__(
" emms;\n" " emms;\n"
" pxor %%mm0,%%mm0;\n" " pxor %%mm0,%%mm0;\n"
@ -152,7 +151,7 @@ SPAN_DECLARE(int32_t) vec_dot_prodi16(const int16_t x[], const int16_t y[], int
: "S" (x), "D" (y), "a" (n) : "S" (x), "D" (y), "a" (n)
: "cc" : "cc"
); );
#else #elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__)
__asm__ __volatile__( __asm__ __volatile__(
" emms;\n" " emms;\n"
" pxor %%mm0,%%mm0;\n" " pxor %%mm0,%%mm0;\n"
@ -250,7 +249,6 @@ SPAN_DECLARE(int32_t) vec_dot_prodi16(const int16_t x[], const int16_t y[], int
: "S" (x), "D" (y), "a" (n) : "S" (x), "D" (y), "a" (n)
: "cc" : "cc"
); );
#endif
#else #else
int i; int i;
@ -290,12 +288,11 @@ SPAN_DECLARE(void) vec_circular_lmsi16(const int16_t x[], int16_t y[], int n, in
SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[]) SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
{ {
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX) #if defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__x86_64__)
static const int32_t lower_bound = 0x80008000; static const int32_t lower_bound = 0x80008000;
static const int32_t upper_bound = 0x7FFF7FFF; static const int32_t upper_bound = 0x7FFF7FFF;
int32_t max; int32_t max;
#if defined(__x86_64__)
__asm__ __volatile__( __asm__ __volatile__(
" emms;\n" " emms;\n"
" pushq %%rdx;\n" " pushq %%rdx;\n"
@ -443,7 +440,11 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
: "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound) : "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
: "ecx" : "ecx"
); );
#else #elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__)
static const int32_t lower_bound = 0x80008000;
static const int32_t upper_bound = 0x7FFF7FFF;
int32_t max;
__asm__ __volatile__( __asm__ __volatile__(
" emms;\n" " emms;\n"
" pushl %%edx;\n" " pushl %%edx;\n"
@ -592,8 +593,6 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
: "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound) : "S" (x), "a" (n), "d" (out), [lower] "m" (lower_bound), [upper] "m" (upper_bound)
: "ecx" : "ecx"
); );
#endif
return max;
#else #else
int i; int i;
int16_t min; int16_t min;
@ -622,8 +621,8 @@ SPAN_DECLARE(int32_t) vec_min_maxi16(const int16_t x[], int n, int16_t out[])
z = abs(min); z = abs(min);
if (z > max) if (z > max)
return z; return z;
return max;
#endif #endif
return max;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/

View File

@ -22,16 +22,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: v8_tests.c,v 1.36 2009/11/04 16:10:14 steveu Exp $ * $Id: v8_tests.c,v 1.36.4.1 2009/12/28 12:32:53 steveu Exp $
*/ */
/*! \page v8_tests_page V.8 tests /*! \page v8_tests_page V.8 tests
\section v8_tests_page_sec_1 What does it do? \section v8_tests_page_sec_1 What does it do?
*/ */
/* Enable the following definition to enable direct probing into the internal structures */
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H) #if defined(HAVE_CONFIG_H)
#include "config.h" #include "config.h"
#endif #endif
@ -59,7 +56,24 @@
int negotiations_ok = 0; int negotiations_ok = 0;
static void handler(void *user_data, v8_result_t *result) static int select_modulation(int mask)
{
/* Select the fastest data modem available */
if (mask & V8_MOD_V90)
return V8_MOD_V90;
if (mask & V8_MOD_V34)
return V8_MOD_V34;
if (mask & V8_MOD_V32)
return V8_MOD_V32;
if (mask & V8_MOD_V23)
return V8_MOD_V23;
if (mask & V8_MOD_V21)
return V8_MOD_V21;
return V8_MOD_FAILED;
}
/*- End of function --------------------------------------------------------*/
static void handler(void *user_data, v8_parms_t *result)
{ {
const char *s; const char *s;
@ -70,24 +84,24 @@ static void handler(void *user_data, v8_result_t *result)
printf("%s V.8 negotiation failed\n", s); printf("%s V.8 negotiation failed\n", s);
return; return;
} }
if (result->modem_connect_tone_detected == MODEM_CONNECT_TONES_ANSAM if (result->modem_connect_tone == MODEM_CONNECT_TONES_ANSAM
|| ||
result->modem_connect_tone_detected == MODEM_CONNECT_TONES_ANSAM_PR result->modem_connect_tone == MODEM_CONNECT_TONES_ANSAM_PR
|| ||
result->modem_connect_tone_detected == MODEM_CONNECT_TONES_NONE) result->modem_connect_tone == MODEM_CONNECT_TONES_NONE)
{ {
printf("%s V.8 negotiation result:\n", s); printf("%s V.8 negotiation result:\n", s);
printf(" Modem connect tone '%s'\n", modem_connect_tone_to_str(result->modem_connect_tone_detected)); printf(" Modem connect tone '%s' (%d)\n", modem_connect_tone_to_str(result->modem_connect_tone), result->modem_connect_tone);
printf(" Call function '%s'\n", v8_call_function_to_str(result->call_function)); printf(" Call function '%s' (%d)\n", v8_call_function_to_str(result->call_function), result->call_function);
printf(" Negotiated modulation '%s'\n", v8_modulation_to_str(result->negotiated_modulation)); printf(" Far end modulations 0x%X\n", result->modulations);
printf(" Protocol '%s'\n", v8_protocol_to_str(result->protocol)); printf(" Protocol '%s' (%d)\n", v8_protocol_to_str(result->protocol), result->protocol);
printf(" PSTN access '%s'\n", v8_pstn_access_to_str(result->pstn_access)); printf(" PSTN access '%s' (%d)\n", v8_pstn_access_to_str(result->pstn_access), result->pstn_access);
printf(" NSF %d %d\n", result->nsf_seen, result->nsf); printf(" PCM modem availability '%s' (%d)\n", v8_pcm_modem_availability_to_str(result->pcm_modem_availability), result->pcm_modem_availability);
printf(" PCM modem availability '%s'\n", v8_pcm_modem_availability_to_str(result->pcm_modem_availability)); if (result->t66 >= 0)
printf(" T.66 %d %d\n", result->t66_seen, result->t66); printf(" T.66 '%s' (%d)\n", v8_t66_to_str(result->t66), result->t66);
if (result->nsf >= 0)
printf(" NSF %d\n", result->nsf);
if (result->call_function == V8_CALL_V_SERIES if (result->call_function == V8_CALL_V_SERIES
&&
result->negotiated_modulation == V8_MOD_V90
&& &&
result->protocol == V8_PROTOCOL_LAPM_V42) result->protocol == V8_PROTOCOL_LAPM_V42)
{ {
@ -97,7 +111,7 @@ static void handler(void *user_data, v8_result_t *result)
else else
{ {
printf("%s V.8 negotiation result:\n", s); printf("%s V.8 negotiation result:\n", s);
printf(" Modem connect tone '%s'\n", modem_connect_tone_to_str(result->modem_connect_tone_detected)); printf(" Modem connect tone '%s' (%d)\n", modem_connect_tone_to_str(result->modem_connect_tone), result->modem_connect_tone);
} }
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -116,6 +130,8 @@ static int v8_calls_v8_tests(SNDFILE *outhandle)
int outframes; int outframes;
int16_t amp[SAMPLES_PER_CHUNK]; int16_t amp[SAMPLES_PER_CHUNK];
int16_t out_amp[2*SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK];
v8_parms_t v8_call_parms;
v8_parms_t v8_answer_parms;
caller_available_modulations = V8_MOD_V17 caller_available_modulations = V8_MOD_V17
| V8_MOD_V21 | V8_MOD_V21
@ -147,8 +163,32 @@ static int v8_calls_v8_tests(SNDFILE *outhandle)
| V8_MOD_V92; | V8_MOD_V92;
negotiations_ok = 0; negotiations_ok = 0;
v8_caller = v8_init(NULL, TRUE, TRUE, caller_available_modulations, handler, (void *) "caller"); v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
v8_answerer = v8_init(NULL, FALSE, TRUE, answerer_available_modulations, handler, (void *) "answerer"); v8_call_parms.call_function = V8_CALL_V_SERIES;
v8_call_parms.modulations = caller_available_modulations;
v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42;
v8_call_parms.pcm_modem_availability = 0;
v8_call_parms.pstn_access = 0;
v8_call_parms.nsf = -1;
v8_call_parms.t66 = -1;
v8_caller = v8_init(NULL,
TRUE,
&v8_call_parms,
handler,
(void *) "caller");
v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_answer_parms.call_function = V8_CALL_V_SERIES;
v8_answer_parms.modulations = answerer_available_modulations;
v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42;
v8_answer_parms.pcm_modem_availability = 0;
v8_answer_parms.pstn_access = 0;
v8_answer_parms.nsf = -1;
v8_answer_parms.t66 = -1;
v8_answerer = v8_init(NULL,
FALSE,
&v8_answer_parms,
handler,
(void *) "answerer");
caller_logging = v8_get_logging_state(v8_caller); caller_logging = v8_get_logging_state(v8_caller);
span_log_set_level(caller_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_level(caller_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
span_log_set_tag(caller_logging, "caller"); span_log_set_tag(caller_logging, "caller");
@ -213,6 +253,7 @@ static int non_v8_calls_v8_tests(SNDFILE *outhandle)
int tone; int tone;
int16_t amp[SAMPLES_PER_CHUNK]; int16_t amp[SAMPLES_PER_CHUNK];
int16_t out_amp[2*SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK];
v8_parms_t v8_answer_parms;
answerer_available_modulations = V8_MOD_V17 answerer_available_modulations = V8_MOD_V17
| V8_MOD_V21 | V8_MOD_V21
@ -232,7 +273,20 @@ static int non_v8_calls_v8_tests(SNDFILE *outhandle)
non_v8_caller_tx = silence_gen_init(NULL, 10*SAMPLE_RATE); non_v8_caller_tx = silence_gen_init(NULL, 10*SAMPLE_RATE);
non_v8_caller_rx = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL); non_v8_caller_rx = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
v8_answerer = v8_init(NULL, FALSE, TRUE, answerer_available_modulations, handler, (void *) "answerer");
v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_answer_parms.call_function = V8_CALL_V_SERIES;
v8_answer_parms.modulations = answerer_available_modulations;
v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42;
v8_answer_parms.pcm_modem_availability = 0;
v8_answer_parms.pstn_access = 0;
v8_answer_parms.nsf = -1;
v8_answer_parms.t66 = -1;
v8_answerer = v8_init(NULL,
FALSE,
&v8_answer_parms,
handler,
(void *) "answerer");
answerer_logging = v8_get_logging_state(v8_answerer); answerer_logging = v8_get_logging_state(v8_answerer);
span_log_set_level(answerer_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_level(answerer_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
span_log_set_tag(answerer_logging, "answerer"); span_log_set_tag(answerer_logging, "answerer");
@ -298,6 +352,7 @@ static int v8_calls_non_v8_tests(SNDFILE *outhandle)
int outframes; int outframes;
int16_t amp[SAMPLES_PER_CHUNK]; int16_t amp[SAMPLES_PER_CHUNK];
int16_t out_amp[2*SAMPLES_PER_CHUNK]; int16_t out_amp[2*SAMPLES_PER_CHUNK];
v8_parms_t v8_call_parms;
caller_available_modulations = V8_MOD_V17 caller_available_modulations = V8_MOD_V17
| V8_MOD_V21 | V8_MOD_V21
@ -315,7 +370,19 @@ static int v8_calls_non_v8_tests(SNDFILE *outhandle)
| V8_MOD_V92; | V8_MOD_V92;
negotiations_ok = 0; negotiations_ok = 0;
v8_caller = v8_init(NULL, TRUE, TRUE, caller_available_modulations, handler, (void *) "caller"); v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
v8_call_parms.call_function = V8_CALL_V_SERIES;
v8_call_parms.modulations = caller_available_modulations;
v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42;
v8_call_parms.pcm_modem_availability = 0;
v8_call_parms.pstn_access = 0;
v8_call_parms.nsf = -1;
v8_call_parms.t66 = -1;
v8_caller = v8_init(NULL,
TRUE,
&v8_call_parms,
handler,
(void *) "caller");
non_v8_answerer_tx = modem_connect_tones_tx_init(NULL, MODEM_CONNECT_TONES_ANS_PR); non_v8_answerer_tx = modem_connect_tones_tx_init(NULL, MODEM_CONNECT_TONES_ANS_PR);
caller_logging = v8_get_logging_state(v8_caller); caller_logging = v8_get_logging_state(v8_caller);
span_log_set_level(caller_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); span_log_set_level(caller_logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
@ -375,7 +442,10 @@ int main(int argc, char *argv[])
SNDFILE *outhandle; SNDFILE *outhandle;
int opt; int opt;
char *decode_test_file; char *decode_test_file;
v8_state_t *v8_caller;
v8_state_t *v8_answerer; v8_state_t *v8_answerer;
v8_parms_t v8_call_parms;
v8_parms_t v8_answer_parms;
logging_state_t *logging; logging_state_t *logging;
decode_test_file = NULL; decode_test_file = NULL;
@ -450,10 +520,40 @@ int main(int argc, char *argv[])
else else
{ {
printf("Decode file '%s'\n", decode_test_file); printf("Decode file '%s'\n", decode_test_file);
v8_answerer = v8_init(NULL, FALSE, TRUE, answerer_available_modulations, handler, (void *) "answerer"); v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
v8_call_parms.call_function = V8_CALL_V_SERIES;
v8_call_parms.modulations = caller_available_modulations;
v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42;
v8_call_parms.pcm_modem_availability = 0;
v8_call_parms.pstn_access = 0;
v8_call_parms.nsf = -1;
v8_call_parms.t66 = -1;
v8_caller = v8_init(NULL,
TRUE,
&v8_call_parms,
handler,
(void *) "caller");
logging = v8_get_logging_state(v8_caller);
span_log_set_level(logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG);
span_log_set_tag(logging, "caller");
v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_answer_parms.call_function = V8_CALL_V_SERIES;
v8_answer_parms.modulations = answerer_available_modulations;
v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42;
v8_answer_parms.pcm_modem_availability = 0;
v8_answer_parms.pstn_access = 0;
v8_answer_parms.nsf = -1;
v8_answer_parms.t66 = -1;
v8_answerer = v8_init(NULL,
FALSE,
&v8_answer_parms,
handler,
(void *) "answerer");
logging = v8_get_logging_state(v8_answerer); logging = v8_get_logging_state(v8_answerer);
span_log_set_level(logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG); span_log_set_level(logging, SPAN_LOG_FLOW | SPAN_LOG_SHOW_TAG);
span_log_set_tag(logging, "decoder"); span_log_set_tag(logging, "answerer");
if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL) if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
{ {
fprintf(stderr, " Cannot open speech file '%s'\n", decode_test_file); fprintf(stderr, " Cannot open speech file '%s'\n", decode_test_file);
@ -463,10 +563,14 @@ int main(int argc, char *argv[])
while ((samples = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK))) while ((samples = sf_readf_short(inhandle, amp, SAMPLES_PER_CHUNK)))
{ {
remnant = v8_rx(v8_caller, amp, samples);
remnant = v8_rx(v8_answerer, amp, samples); remnant = v8_rx(v8_answerer, amp, samples);
remnant = v8_tx(v8_caller, amp, samples);
remnant = v8_tx(v8_answerer, amp, samples);
} }
/*endwhile*/ /*endwhile*/
v8_free(v8_caller);
v8_free(v8_answerer); v8_free(v8_answerer);
if (sf_close(inhandle) != 0) if (sf_close(inhandle) != 0)
{ {