Various small cleanups in spandsp
This commit is contained in:
parent
88ce7dae1c
commit
44252a5d69
|
@ -202,6 +202,18 @@ AC_CHECK_HEADERS([stdlib.h])
|
|||
AC_CHECK_HEADERS([string.h])
|
||||
AC_CHECK_HEADERS([strings.h])
|
||||
AC_CHECK_HEADERS([malloc.h])
|
||||
AC_CHECK_HEADERS([math.h], [INSERT_MATH_HEADER="#include <math.h>"])
|
||||
AC_CHECK_HEADERS([float.h])
|
||||
AC_CHECK_HEADERS([fcntl.h])
|
||||
AC_CHECK_HEADERS([sys/time.h])
|
||||
AC_CHECK_HEADERS([sys/select.h])
|
||||
AC_CHECK_HEADERS([sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([sys/fcntl.h])
|
||||
AC_CHECK_HEADERS([sndfile.h])
|
||||
AC_CHECK_HEADERS([fenv.h])
|
||||
AC_CHECK_HEADERS([fftw3.h], , [AC_CHECK_HEADERS([fftw.h])])
|
||||
AC_CHECK_HEADERS([pcap.h])
|
||||
AC_CHECK_HEADERS([pthread.h])
|
||||
|
||||
case "$host" in
|
||||
*dragonfly*)
|
||||
|
@ -215,18 +227,6 @@ case "$host" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_CHECK_HEADERS([math.h], [INSERT_MATH_HEADER="#include <math.h>"])
|
||||
AC_CHECK_HEADERS([float.h])
|
||||
AC_CHECK_HEADERS([fcntl.h])
|
||||
AC_CHECK_HEADERS([sys/time.h])
|
||||
AC_CHECK_HEADERS([sys/select.h])
|
||||
AC_CHECK_HEADERS([sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([sys/fcntl.h])
|
||||
AC_CHECK_HEADERS([sndfile.h])
|
||||
AC_CHECK_HEADERS([fenv.h])
|
||||
AC_CHECK_HEADERS([fftw3.h], , [AC_CHECK_HEADERS([fftw.h])])
|
||||
AC_CHECK_HEADERS([pcap.h])
|
||||
AC_CHECK_HEADERS([pthread.h])
|
||||
if test "${build}" == "${host}"
|
||||
then
|
||||
AC_CHECK_HEADERS([X11/X.h])
|
||||
|
|
|
@ -110,6 +110,7 @@ libspandsp_la_SOURCES = ademco_contactid.c \
|
|||
complex_vector_float.c \
|
||||
complex_vector_int.c \
|
||||
crc.c \
|
||||
data_modems.c \
|
||||
dds_float.c \
|
||||
dds_int.c \
|
||||
dtmf.c \
|
||||
|
@ -210,6 +211,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
|
|||
spandsp/complex_filters.h \
|
||||
spandsp/complex_vector_float.h \
|
||||
spandsp/complex_vector_int.h \
|
||||
spandsp/data_modems.h \
|
||||
spandsp/dc_restore.h \
|
||||
spandsp/dds.h \
|
||||
spandsp/dtmf.h \
|
||||
|
@ -292,6 +294,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
|
|||
spandsp/private/bell_r2_mf.h \
|
||||
spandsp/private/bert.h \
|
||||
spandsp/private/bitstream.h \
|
||||
spandsp/private/data_modems.h \
|
||||
spandsp/private/dtmf.h \
|
||||
spandsp/private/echo.h \
|
||||
spandsp/private/fax.h \
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
#include <spandsp/t30_logging.h>
|
||||
#include <spandsp/t35.h>
|
||||
#include <spandsp/at_interpreter.h>
|
||||
#include <spandsp/data_modems.h>
|
||||
#include <spandsp/fax_modems.h>
|
||||
#include <spandsp/fax.h>
|
||||
#include <spandsp/t38_core.h>
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
#include <spandsp/private/v42.h>
|
||||
#include <spandsp/private/v42bis.h>
|
||||
#include <spandsp/private/at_interpreter.h>
|
||||
//#include <spandsp/private/data_modems.h>
|
||||
#include <spandsp/private/data_modems.h>
|
||||
#include <spandsp/private/fax_modems.h>
|
||||
#include <spandsp/private/timezone.h>
|
||||
#include <spandsp/private/image_translate.h>
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
#include "spandsp/private/v27ter_tx.h"
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define FP_SCALE FP_Q6_10
|
||||
#define FP_SCALE(x) FP_Q6_10(x)
|
||||
#else
|
||||
#define FP_SCALE(x) (x)
|
||||
#endif
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
enum
|
||||
{
|
||||
V8_WAIT_1S, /* Start point when sending CI */
|
||||
V8_WAIT_1S = 0, /* Start point when sending CI */
|
||||
V8_AWAIT_ANSAM, /* Start point when sending initial silence */
|
||||
V8_CI_ON,
|
||||
V8_CI_OFF,
|
||||
|
@ -539,16 +539,16 @@ static void put_bit(void *user_data, int bit)
|
|||
switch (s->preamble_type)
|
||||
{
|
||||
case V8_SYNC_CI:
|
||||
tag = "CI: ";
|
||||
tag = ">CI: ";
|
||||
break;
|
||||
case V8_SYNC_CM_JM:
|
||||
tag = (s->calling_party) ? "JM: " : "CM: ";
|
||||
tag = (s->calling_party) ? ">JM: " : ">CM: ";
|
||||
break;
|
||||
case V8_SYNC_V92:
|
||||
tag = "V92: ";
|
||||
tag = ">V.92: ";
|
||||
break;
|
||||
default:
|
||||
tag = "??: ";
|
||||
tag = ">??: ";
|
||||
break;
|
||||
}
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, tag, s->rx_data, s->rx_data_ptr);
|
||||
|
@ -639,20 +639,26 @@ static void v8_put_preamble(v8_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void v8_put_byte(v8_state_t *s, int data)
|
||||
static void v8_put_bytes(v8_state_t *s, uint8_t buf[], int len)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
uint8_t byte;
|
||||
uint8_t bits[10];
|
||||
|
||||
/* Insert start & stop bits */
|
||||
bits[0] = 0;
|
||||
for (i = 1; i < 9; i++)
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
bits[i] = (uint8_t) (data & 1);
|
||||
data >>= 1;
|
||||
bits[0] = 0;
|
||||
byte = buf[i];
|
||||
for (j = 1; j < 9; j++)
|
||||
{
|
||||
bits[j] = byte & 1;
|
||||
byte >>= 1;
|
||||
}
|
||||
bits[9] = 1;
|
||||
queue_write(s->tx_queue, bits, 10);
|
||||
}
|
||||
bits[9] = 1;
|
||||
queue_write(s->tx_queue, bits, 10);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -661,12 +667,15 @@ static void send_cm_jm(v8_state_t *s)
|
|||
int val;
|
||||
unsigned int offered_modulations;
|
||||
int bytes;
|
||||
uint8_t buf[10];
|
||||
int ptr;
|
||||
|
||||
/* Send a CM, or a JM as appropriate */
|
||||
v8_put_preamble(s);
|
||||
v8_put_byte(s, V8_CM_JM_SYNC_OCTET);
|
||||
ptr = 0;
|
||||
buf[ptr++] = V8_CM_JM_SYNC_OCTET;
|
||||
/* Data call */
|
||||
v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG);
|
||||
buf[ptr++] = (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG;
|
||||
|
||||
/* Supported modulations */
|
||||
offered_modulations = s->result.modulations;
|
||||
|
@ -676,7 +685,9 @@ static void send_cm_jm(v8_state_t *s)
|
|||
val |= 0x20;
|
||||
if (offered_modulations & V8_MOD_V34)
|
||||
val |= 0x40;
|
||||
v8_put_byte(s, val);
|
||||
if (offered_modulations & V8_MOD_V34HDX)
|
||||
val |= 0x80;
|
||||
buf[ptr++] = val;
|
||||
if (++bytes < s->modulation_bytes)
|
||||
{
|
||||
val = 0x10;
|
||||
|
@ -690,7 +701,7 @@ static void send_cm_jm(v8_state_t *s)
|
|||
val |= 0x40;
|
||||
if (offered_modulations & V8_MOD_V27TER)
|
||||
val |= 0x80;
|
||||
v8_put_byte(s, val);
|
||||
buf[ptr++] = val;
|
||||
}
|
||||
if (++bytes < s->modulation_bytes)
|
||||
{
|
||||
|
@ -705,19 +716,21 @@ static void send_cm_jm(v8_state_t *s)
|
|||
val |= 0x40;
|
||||
if (offered_modulations & V8_MOD_V21)
|
||||
val |= 0x80;
|
||||
v8_put_byte(s, val);
|
||||
buf[ptr++] = val;
|
||||
}
|
||||
|
||||
if (s->parms.protocol)
|
||||
v8_put_byte(s, (s->parms.protocol << 5) | V8_PROTOCOLS_TAG);
|
||||
buf[ptr++] = (s->parms.protocol << 5) | V8_PROTOCOLS_TAG;
|
||||
if (s->parms.pstn_access)
|
||||
v8_put_byte(s, (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG);
|
||||
buf[ptr++] = (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG;
|
||||
if (s->parms.pcm_modem_availability)
|
||||
v8_put_byte(s, (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG);
|
||||
buf[ptr++] = (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG;
|
||||
if (s->parms.t66 >= 0)
|
||||
v8_put_byte(s, (s->parms.t66 << 5) | V8_T66_TAG);
|
||||
buf[ptr++] = (s->parms.t66 << 5) | V8_T66_TAG;
|
||||
/* No NSF */
|
||||
//v8_put_byte(s, (0 << 5) | V8_NSF_TAG);
|
||||
//buf[ptr++] = (0 << 5) | V8_NSF_TAG;
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, (s->calling_party) ? "<CM: " : "<JM: ", &buf[1], ptr - 1);
|
||||
v8_put_bytes(s, buf, ptr);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -729,7 +742,15 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
|
|||
len = 0;
|
||||
if (s->modem_connect_tone_tx_on)
|
||||
{
|
||||
if (s->modem_connect_tone_tx_on > ms_to_samples(75))
|
||||
if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 2))
|
||||
{
|
||||
if (s->fsk_tx_on)
|
||||
{
|
||||
/* The initial silence is over */
|
||||
s->modem_connect_tone_tx_on = 0;
|
||||
}
|
||||
}
|
||||
else if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 1))
|
||||
{
|
||||
/* Send the ANSam tone */
|
||||
len = modem_connect_tones_tx(&s->ansam_tx, amp, max_len);
|
||||
|
@ -752,14 +773,19 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
|
|||
}
|
||||
if (s->fsk_tx_on && len < max_len)
|
||||
{
|
||||
max_len -= len;
|
||||
len = fsk_tx(&s->v21tx, amp + len, max_len);
|
||||
len += fsk_tx(&s->v21tx, &[len], max_len - len);
|
||||
if (len < max_len)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "FSK ends\n");
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "FSK ends (%d/%d) %d %d\n", len, max_len, s->fsk_tx_on, s->state);
|
||||
s->fsk_tx_on = false;
|
||||
//s->state = V8_PARKED;
|
||||
}
|
||||
}
|
||||
if (s->state != V8_PARKED && len < max_len)
|
||||
{
|
||||
vec_zeroi16(&[len], max_len - len);
|
||||
len = max_len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -767,6 +793,7 @@ SPAN_DECLARE_NONSTD(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
|
|||
static void send_v92(v8_state_t *s)
|
||||
{
|
||||
int i;
|
||||
uint8_t buf[2];
|
||||
|
||||
if (s->result.v92 >= 0)
|
||||
{
|
||||
|
@ -774,8 +801,10 @@ static void send_v92(v8_state_t *s)
|
|||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
v8_put_preamble(s);
|
||||
v8_put_byte(s, V8_V92_SYNC_OCTET);
|
||||
v8_put_byte(s, s->result.v92);
|
||||
buf[0] = V8_V92_SYNC_OCTET;
|
||||
buf[1] = s->result.v92;
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, "<V.92: ", &buf[1], 1);
|
||||
v8_put_bytes(s, buf, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -784,13 +813,16 @@ static void send_v92(v8_state_t *s)
|
|||
static void send_ci(v8_state_t *s)
|
||||
{
|
||||
int i;
|
||||
uint8_t buf[2];
|
||||
|
||||
/* Send 4 CI packets in a burst (the spec says at least 3) */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
v8_put_preamble(s);
|
||||
v8_put_byte(s, V8_CI_SYNC_OCTET);
|
||||
v8_put_byte(s, (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG);
|
||||
buf[0] = V8_CI_SYNC_OCTET;
|
||||
buf[1] = (s->result.call_function << 5) | V8_CALL_FUNCTION_TAG;
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, "<CI: ", &buf[1], 1);
|
||||
v8_put_bytes(s, buf, 2);
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -822,9 +854,9 @@ static void handle_modem_connect_tone(v8_state_t *s, int tone)
|
|||
|
||||
SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
||||
{
|
||||
int i;
|
||||
int residual_samples;
|
||||
int tone;
|
||||
uint8_t buf[3];
|
||||
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "v8_rx state %d\n", s->state);
|
||||
residual_samples = 0;
|
||||
|
@ -911,8 +943,9 @@ SPAN_DECLARE_NONSTD(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
/* Now JM has been detected, we send CJ and wait for 75 ms
|
||||
before finishing the V.8 analysis. */
|
||||
fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
|
||||
for (i = 0; i < 3; i++)
|
||||
v8_put_byte(s, 0);
|
||||
memset(buf, 0, 3);
|
||||
v8_put_bytes(s, buf, 3);
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, "<CJ: ", &buf[1], 2);
|
||||
s->state = V8_CJ_ON;
|
||||
s->fsk_tx_on = true;
|
||||
break;
|
||||
|
@ -1060,6 +1093,7 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, bool calling_party, v8_parms_t *parm
|
|||
}
|
||||
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);
|
||||
s->modem_connect_tone_tx_on = ms_to_samples(75) + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -73,10 +73,12 @@ noinst_PROGRAMS = ademco_contactid_tests \
|
|||
complex_vector_float_tests \
|
||||
complex_vector_int_tests \
|
||||
crc_tests \
|
||||
data_modems_tests \
|
||||
dc_restore_tests \
|
||||
dds_tests \
|
||||
dtmf_rx_tests \
|
||||
dtmf_tx_tests \
|
||||
dummy_modems_tests \
|
||||
echo_tests \
|
||||
fax_decode \
|
||||
fax_tests \
|
||||
|
@ -151,6 +153,7 @@ noinst_HEADERS = echo_monitor.h \
|
|||
modem_monitor.h \
|
||||
pcap_parse.h \
|
||||
pseudo_terminals.h \
|
||||
socket_harness.h \
|
||||
udptl.h
|
||||
|
||||
ademco_contactid_tests_SOURCES = ademco_contactid_tests.c
|
||||
|
@ -198,6 +201,9 @@ complex_vector_int_tests_LDADD = $(LIBDIR) -lspandsp
|
|||
crc_tests_SOURCES = crc_tests.c
|
||||
crc_tests_LDADD = $(LIBDIR) -lspandsp
|
||||
|
||||
data_modems_tests_SOURCES = data_modems_tests.c media_monitor.cpp
|
||||
data_modems_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
dc_restore_tests_SOURCES = dc_restore_tests.c
|
||||
dc_restore_tests_LDADD = $(LIBDIR) -lspandsp
|
||||
|
||||
|
@ -210,6 +216,9 @@ dtmf_rx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lsp
|
|||
dtmf_tx_tests_SOURCES = dtmf_tx_tests.c
|
||||
dtmf_tx_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
dummy_modems_tests_SOURCES = dummy_modems_tests.c media_monitor.cpp socket_harness.c pseudo_terminals.c
|
||||
dummy_modems_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp -lutil
|
||||
|
||||
echo_tests_SOURCES = echo_tests.c echo_monitor.cpp
|
||||
echo_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* data_modems_tests.c - Tests for data_modems.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
/*! \page data_modems_tests_page Data modems tests
|
||||
\section data_modems_tests_page_sec_1 What does it do?
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
|
||||
#define ENABLE_GUI
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "spandsp.h"
|
||||
#include "spandsp-sim.h"
|
||||
|
||||
#if defined(ENABLE_GUI)
|
||||
#include "media_monitor.h"
|
||||
#endif
|
||||
|
||||
#define INPUT_FILE_NAME "../test-data/itu/fax/itu1.tif"
|
||||
#define OUTPUT_FILE_NAME "t31.tif"
|
||||
#define OUTPUT_WAVE_FILE_NAME "data_modems.wav"
|
||||
|
||||
#define SAMPLES_PER_CHUNK 160
|
||||
|
||||
struct command_response_s
|
||||
{
|
||||
const char *command;
|
||||
int len_command;
|
||||
const char *response;
|
||||
int len_response;
|
||||
};
|
||||
|
||||
char *decode_test_file = NULL;
|
||||
int countdown = 0;
|
||||
int command_response_test_step = -1;
|
||||
char response_buf[1000];
|
||||
int response_buf_ptr = 0;
|
||||
bool answered = false;
|
||||
bool done = false;
|
||||
bool sequence_terminated = false;
|
||||
|
||||
data_modems_state_t *data_modems_state[2];
|
||||
|
||||
static void reporter(void *user_data, int reason, bert_results_t *results)
|
||||
{
|
||||
int channel;
|
||||
|
||||
channel = (int) (intptr_t) user_data;
|
||||
switch (reason)
|
||||
{
|
||||
case BERT_REPORT_SYNCED:
|
||||
fprintf(stderr, "%d: BERT report synced\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_UNSYNCED:
|
||||
fprintf(stderr, "%d: BERT report unsync'ed\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_REGULAR:
|
||||
fprintf(stderr, "%d: BERT report regular - %d bits, %d bad bits, %d resyncs\n", channel, results->total_bits, results->bad_bits, results->resyncs);
|
||||
break;
|
||||
case BERT_REPORT_GT_10_2:
|
||||
fprintf(stderr, "%d: BERT report > 1 in 10^2\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_LT_10_2:
|
||||
fprintf(stderr, "%d: BERT report < 1 in 10^2\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_LT_10_3:
|
||||
fprintf(stderr, "%d: BERT report < 1 in 10^3\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_LT_10_4:
|
||||
fprintf(stderr, "%d: BERT report < 1 in 10^4\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_LT_10_5:
|
||||
fprintf(stderr, "%d: BERT report < 1 in 10^5\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_LT_10_6:
|
||||
fprintf(stderr, "%d: BERT report < 1 in 10^6\n", channel);
|
||||
break;
|
||||
case BERT_REPORT_LT_10_7:
|
||||
fprintf(stderr, "%d: BERT report < 1 in 10^7\n", channel);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%d: BERT report reason %d\n", channel, reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int get_msg(void *user_data, uint8_t msg[], int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void put_msg(void *user_data, const uint8_t msg[], int len)
|
||||
{
|
||||
if (len < 0)
|
||||
printf("Status %s\n", signal_status_to_str(len));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int modem_tests(int use_gui, int log_audio, int test_sending)
|
||||
{
|
||||
int mdm_len;
|
||||
int16_t mdm_amp[SAMPLES_PER_CHUNK];
|
||||
//int use_tep;
|
||||
//logging_state_t *logging;
|
||||
int outframes;
|
||||
int16_t silence[SAMPLES_PER_CHUNK];
|
||||
int16_t out_amp[2*SAMPLES_PER_CHUNK];
|
||||
SNDFILE *wave_handle;
|
||||
SNDFILE *in_handle;
|
||||
int i;
|
||||
int k;
|
||||
int calling_party;
|
||||
logging_state_t *logging;
|
||||
bert_state_t *bert[2];
|
||||
|
||||
/* Test a pair of modems against each other */
|
||||
|
||||
/* Set up the test environment */
|
||||
//use_tep = false;
|
||||
|
||||
wave_handle = NULL;
|
||||
if (log_audio)
|
||||
{
|
||||
if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
in_handle = NULL;
|
||||
if (decode_test_file)
|
||||
{
|
||||
if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create audio file '%s'\n", decode_test_file);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
memset(silence, 0, sizeof(silence));
|
||||
memset(mdm_amp, 0, sizeof(mdm_amp));
|
||||
mdm_len = 0;
|
||||
|
||||
/* Now set up and run the modems */
|
||||
calling_party = true;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
bert[i] = bert_init(NULL, 1000000, BERT_PATTERN_ITU_O152_11, 2400, 20);
|
||||
bert_set_report(bert[i], 100000, reporter, (void *) (intptr_t) i);
|
||||
if ((data_modems_state[i] = data_modems_init(NULL,
|
||||
calling_party,
|
||||
put_msg,
|
||||
get_msg,
|
||||
NULL)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot start the data modem\n");
|
||||
exit(2);
|
||||
}
|
||||
logging = data_modems_get_logging_state(data_modems_state[i]);
|
||||
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
|
||||
span_log_set_tag(logging, "Modem");
|
||||
calling_party = false;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_GUI)
|
||||
if (use_gui)
|
||||
start_media_monitor();
|
||||
#endif
|
||||
while (!done)
|
||||
{
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
/* The receive side always expects a full block of samples, but the
|
||||
transmit side may not be sending any when it doesn't need to. We
|
||||
may need to pad with some silence. */
|
||||
mdm_len = data_modems_tx(data_modems_state[i], mdm_amp, SAMPLES_PER_CHUNK);
|
||||
if (mdm_len < SAMPLES_PER_CHUNK)
|
||||
{
|
||||
vec_zeroi16(mdm_amp + mdm_len, SAMPLES_PER_CHUNK - mdm_len);
|
||||
mdm_len = SAMPLES_PER_CHUNK;
|
||||
}
|
||||
if (log_audio)
|
||||
{
|
||||
for (k = 0; k < mdm_len; k++)
|
||||
out_amp[2*k + i] = mdm_amp[k];
|
||||
}
|
||||
if (data_modems_rx(data_modems_state[i ^ 1], mdm_amp, mdm_len))
|
||||
break;
|
||||
}
|
||||
|
||||
if (log_audio)
|
||||
{
|
||||
outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
|
||||
if (outframes != SAMPLES_PER_CHUNK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (decode_test_file)
|
||||
{
|
||||
if (sf_close_telephony(in_handle))
|
||||
{
|
||||
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
if (log_audio)
|
||||
{
|
||||
if (sf_close_telephony(wave_handle))
|
||||
{
|
||||
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!done || !sequence_terminated)
|
||||
{
|
||||
printf("Tests failed\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int log_audio;
|
||||
int test_sending;
|
||||
int use_gui;
|
||||
int opt;
|
||||
|
||||
decode_test_file = NULL;
|
||||
log_audio = false;
|
||||
test_sending = false;
|
||||
use_gui = false;
|
||||
while ((opt = getopt(argc, argv, "d:glrs")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'd':
|
||||
decode_test_file = optarg;
|
||||
break;
|
||||
case 'g':
|
||||
#if defined(ENABLE_GUI)
|
||||
use_gui = true;
|
||||
#else
|
||||
fprintf(stderr, "Graphical monitoring not available\n");
|
||||
exit(2);
|
||||
#endif
|
||||
break;
|
||||
case 'l':
|
||||
log_audio = true;
|
||||
break;
|
||||
case 'r':
|
||||
test_sending = false;
|
||||
break;
|
||||
case 's':
|
||||
test_sending = true;
|
||||
break;
|
||||
default:
|
||||
//usage();
|
||||
exit(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
modem_tests(use_gui, log_audio, test_sending);
|
||||
printf("Tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* dummy_modems_tests.c - Tests for data_modems connected together by sockets.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
/*! \page dummy_modems_tests_page Dummy data modems tests
|
||||
\section dummy_modems_tests_page_sec_1 What does it do?
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
|
||||
#define ENABLE_GUI
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <termios.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
//#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
|
||||
|
||||
#include "spandsp.h"
|
||||
#include "spandsp-sim.h"
|
||||
|
||||
#include "pseudo_terminals.h"
|
||||
#include "socket_harness.h"
|
||||
|
||||
#if defined(ENABLE_GUI)
|
||||
#include "media_monitor.h"
|
||||
#endif
|
||||
|
||||
#define OUTPUT_WAVE_FILE_NAME "dummy_modems.wav"
|
||||
|
||||
#define SAMPLES_PER_CHUNK 160
|
||||
|
||||
SNDFILE *wave_handle = NULL;
|
||||
int16_t wave_buffer[4096];
|
||||
|
||||
data_modems_state_t *data_modem_state;
|
||||
|
||||
static int get_msg(void *user_data, uint8_t msg[], int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void put_msg(void *user_data, const uint8_t msg[], int len)
|
||||
{
|
||||
if (len < 0)
|
||||
printf("Status %s\n", signal_status_to_str(len));
|
||||
else
|
||||
printf("Put %d '%s'\n", len, msg);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void terminal_callback(void *user_data, const uint8_t msg[], int len)
|
||||
{
|
||||
printf("terminal callback %d\n", len);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int termios_callback(void *user_data, struct termios *termios)
|
||||
{
|
||||
printf("termios callback\n");
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void hangup_callback(void *user_data, int status)
|
||||
{
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int terminal_free_space_callback(void *user_data)
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int rx_callback(void *user_data, const int16_t amp[], int samples)
|
||||
{
|
||||
int i;
|
||||
int out_samples;
|
||||
|
||||
out_samples = data_modems_rx((data_modems_state_t *) user_data, amp, samples);
|
||||
if (wave_handle)
|
||||
{
|
||||
for (i = 0; i < samples; i++)
|
||||
wave_buffer[2*i] = amp[i];
|
||||
}
|
||||
return out_samples;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int rx_fillin_callback(void *user_data, int samples)
|
||||
{
|
||||
return data_modems_rx_fillin((data_modems_state_t *) user_data, samples);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int tx_callback(void *user_data, int16_t amp[], int samples)
|
||||
{
|
||||
int i;
|
||||
int out_samples;
|
||||
|
||||
out_samples = data_modems_tx((data_modems_state_t *) user_data, amp, samples);
|
||||
if (wave_handle)
|
||||
{
|
||||
if (out_samples < samples)
|
||||
memset(&[out_samples], 0, (samples - out_samples)*2);
|
||||
for (i = 0; i < samples; i++)
|
||||
wave_buffer[2*i + 1] = amp[i];
|
||||
sf_writef_short(wave_handle, wave_buffer, samples);
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int modem_tests(int use_gui, int log_audio, bool calling_party)
|
||||
{
|
||||
logging_state_t *logging;
|
||||
socket_harness_state_t *s;
|
||||
|
||||
/* Now set up and run the modems */
|
||||
if ((data_modem_state = data_modems_init(NULL,
|
||||
calling_party,
|
||||
put_msg,
|
||||
get_msg,
|
||||
NULL)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot start the data modem\n");
|
||||
exit(2);
|
||||
}
|
||||
logging = data_modems_get_logging_state(data_modem_state);
|
||||
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_DATE);
|
||||
span_log_set_tag(logging, "Modem");
|
||||
|
||||
if ((s = socket_harness_init(NULL,
|
||||
"/tmp/modemsocket",
|
||||
"modemA",
|
||||
calling_party,
|
||||
terminal_callback,
|
||||
termios_callback,
|
||||
hangup_callback,
|
||||
terminal_free_space_callback,
|
||||
rx_callback,
|
||||
rx_fillin_callback,
|
||||
tx_callback,
|
||||
data_modem_state)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot start the socket harness\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
wave_handle = NULL;
|
||||
if (log_audio)
|
||||
{
|
||||
if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
socket_harness_run(s);
|
||||
|
||||
if (log_audio)
|
||||
{
|
||||
if (sf_close_telephony(wave_handle))
|
||||
{
|
||||
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int log_audio;
|
||||
int use_gui;
|
||||
int opt;
|
||||
bool calling_party;
|
||||
|
||||
log_audio = false;
|
||||
calling_party = false;
|
||||
use_gui = false;
|
||||
while ((opt = getopt(argc, argv, "acgl")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
calling_party = false;
|
||||
break;
|
||||
case 'c':
|
||||
calling_party = true;
|
||||
break;
|
||||
case 'g':
|
||||
#if defined(ENABLE_GUI)
|
||||
use_gui = true;
|
||||
#else
|
||||
fprintf(stderr, "Graphical monitoring not available\n");
|
||||
exit(2);
|
||||
#endif
|
||||
break;
|
||||
case 'l':
|
||||
log_audio = true;
|
||||
break;
|
||||
default:
|
||||
//usage();
|
||||
exit(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (modem_tests(use_gui, log_audio, calling_party))
|
||||
exit(2);
|
||||
printf("Tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -29,15 +29,21 @@
|
|||
\section fax_tests_page_sec_1 What does it do?
|
||||
These tests exercise the following FAX to FAX paths:
|
||||
|
||||
+--Modems-+-----------TDM/RTP-----------+-Modems--+
|
||||
| \ / |
|
||||
| \ / |
|
||||
T.30 <---+ T.38 gateway T.38 gateway +--->T.30
|
||||
| \ / |
|
||||
| \ / |
|
||||
+---T.38---+----+----UDPTL/RTP----+----+---T.38---+
|
||||
\ /
|
||||
+----------TCP----------+
|
||||
TSB85 <-----------+ +-----------> TSB85
|
||||
\ /
|
||||
T.31 <-----------+ \ / +-----------> T.31
|
||||
\ \ / /
|
||||
+--Modems-+-+-----------TDM/RTP-----------+-+-Modems--+
|
||||
| \ / |
|
||||
| \ / |
|
||||
T.30 <---+ T.38 gateway T.38 gateway +---> T.30
|
||||
| \ / |
|
||||
| \ / |
|
||||
+---T.38---+-+----+----UDPTL/RTP----+----+ +---T.38---+
|
||||
/ / \ / \ \
|
||||
T.31 <------------/ / +----------TCP----------+ \ +------------> T.31
|
||||
/ \
|
||||
TSB85 <------------+ +------------> TSB85
|
||||
|
||||
T.30<->Modems<-------------------------TDM/RTP------------------------->Modems<->T.30
|
||||
T.30<->Modems<-TDM/RTP->T.38 gateway<-UDPTL/RTP->T.38 gateway<-TDM/RTP->Modems<->T.30
|
||||
|
@ -45,6 +51,7 @@ T.30<->Modems<-TDM/RTP->T.38 gateway<-UDPTL/RTP-------------------------->T.38<-
|
|||
T.30<->T.38<--------------------------UDPTL/RTP->T.38 gateway<-TDM/RTP->Modems<->T.30
|
||||
T.30<->T.38<--------------------------UDPTL/RTP-------------------------->T.38<->T.30
|
||||
|
||||
The T.31 and TSB85 parts are incomplete right now.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
|
@ -520,6 +527,7 @@ int main(int argc, char *argv[])
|
|||
char *page_header_info;
|
||||
char *page_header_tz;
|
||||
const char *tag;
|
||||
const char *xml_file_name;
|
||||
char buf[132 + 1];
|
||||
#if defined(ENABLE_GUI)
|
||||
int use_gui;
|
||||
|
@ -557,7 +565,8 @@ int main(int argc, char *argv[])
|
|||
colour_enabled = false;
|
||||
t37_like_output = false;
|
||||
t38_transport = T38_TRANSPORT_UDPTL;
|
||||
while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:z:")) != -1)
|
||||
xml_file_name = "../spandsp/tsb85.xml";
|
||||
while ((opt = getopt(argc, argv, "7b:c:Cd:D:efFgH:i:Ilm:M:n:p:s:S:tT:u:v:x:z:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
@ -682,6 +691,9 @@ int main(int argc, char *argv[])
|
|||
case 'v':
|
||||
t38_version = atoi(optarg);
|
||||
break;
|
||||
case 'x':
|
||||
xml_file_name = optarg;
|
||||
break;
|
||||
case 'z':
|
||||
page_header_tz = optarg;
|
||||
break;
|
||||
|
@ -736,8 +748,9 @@ int main(int argc, char *argv[])
|
|||
tag = (i == 0) ? "A" : "B";
|
||||
|
||||
memset(&expected_rx_info[i], 0, sizeof(expected_rx_info[i]));
|
||||
if (mode[i] == T38_TERMINAL_FAX)
|
||||
switch (mode[i])
|
||||
{
|
||||
case T38_TERMINAL_FAX:
|
||||
if ((t38_state[i] = t38_terminal_init(NULL, (i == 0), tx_packet_handler, (void *) (intptr_t) i)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot start the T.38 terminal instance\n");
|
||||
|
@ -757,9 +770,9 @@ int main(int argc, char *argv[])
|
|||
logging = t30_get_logging_state(t30_state[i]);
|
||||
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
|
||||
span_log_set_tag(logging, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case AUDIO_FAX:
|
||||
case T38_GATEWAY_FAX:
|
||||
if ((fax_state[i] = fax_init(NULL, (i == 0))) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot start FAX instance\n");
|
||||
|
@ -783,7 +796,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
if ((t38_gateway_state[i] = t38_gateway_init(NULL, tx_packet_handler, (void *) (intptr_t) i)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot start the T.38 gateway instancel\n");
|
||||
fprintf(stderr, "Cannot start the T.38 gateway instance\n");
|
||||
exit(2);
|
||||
}
|
||||
t38_core_state[i] = t38_gateway_get_t38_core_state(t38_gateway_state[i]);
|
||||
|
@ -820,6 +833,17 @@ int main(int argc, char *argv[])
|
|||
signal_scaling = powf(10.0f, signal_level/20.0f);
|
||||
printf("Signal scaling %f\n", signal_scaling);
|
||||
}
|
||||
break;
|
||||
case T31_AUDIO_FAX:
|
||||
break;
|
||||
case T31_T38_TERMINAL_FAX:
|
||||
case T31_T38_GATEWAY_FAX:
|
||||
break;
|
||||
case TSB85_AUDIO_FAX:
|
||||
break;
|
||||
case TSB85_T38_TERMINAL_FAX:
|
||||
case TSB85_T38_GATEWAY_FAX:
|
||||
break;
|
||||
}
|
||||
set_t30_callbacks(t30_state[i], i);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* socket_harness.c
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*/
|
||||
|
||||
|
||||
/*! \page bitstream_tests_page Bitstream tests
|
||||
\section bitstream_tests_page_sec_1 What does it do?
|
||||
|
||||
\section bitstream_tests_page_sec_2 How is it used?
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
|
||||
|
||||
#include "spandsp.h"
|
||||
|
||||
#include "pseudo_terminals.h"
|
||||
#include "socket_harness.h"
|
||||
|
||||
//#define SIMULATE_RING 1
|
||||
|
||||
#define CLOSE_COUNT_MAX 100
|
||||
|
||||
/* static data */
|
||||
static int16_t inbuf[4096];
|
||||
static int16_t outbuf[4096];
|
||||
|
||||
static volatile sig_atomic_t keep_running = true;
|
||||
|
||||
static void log_signal(int signum)
|
||||
{
|
||||
fprintf(stderr, "Signal %d: mark termination.\n", signum);
|
||||
keep_running = false;
|
||||
exit(2);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int socket_harness_run(socket_harness_state_t *s)
|
||||
{
|
||||
struct timeval tmo;
|
||||
fd_set rset;
|
||||
fd_set eset;
|
||||
struct termios termios;
|
||||
int max_fd;
|
||||
int count;
|
||||
int samples;
|
||||
int tx_samples;
|
||||
int ret;
|
||||
|
||||
while (keep_running)
|
||||
{
|
||||
//if (s->modem->event)
|
||||
// modem_event(s->modem);
|
||||
#ifdef SIMULATE_RING
|
||||
tmo.tv_sec = 0;
|
||||
tmo.tv_usec= 1000000/RING_HZ;
|
||||
#else
|
||||
tmo.tv_sec = 1;
|
||||
tmo.tv_usec= 0;
|
||||
#endif
|
||||
max_fd = 0;
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&eset);
|
||||
FD_SET(s->audio_fd, &rset);
|
||||
FD_SET(s->audio_fd, &eset);
|
||||
FD_SET(s->pty_fd, &rset);
|
||||
FD_SET(s->pty_fd, &eset);
|
||||
if (s->audio_fd > max_fd)
|
||||
max_fd = s->audio_fd;
|
||||
if (s->pty_fd > max_fd)
|
||||
max_fd = s->pty_fd;
|
||||
if (s->pty_closed && s->close_count)
|
||||
{
|
||||
if (!s->started || s->close_count++ > CLOSE_COUNT_MAX)
|
||||
s->close_count = 0;
|
||||
}
|
||||
else if (s->terminal_free_space_callback(s->user_data))
|
||||
{
|
||||
FD_SET(s->pty_fd, &rset);
|
||||
if (s->pty_fd > max_fd)
|
||||
max_fd = s->pty_fd;
|
||||
}
|
||||
if ((ret = select(max_fd + 1, &rset, NULL, &eset, &tmo)) < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
fprintf(stderr, "Error: select: %s\n", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
#ifdef SIMULATE_RING
|
||||
if (!modem->modem->started)
|
||||
{
|
||||
rcount++;
|
||||
if (rcount <= RING_ON)
|
||||
modem_ring(modem->modem);
|
||||
else if (rcount > RING_OFF)
|
||||
rcount = 0;
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(s->audio_fd, &rset))
|
||||
{
|
||||
if ((count = read(s->audio_fd, inbuf, sizeof(inbuf)/2)) < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
{
|
||||
fprintf(stderr, "Error: audio read: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
count = 0;
|
||||
}
|
||||
if (count == 0)
|
||||
{
|
||||
fprintf(stderr, "Audio socket closed\n");
|
||||
return 0;
|
||||
}
|
||||
samples = count/2;
|
||||
usleep(125*samples);
|
||||
|
||||
s->rx_callback(s->user_data, inbuf, samples);
|
||||
tx_samples = s->tx_callback(s->user_data, outbuf, samples);
|
||||
if (tx_samples < samples)
|
||||
memset(&outbuf[tx_samples], 0, (samples - tx_samples)*2);
|
||||
|
||||
if ((count = write(s->audio_fd, outbuf, samples*2)) < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
{
|
||||
fprintf(stderr, "Error: audio write: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* TODO: */
|
||||
}
|
||||
if (count != samples*2)
|
||||
fprintf(stderr, "audio write = %d\n", count);
|
||||
}
|
||||
|
||||
if (FD_ISSET(s->pty_fd, &rset))
|
||||
{
|
||||
/* Check termios */
|
||||
tcgetattr(s->pty_fd, &termios);
|
||||
if (memcmp(&termios, &s->termios, sizeof(termios)))
|
||||
s->termios_callback(s->user_data, &termios);
|
||||
/* Read data */
|
||||
if ((count = s->terminal_free_space_callback(s->user_data)))
|
||||
{
|
||||
if (count > sizeof(inbuf))
|
||||
count = sizeof(inbuf);
|
||||
if ((count = read(s->pty_fd, inbuf, count)) < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
fprintf(stderr, "pty read, errno = EAGAIN\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (errno == EIO)
|
||||
{
|
||||
if (!s->pty_closed)
|
||||
{
|
||||
fprintf(stderr, "pty closed.\n");
|
||||
s->pty_closed = 1;
|
||||
if ((termios.c_cflag & HUPCL))
|
||||
s->hangup_callback(s->user_data, 0);
|
||||
}
|
||||
s->close_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: pty read: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count == 0)
|
||||
fprintf(stderr, "pty read = 0\n");
|
||||
s->pty_closed = false;
|
||||
s->terminal_callback(s->user_data, (uint8_t *) inbuf, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
|
||||
const char *socket_name,
|
||||
const char *tag,
|
||||
int caller,
|
||||
put_msg_func_t terminal_callback,
|
||||
termio_update_func_t termios_callback,
|
||||
modem_status_func_t hangup_callback,
|
||||
put_msg_free_space_func_t terminal_free_space_callback,
|
||||
span_rx_handler_t rx_callback,
|
||||
span_rx_fillin_handler_t rx_fillin_callback,
|
||||
span_tx_handler_t tx_callback,
|
||||
void *user_data)
|
||||
{
|
||||
int sockfd;
|
||||
int listensockfd;
|
||||
struct sockaddr_un serv_addr;
|
||||
struct sockaddr_un cli_addr;
|
||||
socklen_t servlen;
|
||||
socklen_t clilen;
|
||||
|
||||
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Socket failed - errno = %d\n", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
if ((s = (socket_harness_state_t *) malloc(sizeof(*s))) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
signal(SIGINT, log_signal);
|
||||
signal(SIGTERM, log_signal);
|
||||
|
||||
s->terminal_callback = terminal_callback;
|
||||
s->termios_callback = termios_callback;
|
||||
s->hangup_callback = hangup_callback;
|
||||
s->terminal_free_space_callback = terminal_free_space_callback;
|
||||
|
||||
s->rx_callback = rx_callback;
|
||||
s->rx_fillin_callback = rx_fillin_callback;
|
||||
s->tx_callback = tx_callback;
|
||||
|
||||
s->user_data = user_data;
|
||||
|
||||
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sun_family = AF_UNIX;
|
||||
/* This is a generic Unix domain socket. */
|
||||
strcpy(serv_addr.sun_path, socket_name);
|
||||
printf("Creating socket '%s'\n", serv_addr.sun_path);
|
||||
servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family) + 1;
|
||||
if (caller)
|
||||
{
|
||||
fprintf(stderr, "Connecting to '%s'\n", serv_addr.sun_path);
|
||||
if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
|
||||
{
|
||||
fprintf(stderr, "Connect failed - errno = %d\n", errno);
|
||||
exit(2);
|
||||
}
|
||||
fprintf(stderr, "Connected to '%s'\n", serv_addr.sun_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Listening to '%s'\n", serv_addr.sun_path);
|
||||
listensockfd = sockfd;
|
||||
/* The file may or may not exist. Just try to delete it anyway. */
|
||||
unlink(serv_addr.sun_path);
|
||||
if (bind(listensockfd, (struct sockaddr *) &serv_addr, servlen) < 0)
|
||||
{
|
||||
fprintf(stderr, "Bind failed - errno = %d\n", errno);
|
||||
exit(2);
|
||||
}
|
||||
listen(listensockfd, 5);
|
||||
clilen = sizeof(cli_addr);
|
||||
if ((sockfd = accept(listensockfd, (struct sockaddr *) &cli_addr, &clilen)) < 0)
|
||||
{
|
||||
fprintf(stderr, "Accept failed - errno = %d", errno);
|
||||
exit(2);
|
||||
}
|
||||
fprintf(stderr, "Accepted on '%s'\n", serv_addr.sun_path);
|
||||
}
|
||||
if (pseudo_terminal_create(&s->modem))
|
||||
{
|
||||
fprintf(stderr, "Failed to create pseudo TTY\n");
|
||||
exit(2);
|
||||
}
|
||||
s->audio_fd = sockfd;
|
||||
s->pty_fd = s->modem.master;
|
||||
return s;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int socket_harness_release(socket_harness_state_t *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int socket_harness_free(socket_harness_state_t *s)
|
||||
{
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* socket_harness.h
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*/
|
||||
|
||||
typedef int (*termio_update_func_t)(void *user_data, struct termios *termios);
|
||||
|
||||
typedef int (*put_msg_free_space_func_t)(void *user_data);
|
||||
|
||||
typedef struct socket_harness_state_s
|
||||
{
|
||||
void *user_data;
|
||||
|
||||
put_msg_func_t terminal_callback;
|
||||
termio_update_func_t termios_callback;
|
||||
modem_status_func_t hangup_callback;
|
||||
put_msg_free_space_func_t terminal_free_space_callback;
|
||||
|
||||
span_rx_handler_t rx_callback;
|
||||
span_rx_fillin_handler_t rx_fillin_callback;
|
||||
span_tx_handler_t tx_callback;
|
||||
|
||||
int audio_fd;
|
||||
int pty_fd;
|
||||
logging_state_t logging;
|
||||
struct termios termios;
|
||||
|
||||
unsigned int delay;
|
||||
unsigned int started;
|
||||
unsigned pty_closed;
|
||||
unsigned close_count;
|
||||
|
||||
modem_t modem;
|
||||
} socket_harness_state_t;
|
||||
|
||||
int socket_harness_run(socket_harness_state_t *s);
|
||||
|
||||
socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
|
||||
const char *socket_name,
|
||||
const char *tag,
|
||||
int caller,
|
||||
put_msg_func_t terminal_callback,
|
||||
termio_update_func_t termios_callback,
|
||||
modem_status_func_t hangup_callback,
|
||||
put_msg_free_space_func_t terminal_free_space_callback,
|
||||
span_rx_handler_t rx_callback,
|
||||
span_rx_fillin_handler_t rx_fillin_callback,
|
||||
span_tx_handler_t tx_callback,
|
||||
void *user_data);
|
||||
|
||||
int socket_harness_release(socket_harness_state_t *s);
|
||||
|
||||
int socket_harness_free(socket_harness_state_t *s);
|
|
@ -53,7 +53,7 @@ else
|
|||
cd gsm0610
|
||||
fi
|
||||
|
||||
if [ $1x = --no-exe-runx ]
|
||||
if [ $1x == --no-exe-runx ]
|
||||
then
|
||||
# Run the .exe files, which should be here
|
||||
./FR_A.EXE
|
||||
|
@ -77,7 +77,7 @@ rm -rf READ_FRA.TXT
|
|||
rm -rf ACTION
|
||||
rm -rf unpacked
|
||||
|
||||
if [ $1x = --no-exex ]
|
||||
if [ $1x == --no-exex ]
|
||||
then
|
||||
# We need to prepare the .exe files to be run separately
|
||||
rm -rf *.INP
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
:
|
||||
|
||||
#!/bin/sh
|
||||
#
|
||||
# Install the things which need adding to a fresh Fedora or Centos install to make it ready to build
|
||||
# spandsp and its test suite
|
||||
|
@ -19,7 +18,7 @@ yum install fftw-devel \
|
|||
sox \
|
||||
gcc-c++ \
|
||||
libtool \
|
||||
autconf \
|
||||
autoconf \
|
||||
automake \
|
||||
m4 \
|
||||
netpbm \
|
||||
|
|
Loading…
Reference in New Issue