SPAN_DECLARE(SNDFILE *) sf_open_telephony_write(const char *name, int channels);
+SPAN_DECLARE(int) sf_close_telephony(SNDFILE *handle);
+
#ifdef __cplusplus
}
#endif
static complex_t icircle[MAX_FFT_LEN/2];
static int icircle_init = FALSE;
+#define SF_MAX_HANDLE 32
+static int sf_close_at_exit_registered = FALSE;
+static SNDFILE *sf_close_at_exit_list[SF_MAX_HANDLE] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
SPAN_DECLARE(complexify_state_t *) complexify_init(void)
{
complexify_state_t *s;
}
/*- End of function --------------------------------------------------------*/
+static void sf_close_at_exit(void)
+{
+ int i;
+
+ for (i = 0; i < SF_MAX_HANDLE; i++)
+ {
+ if (sf_close_at_exit_list[i])
+ {
+ sf_close(sf_close_at_exit_list[i]);
+ sf_close_at_exit_list[i] = NULL;
+ }
+ }
+}
+/*- End of function --------------------------------------------------------*/
+
+static int sf_record_handle(SNDFILE *handle)
+{
+ int i;
+
+ for (i = 0; i < SF_MAX_HANDLE; i++)
+ {
+ if (sf_close_at_exit_list[i] == NULL)
+ break;
+ }
+ if (i >= SF_MAX_HANDLE)
+ return -1;
+ sf_close_at_exit_list[i] = handle;
+ if (!sf_close_at_exit_registered)
+ {
+ atexit(sf_close_at_exit);
+ sf_close_at_exit_registered = TRUE;
+ }
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
SPAN_DECLARE(SNDFILE *) sf_open_telephony_read(const char *name, int channels)
{
SNDFILE *handle;
printf(" Unexpected number of channels in audio file '%s'\n", name);
exit(2);
}
-
+ sf_record_handle(handle);
return handle;
}
/*- End of function --------------------------------------------------------*/
fprintf(stderr, " Cannot open audio file '%s' for writing\n", name);
exit(2);
}
-
+ sf_record_handle(handle);
return handle;
}
/*- End of function --------------------------------------------------------*/
+
+SPAN_DECLARE(int) sf_close_telephony(SNDFILE *handle)
+{
+ int res;
+ int i;
+
+ if ((res = sf_close(handle)) == 0)
+ {
+ for (i = 0; i < SF_MAX_HANDLE; i++)
+ {
+ if (sf_close_at_exit_list[i] == handle)
+ {
+ sf_close(sf_close_at_exit_list[i]);
+ sf_close_at_exit_list[i] = NULL;
+ break;
+ }
+ }
+ }
+ return res;
+}
+/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
#include "at_interpreter_dictionary.h"
-static int command_search(const char *u, int len, int *matched)
+static int command_search(const char *u, int *matched)
{
int i;
int index;
t = s->line + 2;
while (t && *t)
{
- if ((entry = command_search(t, 15, &matched)) <= 0)
+ if ((entry = command_search(t, &matched)) <= 0)
break;
if ((t = at_commands[entry - 1](s, t)) == NULL)
break;
int output_length;
int input_width;
int input_length;
+ int x;
double c1;
double c2;
- int x;
#if defined(SPANDSP_USE_FIXED_POINT)
int frac_row;
int frac_col;
x = i*input_width/output_width;
frac_col = x - x*output_width;
c1 = s->raw_pixel_row[0][x] + (s->raw_pixel_row[0][x + 1] - s->raw_pixel_row[0][x])*frac_col;
- c1 = s->raw_pixel_row[1][x] + (s->raw_pixel_row[1][x + 1] - s->raw_pixel_row[1][x])*frac_col;
+ c2 = s->raw_pixel_row[1][x] + (s->raw_pixel_row[1][x + 1] - s->raw_pixel_row[1][x])*frac_col;
buf[i] = saturateu8(c1 + (c2 - c1)*frac_row);
}
#else
return 0xc0000000;
return 0x40000000;
}
-
+
abs_y = fabsf(y);
/* If we are in quadrant II or III, flip things around */
#include <spandsp/private/t4_t6_encode.h>
/*#include <spandsp/private/t81_t82_arith_coding.h>*/
/*#include <spandsp/private/t85.h>*/
+/*#include <spandsp/private/t42.h>*/
+/*#include <spandsp/private/t43.h>*/
#include <spandsp/private/t4_rx.h>
#include <spandsp/private/t4_tx.h>
#include <spandsp/private/t30.h>
#define T30_DCS_BIT_200_200 15
#define T30_DIS_BIT_2D_CAPABLE 16
-#define T30_DCS_BIT_2D_CODING 16
+#define T30_DCS_BIT_2D_MODE 16
/* Standard facsimile terminals conforming to ITU-T Rec. T.4 must have the following capability:
Paper length = 297 mm. */
#define T30_DIS_BIT_POLLED_SUBADDRESSING_CAPABLE 35
#define T30_DIS_BIT_T43_CAPABLE 36
-#define T30_DCS_BIT_T43_CODING 36
+#define T30_DCS_BIT_T43_MODE 36
#define T30_DIS_BIT_PLANE_INTERLEAVE_CAPABLE 37
#define T30_DCS_BIT_PLANE_INTERLEAVE 37
bits 49, 102 and 50 in DCS or bits 47, 101, 50 and 35 in DTC shall be set to "1" with the following
meaning:
Bit DIS DTC DCS
- 35 Polled SubAddress capability Polled SubAddress transmission Not allowed \96 set to "0"
- 47 Selective polling capability Selective polling transmission Not allowed \96 set to "0"
+ 35 Polled SubAddress capability Polled SubAddress transmission Not allowed - set to "0"
+ 47 Selective polling capability Selective polling transmission Not allowed - set to "0"
49 Subaddressing capability Not allowed (Set to "0") Subaddressing transmission
50 Password Password transmission Sender Identification transmission
- 101 Internet Selective Polling Address capability Internet Selective Polling Address transmission Not allowed \96 set to "0"
+ 101 Internet Selective Polling Address capability Internet Selective Polling Address transmission Not allowed - set to "0"
102 Internet Routing Address capability Not allowed (Set to "0") Internet Routing Address transmission
Terminals conforming to the 1993 version of T.30 may set the above bits to "0" even though PWD/SEP/SUB
/*! \brief The time at which handling of the current page began. */
time_t page_start_time;
+ /*! \brief TRUE for FAX page headers to overlay (i.e. replace) the beginning of the
+ page image. FALSE for FAX page headers to add to the overall length of
+ the page. */
+ int header_overlays_image;
/*! \brief The text which will be used in FAX page header. No text results
in no header line. */
const char *header_info;
/*! \brief The register for the data scrambler. */
uint32_t scramble_reg;
/*! \brief Scrambler tap */
- //int scrambler_tap;
+ int scrambler_tap;
/*! \brief TRUE if the short training sequence is to be used. */
int short_train;
/*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
#if defined(SPANDSP_USE_FIXED_POINT)
- complexi16_t rrc_filter[2*V17_TX_FILTER_STEPS];
+ /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
+ int16_t rrc_filter_re[V17_TX_FILTER_STEPS];
+ int16_t rrc_filter_im[V17_TX_FILTER_STEPS];
#else
- complexf_t rrc_filter[2*V17_TX_FILTER_STEPS];
+ /*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
+ float rrc_filter_re[V17_TX_FILTER_STEPS];
+ float rrc_filter_im[V17_TX_FILTER_STEPS];
#endif
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
int rrc_filter_step;
/*! \brief The register for the data scrambler. */
uint32_t scramble_reg;
/*! \brief Scrambler tap */
- //int scrambler_tap;
+ int scrambler_tap;
/*! \brief TRUE if transmitting the training sequence. FALSE if transmitting user data. */
int in_training;
/*! \brief TRUE if the short training sequence is to be used. */
int error_correcting_mode_retries;
/*! \brief Current status. */
int current_status;
-#if 0
/*! \brief The number of RTP events in this call. */
int rtp_events;
/*! \brief The number of RTN events in this call. */
int rtn_events;
-#endif
} t30_stats_t;
#if defined(__cplusplus)
\param info A POSIX timezone description string. */
SPAN_DECLARE(void) t4_tx_set_header_tz(t4_state_t *s, const char *tzstring);
+/*! Set page header extends or overlays the image mode.
+ \brief Set page header overlay mode.
+ \param s The T.4 context.
+ \param header_overlays_image TRUE for overlay, or FALSE for extend the page. */
+SPAN_DECLARE(void) t4_tx_set_header_overlays_image(t4_state_t *s, int header_overlays_image);
+
/*! \brief Set the row read handler for a T.4 transmit context.
\param s The T.4 transmit context.
\param handler A pointer to the handler routine.
#include "spandsp/v27ter_tx.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/t43.h"
+#endif
#include "spandsp/t4_t6_decode.h"
#include "spandsp/t4_t6_encode.h"
#include "spandsp/t30_fcf.h"
#include "spandsp/t30_logging.h"
#include "spandsp/private/logging.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/private/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/private/t43.h"
+#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/t4_rx.h"
static void disconnect(t30_state_t *s);
static void decode_20digit_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int len);
static void decode_url_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int len);
+static int decode_nsf_nss_nsc(t30_state_t *s, uint8_t *msg[], const uint8_t *pkt, int len);
static int set_min_scan_time_code(t30_state_t *s);
static int send_cfr_sequence(t30_state_t *s, int start);
static void timer_t2_start(t30_state_t *s);
/* Select the compression to use. */
switch (s->line_encoding)
{
+#if defined(SPANDSP_SUPPORT_T42)
+ case T4_COMPRESSION_ITU_T42:
+ set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
+ set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
+ break;
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+ case T4_COMPRESSION_ITU_T43:
+ set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE);
+ set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
+ break;
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
case T4_COMPRESSION_ITU_T85:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_MODE);
clr_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_L0_MODE);
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T85_L0_MODE);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
break;
+#endif
case T4_COMPRESSION_ITU_T6:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T6_MODE);
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21);
break;
case T4_COMPRESSION_ITU_T4_2D:
- set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_2D_CODING);
+ set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_2D_MODE);
set_ctrl_bits(s->dcs_frame, s->min_scan_time_code, 21);
break;
case T4_COMPRESSION_ITU_T4_1D:
if (bad != T30_ERR_OK)
{
s->current_status = bad;
- span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) not an acceptable FAX image width\n", s->image_width);
+ span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
return -1;
}
switch (s->image_width)
if (bad != T30_ERR_OK)
{
s->current_status = bad;
- span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) not an acceptable FAX image width\n", s->image_width);
+ span_log(&s->logging, SPAN_LOG_FLOW, "Image width (%d pixels) is not an acceptable FAX image width\n", s->image_width);
return -1;
}
/* Deal with the image length */
return -1;
}
}
+#if 0
+ /* T.4 1D is always available */
+ bi_level_support = T30_SUPPORT_T4_1D_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
+ bi_level_support |= T30_SUPPORT_T4_2D_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
+ bi_level_support |= T30_SUPPORT_T6_COMPRESSION;
+ /* Bit 79 set with bit 78 clear is invalid, so let's completely ignore 79
+ if 78 is clear. */
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE))
+ {
+ bi_level_support |= T30_SUPPORT_T85_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE)
+ bi_level_support |= T30_SUPPORT_T85_L0_COMPRESSION;
+ }
+
+ gray_support = 0;
+ colour_support = 0;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE))
+ {
+ /* Multi-level coding available */
+ gray_support |= T30_SUPPORT_T81_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
+ gray_support |= T30_SUPPORT_T81_12BIT_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
+ {
+ gray_support |= T30_SUPPORT_T43_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
+ gray_support |= T30_SUPPORT_T43_COMPRESSION_12BIT;
+ }
+
+ if (test_ctrl_bit(s->far_dis_dtc_frame, bit69))
+ {
+ /* Colour coding available */
+ colour_support |= T30_SUPPORT_T81_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
+ colour_support |= T30_SUPPORT_T81_12BIT_COMPRESSION;
+ if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
+ {
+ colour_support |= T30_SUPPORT_T81_SUBSAMPLING_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
+ colour_support |= T30_SUPPORT_T81_SUBSAMPLING_COMPRESSION_12BIT;
+ }
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
+ {
+ colour_support |= T30_SUPPORT_T43_COMPRESSION;
+ if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
+ colour_support |= T30_SUPPORT_T43_12BIT_COMPRESSION;
+ }
+ }
+ /* bit74 custom illuminant */
+ /* bit75 custom gamut range */
+ }
+#endif
queue_phase(s, T30_PHASE_B_TX);
/* Try to send something */
if (s->tx_file[0])
{
s->line_encoding = T4_COMPRESSION_ITU_T6;
}
- else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_2D_CODING))
+ else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_2D_MODE))
{
s->line_encoding = T4_COMPRESSION_ITU_T4_2D;
}
span_log(&s->logging, SPAN_LOG_FLOW, "The remote was made by '%s'\n", s->vendor);
if (s->model)
span_log(&s->logging, SPAN_LOG_FLOW, "The remote is a '%s'\n", s->model);
+ s->rx_info.nsf_len = decode_nsf_nss_nsc(s, &s->rx_info.nsf, &msg[2], len - 2);
}
else
{
/* NSC - Non-standard facilities command */
/* OK in (NSC) (CIG) DTC */
+ s->rx_info.nsc_len = decode_nsf_nss_nsc(s, &s->rx_info.nsc, &msg[2], len - 2);
}
break;
case (T30_PWD & 0xFE):
break;
case (T30_NSS & 0xFE):
/* Non-standard facilities set-up */
+ s->rx_info.nss_len = decode_nsf_nss_nsc(s, &s->rx_info.nss, &msg[2], len - 2);
break;
case (T30_SUB & 0xFE):
/* Sub-address */
}
/*- End of function --------------------------------------------------------*/
+static int decode_nsf_nss_nsc(t30_state_t *s, uint8_t *msg[], const uint8_t *pkt, int len)
+{
+ uint8_t *t;
+
+ if ((t = malloc(len - 1)) == NULL)
+ return 0;
+ memcpy(t, pkt + 1, len - 1);
+ *msg = t;
+ return len - 1;
+}
+/*- End of function --------------------------------------------------------*/
+
static void t30_non_ecm_rx_status(void *user_data, int status)
{
t30_state_t *s;
t->encoding = stats.encoding;
t->image_size = stats.line_image_size;
t->current_status = s->current_status;
-#if 0
t->rtn_events = s->rtn_events;
t->rtp_events = s->rtp_events;
-#endif
}
/*- End of function --------------------------------------------------------*/
#include "spandsp/v27ter_tx.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/t43.h"
+#endif
#include "spandsp/t4_t6_decode.h"
#include "spandsp/t4_t6_encode.h"
#include "spandsp/t30_fcf.h"
#include "spandsp/t30_logging.h"
#include "spandsp/private/logging.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/private/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/private/t43.h"
+#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/t4_rx.h"
SPAN_DECLARE(int) t30_set_tx_page_header_overlays_image(t30_state_t *s, int header_overlays_image)
{
-#if 0
s->header_overlays_image = header_overlays_image;
t4_tx_set_header_overlays_image(&s->t4.tx, s->header_overlays_image);
-#endif
return 0;
}
/*- End of function --------------------------------------------------------*/
mask = T30_SUPPORT_T4_1D_COMPRESSION
| T30_SUPPORT_T4_2D_COMPRESSION
| T30_SUPPORT_T6_COMPRESSION
+#if defined(SPANDSP_SUPPORT_T42)
+ | T30_SUPPORT_T42_COMPRESSION
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+ | T30_SUPPORT_T43_COMPRESSION
+#endif
#if defined(SPANDSP_SUPPORT_T85)
| T30_SUPPORT_T85_COMPRESSION
- | T30_SUPPORT_T85_L0_COMPRESSION;
-#else
- | 0;
+ | T30_SUPPORT_T85_L0_COMPRESSION
#endif
+ | 0;
s->supported_compressions = supported_compressions & mask;
t30_build_dis_or_dtc(s);
return 0;
#include "spandsp/v27ter_tx.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/t43.h"
+#endif
#include "spandsp/t4_t6_decode.h"
#include "spandsp/t4_t6_encode.h"
#include "spandsp/t30_fcf.h"
#include "spandsp/t30_logging.h"
#include "spandsp/private/logging.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/private/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/private/t43.h"
+#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/t4_rx.h"
}
dle_unstuff(s, t, len);
break;
+ case AT_MODE_CONNECTED:
+ /* TODO: Implement for data modem operation */
+ break;
}
return len;
}
#include "spandsp/modem_connect_tones.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/t43.h"
+#endif
#include "spandsp/t4_t6_decode.h"
#include "spandsp/t4_t6_encode.h"
#include "spandsp/t30_fcf.h"
#include "spandsp/private/modem_connect_tones.h"
#include "spandsp/private/hdlc.h"
#include "spandsp/private/fax_modems.h"
-#if defined(SPANDSP_SUPPORT_T85)
+#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t81_t82_arith_coding.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t85.h"
#endif
+#if defined(SPANDSP_SUPPORT_T42)
+#include "spandsp/private/t42.h"
+#endif
+#if defined(SPANDSP_SUPPORT_T43)
+#include "spandsp/private/t43.h"
+#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/t4_rx.h"
case T30_EOS | 1:
#if 0
/* If we are hitting one of these conditions, it will take another DCS/DTC to select
- the fast modem again, so abandon our idea of t. */
+ the fast modem again, so abandon our idea of it. */
s->core.fast_bit_rate = 0;
s->core.fast_rx_modem = T38_NONE;
s->core.image_data_mode = FALSE;
}
/*- End of function --------------------------------------------------------*/
-static int t4_tx_put_fax_header(t4_state_t *s)
+static int t4_tx_put_fax_header(t4_state_t *s, int *rows)
{
int row;
int i;
repeats = 1;
break;
}
+ *rows = 16*repeats;
for (row = 0; row < 16; row++)
{
t = header;
int run_space;
int len;
int old_image_width;
+ int header_rows;
uint8_t *bufptr8;
uint32_t *bufptr;
if (s->header_info && s->header_info[0])
{
- if (t4_tx_put_fax_header(s))
+ if (t4_tx_put_fax_header(s, &header_rows))
return -1;
}
if (s->t4_t6_tx.row_read_handler)
}
/*- End of function --------------------------------------------------------*/
+SPAN_DECLARE(void) t4_tx_set_header_overlays_image(t4_state_t *s, int header_overlays_image)
+{
+ s->header_overlays_image = header_overlays_image;
+}
+/*- End of function --------------------------------------------------------*/
+
SPAN_DECLARE(void) t4_tx_set_local_ident(t4_state_t *s, const char *ident)
{
s->tiff.local_ident = (ident && ident[0]) ? ident : NULL;
#include "spandsp/telephony.h"
#include "spandsp/logging.h"
+#include "spandsp/fast_convert.h"
+#include "spandsp/math_fixed.h"
+#include "spandsp/saturated.h"
#include "spandsp/complex.h"
#include "spandsp/vector_float.h"
#include "spandsp/complex_vector_float.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/v17rx.h"
-#include "v17_v32bis_tx_constellation_maps.h"
-#include "v17_v32bis_rx_constellation_maps.h"
#if defined(SPANDSP_USE_FIXED_POINT)
#include "v17_v32bis_rx_fixed_rrc.h"
#else
#include "v17_v32bis_rx_floating_rrc.h"
#endif
+#include "v17_v32bis_tx_constellation_maps.h"
+#include "v17_v32bis_rx_constellation_maps.h"
/*! The nominal frequency of the carrier, in Hertz */
#define CARRIER_NOMINAL_FREQ 1800.0f
{
int out_bit;
- //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;
+ out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
s->scramble_reg <<= 1;
if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION && s->training_stage < TRAINING_STAGE_TCM_WINDUP)
s->scramble_reg |= out_bit;
s->put_bit = put_bit;
s->put_bit_user_data = user_data;
s->short_train = FALSE;
- //s->scrambler_tap = 18 - 1;
+ s->scrambler_tap = 18 - 1;
v17_rx_signal_cutoff(s, -45.5f);
s->carrier_phase_rate_save = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
v17_rx_restart(s, bit_rate, s->short_train);
{
int out_bit;
- //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;
+ out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
s->scramble_reg = (s->scramble_reg << 1) | out_bit;
return out_bit;
}
SPAN_DECLARE_NONSTD(int) v17_tx(v17_tx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
- complexi_t x;
- complexi_t z;
+ complexi16_t v;
+ complexi32_t x;
+ complexi32_t z;
+ int16_t iamp;
#else
+ complexf_t v;
complexf_t x;
complexf_t z;
+ float famp;
#endif
- int i;
int sample;
if (s->training_step >= V17_TRAINING_SHUTDOWN_END)
if ((s->baud_phase += 3) >= 10)
{
s->baud_phase -= 10;
- s->rrc_filter[s->rrc_filter_step] =
- s->rrc_filter[s->rrc_filter_step + V17_TX_FILTER_STEPS] = getbaud(s);
+ v = getbaud(s);
+ s->rrc_filter_re[s->rrc_filter_step] = v.re;
+ s->rrc_filter_im[s->rrc_filter_step] = v.im;
if (++s->rrc_filter_step >= V17_TX_FILTER_STEPS)
s->rrc_filter_step = 0;
}
- /* Root raised cosine pulse shaping at baseband */
#if defined(SPANDSP_USE_FIXED_POINT)
- x = complex_seti(0, 0);
- for (i = 0; i < V17_TX_FILTER_STEPS; i++)
- {
- x.re += (int32_t) tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].re;
- x.im += (int32_t) tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].im;
- }
+ /* Root raised cosine pulse shaping at baseband */
+ x.re = vec_circular_dot_prodi16(s->rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V17_TX_FILTER_STEPS, s->rrc_filter_step) >> 4;
+ x.im = vec_circular_dot_prodi16(s->rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V17_TX_FILTER_STEPS, s->rrc_filter_step) >> 4;
/* Now create and modulate the carrier */
- x.re >>= 4;
- x.im >>= 4;
- z = dds_complexi(&(s->carrier_phase), s->carrier_phase_rate);
+ z = dds_complexi32(&s->carrier_phase, s->carrier_phase_rate);
+ iamp = ((int32_t) x.re*z.re - x.im*z.im) >> 15;
/* Don't bother saturating. We should never clip. */
- i = (x.re*z.re - x.im*z.im) >> 15;
- amp[sample] = (int16_t) ((i*s->gain) >> 15);
+ amp[sample] = (int16_t) (((int32_t) iamp*s->gain) >> 11);
#else
- x = complex_setf(0.0f, 0.0f);
- for (i = 0; i < V17_TX_FILTER_STEPS; i++)
- {
- x.re += tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].re;
- x.im += tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].im;
- }
+ /* Root raised cosine pulse shaping at baseband */
+ x.re = vec_circular_dot_prodf(s->rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V17_TX_FILTER_STEPS, s->rrc_filter_step);
+ x.im = vec_circular_dot_prodf(s->rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V17_TX_FILTER_STEPS, s->rrc_filter_step);
/* Now create and modulate the carrier */
- z = dds_complexf(&(s->carrier_phase), s->carrier_phase_rate);
+ z = dds_complexf(&s->carrier_phase, s->carrier_phase_rate);
+ famp = x.re*z.re - x.im*z.im;
/* Don't bother saturating. We should never clip. */
- amp[sample] = (int16_t) lfastrintf((x.re*z.re - x.im*z.im)*s->gain);
+ amp[sample] = (int16_t) lfastrintf(famp*s->gain);
#endif
}
return sample;
SPAN_DECLARE(void) v17_tx_power(v17_tx_state_t *s, float power)
{
+ float gain;
+
/* The constellation design seems to keep the average power the same, regardless
of which bit rate is in use. */
+ gain = 0.223f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN;
#if defined(SPANDSP_USE_FIXED_POINT)
- s->gain = 0.223f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*16.0f*(32767.0f/30672.52f)*32768.0f/TX_PULSESHAPER_GAIN;
+ s->gain = (int16_t) gain;
#else
- s->gain = 0.223f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN;
+ s->gain = gain;
#endif
}
/*- End of function --------------------------------------------------------*/
/* NB: some modems seem to use 3 instead of 1 for long training */
s->diff = (short_train) ? 0 : 1;
#if defined(SPANDSP_USE_FIXED_POINT)
- cvec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
+ vec_zeroi16(s->rrc_filter_re, sizeof(s->rrc_filter_re)/sizeof(s->rrc_filter_re[0]));
+ vec_zeroi16(s->rrc_filter_im, sizeof(s->rrc_filter_im)/sizeof(s->rrc_filter_im[0]));
#else
- cvec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
+ vec_zerof(s->rrc_filter_re, sizeof(s->rrc_filter_re)/sizeof(s->rrc_filter_re[0]));
+ vec_zerof(s->rrc_filter_im, sizeof(s->rrc_filter_im)/sizeof(s->rrc_filter_im[0]));
#endif
s->rrc_filter_step = 0;
s->convolution = 0;
span_log_set_protocol(&s->logging, "V.17 TX");
s->get_bit = get_bit;
s->get_bit_user_data = user_data;
- //s->scrambler_tap = 18 - 1;
+ s->scrambler_tap = 18 - 1;
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
v17_tx_power(s, -14.0f);
v17_tx_restart(s, bit_rate, tep, FALSE);
{
adsi_rx(rx_adsi, amp, frames);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
printf(" Cannot close speech file '%s'\n", bellcore_files[j]);
exit(2);
break;
adsi_rx(rx_adsi, amp, len);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
}
if (log_audio)
{
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
}
error = 100.0*(1.0 - sqrt(total/total_samples)/noise_source.rms);
printf("RMS = %.3f (expected %d) %.2f%% error [clipped samples %d+%d]\n",
- log10(sqrt(total/total_samples)/32768.0)*20.0 + DBM0_MAX_POWER,
+ 10.0*log10((total/total_samples)/(32768.0*32768.0) + 1.0e-10) + DBM0_MAX_POWER,
j,
error,
clip_low,
}
while (len > 0);
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit (2);
exit(2);
}
printf("Level is %fdBOv/%fdBm0\n", power_meter_current_dbov(&meter), power_meter_current_dbm0(&meter));
- if (fabs(power_meter_current_dbm0(&meter) + 10.0f) > 0.05f)
+ if (fabs(power_meter_current_dbm0(&meter) + 10.0f) > 0.1f)
{
printf("Test failed.\n");
exit(2);
exit(2);
}
printf("Level is %fdBOv/%fdBm0\n", power_meter_current_dbov(&meter), power_meter_current_dbm0(&meter));
- if (fabs(power_meter_current_dbov(&meter) + 10.0f) > 0.05f)
+ if (fabs(power_meter_current_dbov(&meter) + 10.0f) > 0.1f)
{
printf("Test failed.\n");
exit(2);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_COMPLEX);
exit(2);
hits += len;
}
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
printf(" Cannot close speech file '%s'\n", bellcore_files[j]);
exit(2);
}
while (len > 0);
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
{
s->spec_re_plot[2*i] = i*4000.0/512.0;
#if defined(HAVE_FFTW3_H)
- s->spec_re_plot[2*i + 1] = 20.0*log10(sqrt(s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768)) + 3.14;
+ s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14;
#else
- s->spec_re_plot[2*i + 1] = 20.0*log10(sqrt(s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768)) + 3.14;
+ s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14;
#endif
}
s->spec_re = new Ca_Line(512, s->spec_re_plot, 0, 0, FL_BLUE, CA_NO_POINT);
static void signal_free(signal_source_t *sig)
{
- if (sf_close(sig->handle) != 0)
+ if (sf_close_telephony(sig->handle))
{
fprintf(stderr, " Cannot close sound file '%s'\n", sig->name);
exit(2);
}
if (signal <= 0.0f)
return -99.0f;
- power = DBM0_MAX_POWER + 20.0f*log10f(signal/32767.0f);
+ power = DBM0_MAX_POWER + 20.0f*log10f(signal/32767.0f + 1.0e-10f);
if (power > dev->peak)
dev->peak = power;
return power;
printf("%-4s %-1d %-5.1f%6.2fs%9.2f%9.2f%9.2f%9.2f%9.2f\n",
test_name,
chan_model.model_no,
- 20.0f*log10f(-chan_model.erl),
+ 20.0f*log10f(-chan_model.erl + 1.0e-10f),
0.0f, //test_clock,
level_measurement_device_get_peak(rin_power_meter),
level_measurement_device_get_peak(rout_power_meter),
if (two_channel_file)
{
- sf_close(rxtxfile);
+ sf_close_telephony(rxtxfile);
}
else
{
- sf_close(txfile);
- sf_close(rxfile);
+ sf_close_telephony(txfile);
+ sf_close_telephony(rxfile);
}
- sf_close(ecfile);
+ sf_close_telephony(ecfile);
}
/*- End of function --------------------------------------------------------*/
}
match_test_name(argv[i]);
}
- if (sf_close(result_handle) != 0)
+ if (sf_close_telephony(result_handle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", "result_sound.wav");
exit(2);
}
signal_free(&local_css);
signal_free(&far_css);
- if (sf_close(residue_handle) != 0)
+ if (sf_close_telephony(residue_handle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", RESIDUE_FILE_NAME);
exit(2);
}
t4_rx_release(&t4_state);
- if (sf_close(inhandle) != 0)
+ if (sf_close(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", filename);
exit(2);
/*! \file */
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <inttypes.h>
faxtester_state_t *s;
s = (faxtester_state_t *) user_data;
- fprintf(stderr, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
+ span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
switch (status)
{
case SIG_STATUS_TRAINING_FAILED:
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
if (use_receiver_not_ready)
t30_set_receiver_not_ready(s, 3);
i = (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
machines[i - 'A'].succeeded = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12);
machines[i - 'A'].done = TRUE;
#include "spandsp-sim.h"
#include "fax_utils.h"
-void log_tx_parameters(t30_state_t *s, const char *tag)
+void fax_log_tx_parameters(t30_state_t *s, const char *tag)
{
const char *u;
}
/*- End of function --------------------------------------------------------*/
-void log_rx_parameters(t30_state_t *s, const char *tag)
+void fax_log_rx_parameters(t30_state_t *s, const char *tag)
{
const char *u;
}
/*- End of function --------------------------------------------------------*/
-void log_transfer_statistics(t30_state_t *s, const char *tag)
+void fax_log_transfer_statistics(t30_state_t *s, const char *tag)
{
t30_stats_t t;
#endif
}
/*- End of function --------------------------------------------------------*/
+
+int get_tiff_total_pages(const char *file)
+{
+ TIFF *tiff_file;
+ int max;
+
+ if ((tiff_file = TIFFOpen(file, "r")) == NULL)
+ return -1;
+ /* Each page *should* contain the total number of pages, but can this be
+ trusted? Some files say 0. Actually searching for the last page is
+ more reliable. */
+ max = 0;
+ while (TIFFSetDirectory(tiff_file, (tdir_t) max))
+ max++;
+ TIFFClose(tiff_file);
+ return max;
+}
+/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
{
#endif
-void log_tx_parameters(t30_state_t *s, const char *tag);
+void fax_log_tx_parameters(t30_state_t *s, const char *tag);
-void log_rx_parameters(t30_state_t *s, const char *tag);
+void fax_log_rx_parameters(t30_state_t *s, const char *tag);
-void log_transfer_statistics(t30_state_t *s, const char *tag);
+void fax_log_transfer_statistics(t30_state_t *s, const char *tag);
+
+int get_tiff_total_pages(const char *file);
#if defined(__cplusplus)
}
fsk_rx(caller_rx, caller_model_amp, samples);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
}
if (log_audio)
{
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
static void signal_free(signal_source_t *sig)
{
- if (sf_close(sig->handle) != 0)
+ if (sf_close_telephony(sig->handle))
{
fprintf(stderr, " Cannot close sound file '%s'\n", sig->name);
exit(2);
if (log_audio)
{
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
}
if (encode)
{
- if (sf_close(inhandle))
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME);
exit(2);
}
if (decode)
{
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
}
/*- End of function --------------------------------------------------------*/
+static void signal_to_distortion_tests(void)
+{
+ g722_encode_state_t enc_state;
+ g722_decode_state_t dec_state;
+ swept_tone_state_t *swept;
+ power_meter_t in_meter;
+ power_meter_t out_meter;
+ int16_t original[1024];
+ uint8_t compressed[1024];
+ int16_t decompressed[1024];
+ int len;
+ int len2;
+ int len3;
+ int i;
+ int32_t in_level;
+ int32_t out_level;
+
+ /* Test a back to back encoder/decoder pair to ensure we comply with Figure 11/G.722 to
+ Figure 16/G.722, Figure A.1/G.722, and Figure A.2/G.722 */
+ g722_encode_init(&enc_state, 64000, 0);
+ g722_decode_init(&dec_state, 64000, 0);
+ power_meter_init(&in_meter, 7);
+ power_meter_init(&out_meter, 7);
+
+ /* First some silence */
+ len = 1024;
+ memset(original, 0, len*sizeof(original[0]));
+ for (i = 0; i < len; i++)
+ in_level = power_meter_update(&in_meter, original[i]);
+ len2 = g722_encode(&enc_state, compressed, original, len);
+ len3 = g722_decode(&dec_state, decompressed, compressed, len2);
+ for (i = 0; i < len3; i++)
+ out_level = power_meter_update(&out_meter, decompressed[i]);
+ printf("Silence produces %d at the output\n", out_level);
+
+ /* Now a swept tone test */
+ swept = swept_tone_init(NULL, 25.0f, 3500.0f, -10.0f, 60*16000, FALSE);
+ do
+ {
+ len = swept_tone(swept, original, 1024);
+ for (i = 0; i < len; i++)
+ in_level = power_meter_update(&in_meter, original[i]);
+ len2 = g722_encode(&enc_state, compressed, original, len);
+ len3 = g722_decode(&dec_state, decompressed, compressed, len2);
+ for (i = 0; i < len3; i++)
+ out_level = power_meter_update(&out_meter, decompressed[i]);
+ printf("%10d, %10d, %f\n", in_level, out_level, (float) out_level/in_level);
+ }
+ while (len > 0);
+}
+/*- End of function --------------------------------------------------------*/
+
int main(int argc, char *argv[])
{
g722_encode_state_t enc_state;
if (itutests)
{
itu_compliance_tests();
+ signal_to_distortion_tests();
}
else
{
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
frames = g726_decode(&dec_state, amp, adpcmdata, adpcm);
outframes = sf_writef_short(outhandle, amp, frames);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
printf(" Cannot close audio file '%s'\n", IN_FILE_NAME);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
printf(" Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
outframes = sf_writef_short(outhandle, post_amp, frames);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
}
outframes = sf_writef_short(outhandle, post_amp, dec_frames);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", in_file_name);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
{
s->spec_re_plot[2*i] = i*4000.0/512.0;
#if defined(HAVE_FFTW3_H)
- s->spec_re_plot[2*i + 1] = 20.0*log10(sqrt(s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768)) + 3.14;
+ s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14;
#else
- s->spec_re_plot[2*i + 1] = 20.0*log10(sqrt(s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768)) + 3.14;
+ s->spec_re_plot[2*i + 1] = 10.0*log10((s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768*256.0*32768) + 1.0e-10) + 3.14;
#endif
}
s->spec_re = new Ca_Line(512, s->spec_re_plot, 0, 0, FL_BLUE, CA_NO_POINT);
fprintf(stderr, " Error writing audio file\n");
exit(2);
}
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_COMPLEXIFY);
exit(2);
}
if (speech_test)
{
- if (sf_close(inhandle1))
+ if (sf_close_telephony(inhandle1))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
}
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME1);
exit(2);
}
if (speech_test)
{
- if (sf_close(inhandle1))
+ if (sf_close_telephony(inhandle1))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME1);
exit(2);
}
- if (sf_close(inhandle2))
+ if (sf_close_telephony(inhandle2))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME2);
exit(2);
}
}
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME2);
exit(2);
float out;
double sumin;
double sumout;
+ double gain;
int i;
int j;
int p;
sumout += out*out;
}
/*endfor*/
- printf("%7.1f %f\n", swept_tone_current_frequency(s), 10.0*log10(sumout/sumin));
+ gain = (sumin != 0.0) ? 10.0*log10(sumout/sumin + 1.0e-10) : 0.0;
+ printf("%7.1f %f\n", swept_tone_current_frequency(s), gain);
}
/*endfor*/
swept_tone_free(s);
\section lpc10_tests_page_sec_1 What does it do?
\section lpc10_tests_page_sec_2 How is it used?
-To perform a general audio quality test, lpc10 should be run. The file ../test-data/local/short_nb_voice.wav
+To perform a general audio quality test, lpc10 should be run. The file ../test-data/local/dam9.wav
will be compressed to LPC10 data, decompressed, and the resulting audio stored in post_lpc10.wav.
*/
else
outframes = sf_writef_short(outhandle, post_amp, dec_len);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", in_file_name);
exit(2);
}
- if (sf_close(refhandle) != 0)
+ if (sf_close_telephony(refhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", REF_FILE_NAME);
exit(2);
}
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
outframes = sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES);
printf("%d samples of silence\n", C1_SILENCE_SAMPLES);
- if (sf_close(filehandle) != 0)
+ if (sf_close(filehandle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", "sound_c1.wav");
exit(2);
outframes = sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES);
printf("%d samples of silence\n", C3_SILENCE_SAMPLES);
- if (sf_close(filehandle) != 0)
+ if (sf_close(filehandle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", "sound_c3.wav");
exit(2);
}
/*endif*/
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
printf(" Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
/*endif*/
}
/*endwhile*/
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", bellcore_files[j]);
exit(2);
modem_connect_tones_rx(&ans_pr_rx, amp, frames);
}
/*endwhile*/
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", decode_test_file);
exit(2);
static void signal_free(signal_source_t *sig)
{
- if (sf_close(sig->handle) != 0)
+ if (sf_close_telephony(sig->handle))
{
fprintf(stderr, " Cannot close sound file '%s'\n", sig->name);
exit(2);
modem_echo_can_free(ctx);
signal_free(&local_css);
- if (sf_close(resulthandle) != 0)
+ if (sf_close_telephony(resulthandle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", "result_sound.wav");
exit(2);
s->audio_meter->sample(amp[i]/32768.0);
s->power_reading += ((amp[i]*amp[i] - s->power_reading) >> 10);
}
- if (s->power_reading <= 0)
- val = -90.0;
- else
- val = log10((double) s->power_reading/(32767.0f*32767.0f))*10.0f + 3.14 + 3.02;
+ val = 10.0*log10((double) s->power_reading/(32767.0*32767.0) + 1.0e-10) + 3.14 + 3.02;
snprintf(buf, sizeof(buf), "%5.1fdBm0", val);
s->audio_level->value(buf);
total += ((double) value)*((double) value);
}
printf ("RMS = %.3f (expected %d) %.2f%% error [clipped samples %d+%d]\n",
- log10(sqrt(total/total_samples)/32768.0)*20.0,
+ 10.0*log10((total/total_samples)/(32768.0*32768.0) + 1.0e-10),
level,
100.0*(1.0 - sqrt(total/total_samples)/(pow(10.0, level/20.0)*32768.0)),
clip_low,
clip_high);
- if (level < -5 && fabs(log10(sqrt(total/total_samples)/32768.0)*20.0 - level) > 0.2)
+ if (level < -5 && fabs(10.0*log10((total/total_samples)/(32768.0*32768.0) + 1.0e-10) - level) > 0.2)
{
printf("Test failed\n");
exit(2);
total += ((double) value)*((double) value);
}
printf ("RMS = %.3f (expected %d) %.2f%% error [clipped samples %d+%d]\n",
- log10(sqrt(total/total_samples)/32768.0)*20.0,
+ 10.0*log10((total/total_samples)/(32768.0*32768.0) + 1.0e-10),
level,
100.0*(1.0 - sqrt(total/total_samples)/(pow(10.0, level/20.0)*32768.0)),
clip_low,
clip_high);
- if (level < -5 && fabs(log10(sqrt(total/total_samples)/32768.0)*20.0 - level) > 0.2)
+ if (level < -5 && fabs(10.0*log10((total/total_samples)/(32768.0*32768.0) + 1.0e-10) - level) > 0.2)
{
printf("Test failed\n");
exit(2);
}
}
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
oki_adpcm_release(oki_enc_state);
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", in_file_name);
exit(2);
}
oki_adpcm_release(oki_dec_state);
oki_adpcm_release(oki_dec_state2);
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
typedef int (pcap_timing_update_handler_t)(void *user_data, struct timeval *ts);
typedef int (pcap_packet_handler_t)(void *user_data, const uint8_t *pkt, int len);
-
int pcap_scan_pkts(const char *file,
uint32_t src_addr,
uint16_t src_port,
}
}
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", INPUT_FILE_NAME);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
printf("Dropped %d of %d blocks\n", lost_blocks, block_no);
if (tone < 0)
{
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", INPUT_FILE_NAME);
exit(2);
}
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
*/
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
exit(2);
}
}
- sf_close(outhandle);
+ if (sf_close_telephony(outhandle))
+ {
+ fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
+ exit(2);
+ }
printf("Min on %d, max on %d, min off %d, max off %d\n", extremes[0], extremes[1], extremes[2], extremes[3]);
return 0;
}
if ((inhandle = sf_open_telephony_read(file, 1)) == NULL)
{
- printf(" Cannot open speech file '%s'\n", file);
+ printf(" Cannot open audio file '%s'\n", file);
exit(2);
}
sf_writef_short(outhandle, amp_out, inframes);
sample += inframes;
}
- sf_close(inhandle);
- sf_close(outhandle);
+ if (sf_close_telephony(inhandle))
+ {
+ fprintf(stderr, " Cannot close audio file '%s'\n", file);
+ exit(2);
+ }
+ if (sf_close_telephony(outhandle))
+ {
+ fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
+ exit(2);
+ }
return 0;
}
/*- End of function --------------------------------------------------------*/
*/
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
outframes = sf_writef_short(outhandle, amp, len);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit (2);
sumout += (double) buf[i]*(double) buf[i];
/*endfor*/
freq = swept_tone_current_frequency(swept);
- if (sumin)
- gain = 10.0*log10(sumout/sumin);
- else
- gain = 0.0;
+ gain = (sumin != 0.0) ? 10.0*log10(sumout/sumin + 1.0e-10) : 0.0;
printf("%7.1f Hz %.3f dBm0 < %.3f dBm0 < %.3f dBm0\n",
freq,
template[template_entry].min_level,
sig_tone_rx(s, amp, frames);
}
/*endwhile*/
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
printf(" Cannot close speech file '%s'\n", bellcore_files[j]);
exit(2);
/*endif*/
}
/*endfor*/
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
sample += x;
}
}
- if (sf_close(inhandle))
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", IN_FILE_NAME);
exit(2);
sample += x;
}
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
printf(" Cannot close speech file '%s'\n", bellcore_files[j]);
exit(2);
}
printf("Test with swept tone.\n");
- s = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 60*SAMPLE_RATE, 1);
+ s = swept_tone_init(NULL, 200.0f, 3900.0f, -10.0f, 60*SAMPLE_RATE, TRUE);
for (j = 0; j < 60*SAMPLE_RATE; j += BLOCK_LEN)
{
len = swept_tone(s, buf, BLOCK_LEN);
#endif
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("Phase E handler on channel %c\n", i);
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
//exit(0);
}
/*- End of function --------------------------------------------------------*/
}
if (decode_test_file)
{
- if (sf_close(in_handle) != 0)
+ 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(wave_handle) != 0)
+ if (sf_close_telephony(wave_handle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
exit(2);
*/
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
*
* Written by Steve Underwood <steveu@coppice.org>
*
- * Copyright (C) 2009 Steve Underwood
+ * Copyright (C) 2010 Steve Underwood
*
* All rights reserved.
*
* 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.
- *
- * Some code from SIPP (http://sf.net/projects/sipp) was used as a model
- * for how to work with PCAP files. That code was authored by Guillaume
- * TEISSIER from FTR&D 02/02/2006, and released under the GPL2 licence.
*/
+/*! \file */
+
+/* Enable the following definition to enable direct probing into the FAX structures */
+//#define WITH_SPANDSP_INTERNALS
+
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <unistd.h>
#endif
+//#if defined(WITH_SPANDSP_INTERNALS)
+#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
+//#endif
+
#include "udptl.h"
#include "spandsp.h"
+#include "spandsp-sim.h"
#include "fax_utils.h"
#include "pcap_parse.h"
#define INPUT_FILE_NAME "t38.pcap"
-#define OUTPUT_FILE_NAME "t38pcap.tif"
+#define INPUT_TIFF_FILE_NAME "../test-data/itu/fax/itutests.tif"
+#define OUTPUT_TIFF_FILE_NAME "t38pcap.tif"
+
+#define OUTPUT_WAVE_FILE_NAME "t38_decode2.wav"
+
+#define SAMPLES_PER_CHUNK 160
+
+static t38_core_state_t *t38_core;
+static t38_terminal_state_t *t38_terminal_state;
+static t38_gateway_state_t *t38_gateway_state;
+static fax_state_t *fax_state;
+static struct timeval now;
+static SNDFILE *wave_handle;
+
+static int log_audio;
+static int use_transmit_on_idle;
+static int done = FALSE;
-t38_terminal_state_t *t38_state;
-struct timeval now;
+static int started = FALSE;
+static int64_t current = 0;
static int phase_b_handler(t30_state_t *s, void *user_data, int result)
{
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
}
/*- End of function --------------------------------------------------------*/
}
/*- End of function --------------------------------------------------------*/
-static int timing_update(void *user_data, struct timeval *ts)
+static int t38_terminal_timing_update(void *user_data, struct timeval *ts)
{
t30_state_t *t30;
- t38_core_state_t *t38_core;
logging_state_t *logging;
int samples;
int partial;
- static int64_t current = 0;
int64_t when;
int64_t diff;
when = ts->tv_sec*1000000LL + ts->tv_usec;
if (current == 0)
+ {
+ if (started)
+ current = when;
+ return 0;
+ }
+
+ diff = when - current;
+ samples = diff/125LL;
+ while (samples > 0)
+ {
+ partial = (samples > SAMPLES_PER_CHUNK) ? SAMPLES_PER_CHUNK : samples;
+ //fprintf(stderr, "Update time by %d samples\n", partial);
+ logging = t38_terminal_get_logging_state(t38_terminal_state);
+ span_log_bump_samples(logging, partial);
+ logging = t38_core_get_logging_state(t38_core);
+ span_log_bump_samples(logging, partial);
+ t30 = t38_terminal_get_t30_state(t38_terminal_state);
+ logging = t30_get_logging_state(t30);
+ span_log_bump_samples(logging, partial);
+
+ t38_terminal_send_timeout(t38_terminal_state, partial);
current = when;
+ samples -= partial;
+ }
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int t38_gateway_timing_update(void *user_data, struct timeval *ts)
+{
+ t30_state_t *t30;
+ logging_state_t *logging;
+ int samples;
+ int partial;
+ int64_t when;
+ int64_t diff;
+ int16_t t38_amp[SAMPLES_PER_CHUNK];
+ int16_t t30_amp[SAMPLES_PER_CHUNK];
+ int16_t out_amp[2*SAMPLES_PER_CHUNK];
+ int t38_len;
+ int t30_len;
+ int outframes;
+ int i;
+
+ memcpy(&now, ts, sizeof(now));
+
+ when = ts->tv_sec*1000000LL + ts->tv_usec;
+ if (current == 0)
+ {
+ if (started)
+ current = when;
+ return 0;
+ }
diff = when - current;
samples = diff/125LL;
while (samples > 0)
{
- partial = (samples > 160) ? 160 : samples;
+ partial = (samples > SAMPLES_PER_CHUNK) ? SAMPLES_PER_CHUNK : samples;
//fprintf(stderr, "Update time by %d samples\n", partial);
- logging = t38_terminal_get_logging_state(t38_state);
+ logging = t38_gateway_get_logging_state(t38_gateway_state);
span_log_bump_samples(logging, partial);
- t38_core = t38_terminal_get_t38_core_state(t38_state);
logging = t38_core_get_logging_state(t38_core);
span_log_bump_samples(logging, partial);
- t30 = t38_terminal_get_t30_state(t38_state);
+ logging = fax_get_logging_state(fax_state);
+ span_log_bump_samples(logging, partial);
+ t30 = fax_get_t30_state(fax_state);
logging = t30_get_logging_state(t30);
span_log_bump_samples(logging, partial);
+
+ memset(out_amp, 0, sizeof(out_amp));
+
+ t30_len = fax_tx(fax_state, t30_amp, partial);
+ if (!use_transmit_on_idle)
+ {
+ /* 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. */
+ if (t30_len < partial)
+ {
+ memset(t30_amp + t30_len, 0, sizeof(int16_t)*(partial - t30_len));
+ t30_len = partial;
+ }
+ }
+ if (log_audio)
+ {
+ for (i = 0; i < t30_len; i++)
+ out_amp[2*i + 1] = t30_amp[i];
+ }
+ if (t38_gateway_rx(t38_gateway_state, t30_amp, t30_len))
+ break;
- t38_terminal_send_timeout(t38_state, partial);
+ t38_len = t38_gateway_tx(t38_gateway_state, t38_amp, partial);
+ if (!use_transmit_on_idle)
+ {
+ if (t38_len < partial)
+ {
+ memset(t38_amp + t38_len, 0, sizeof(int16_t)*(partial - t38_len));
+ t38_len = partial;
+ }
+ }
+ if (log_audio)
+ {
+ for (i = 0; i < t38_len; i++)
+ out_amp[2*i] = t38_amp[i];
+ }
+ if (fax_rx(fax_state, t38_amp, partial))
+ break;
+
+ if (log_audio)
+ {
+ outframes = sf_writef_short(wave_handle, out_amp, partial);
+ if (outframes != partial)
+ break;
+ }
+
+ if (done)
+ break;
+
current = when;
samples -= partial;
}
static int ifp_handler(void *user_data, const uint8_t msg[], int len, int seq_no)
{
- t38_core_state_t *t38_core;
int i;
-
+
+ started = TRUE;
+
printf("%5d >>> ", seq_no);
for (i = 0; i < len; i++)
printf("%02X ", msg[i]);
printf("\n");
- t38_core = t38_terminal_get_t38_core_state(t38_state);
t38_core_rx_ifp_packet(t38_core, msg, len, seq_no);
return 0;
}
/*- End of function --------------------------------------------------------*/
+static uint32_t parse_inet_addr(const char *s)
+{
+ int i;
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ uint32_t d;
+
+ a = 0;
+ b = 0;
+ c = 0;
+ d = 0;
+ i = sscanf(s, "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32, &a, &b, &c, &d);
+ switch (i)
+ {
+ case 4:
+ c = (c << 8) | d;
+ case 3:
+ b = (b << 16) | c;
+ case 2:
+ a = (a << 24) | b;
+ }
+ return a;
+}
+/*- End of function --------------------------------------------------------*/
+
int main(int argc, char *argv[])
{
t30_state_t *t30;
- t38_core_state_t *t38_core;
logging_state_t *logging;
const char *input_file_name;
int t38_version;
+ int caller;
int use_ecm;
int use_tep;
int options;
int supported_modems;
int fill_removal;
int opt;
+ int t38_terminal_operation;
uint32_t src_addr;
uint16_t src_port;
uint32_t dest_addr;
uint16_t dest_port;
-
+ caller = FALSE;
use_ecm = FALSE;
- t38_version = 1;
+ t38_version = 0;
options = 0;
input_file_name = INPUT_FILE_NAME;
fill_removal = FALSE;
use_tep = FALSE;
+ use_transmit_on_idle = TRUE;
supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
+ t38_terminal_operation = TRUE;
+ log_audio = FALSE;
src_addr = 0;
src_port = 0;
dest_addr = 0;
dest_port = 0;
- while ((opt = getopt(argc, argv, "D:d:eFi:m:oS:s:tv:")) != -1)
+ while ((opt = getopt(argc, argv, "cD:d:eFGi:lm:oS:s:tv:")) != -1)
{
switch (opt)
{
+ case 'c':
+ caller = TRUE;
+ break;
case 'D':
- dest_addr = atoi(optarg);
+ dest_addr = parse_inet_addr(optarg);
break;
case 'd':
dest_port = atoi(optarg);
case 'F':
fill_removal = TRUE;
break;
+ case 'G':
+ t38_terminal_operation = FALSE;
+ break;
case 'i':
input_file_name = optarg;
break;
+ case 'l':
+ log_audio = TRUE;
+ break;
case 'm':
supported_modems = atoi(optarg);
break;
options = atoi(optarg);
break;
case 'S':
- src_addr = atoi(optarg);
+ src_addr = parse_inet_addr(optarg);
break;
case 's':
src_port = atoi(optarg);
}
}
- if ((t38_state = t38_terminal_init(NULL, FALSE, tx_packet_handler, NULL)) == NULL)
+ printf("Using T.38 version %d\n", t38_version);
+
+ if (t38_terminal_operation)
{
- fprintf(stderr, "Cannot start the T.38 channel\n");
- exit(2);
- }
- t30 = t38_terminal_get_t30_state(t38_state);
- t38_core = t38_terminal_get_t38_core_state(t38_state);
- t38_set_t38_version(t38_core, t38_version);
- t38_terminal_set_config(t38_state, options);
- t38_terminal_set_tep_mode(t38_state, use_tep);
+ if ((t38_terminal_state = t38_terminal_init(NULL, caller, tx_packet_handler, NULL)) == NULL)
+ {
+ fprintf(stderr, "Cannot start the T.38 channel\n");
+ exit(2);
+ }
+ t30 = t38_terminal_get_t30_state(t38_terminal_state);
+ t38_core = t38_terminal_get_t38_core_state(t38_terminal_state);
+ t38_set_t38_version(t38_core, t38_version);
+ t38_terminal_set_config(t38_terminal_state, options);
+ t38_terminal_set_tep_mode(t38_terminal_state, use_tep);
- logging = t38_terminal_get_logging_state(t38_state);
- span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, "T.38");
-
- logging = t38_core_get_logging_state(t38_core);
- span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, "T.38");
-
- logging = t30_get_logging_state(t30);
- span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
- span_log_set_tag(logging, "T.38");
-
- t30_set_supported_modems(t30, supported_modems);
- t30_set_tx_ident(t30, "11111111");
- t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
- t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
- t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
- t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
- t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
- t30_set_ecm_capability(t30, TRUE);
- t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION | T30_SUPPORT_T85_COMPRESSION);
-
- if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, timing_update, process_packet, NULL))
- exit(2);
- /* Push the time along, to flush out any remaining activity from the application. */
- now.tv_sec += 60;
- timing_update(NULL, &now);
+ logging = t38_terminal_get_logging_state(t38_terminal_state);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "T.38");
+
+ logging = t38_core_get_logging_state(t38_core);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "T.38");
+
+ logging = t30_get_logging_state(t30);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "T.38");
+
+ t30_set_supported_modems(t30, supported_modems);
+ t30_set_tx_ident(t30, "11111111");
+ t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
+ if (caller)
+ t30_set_tx_file(t30, INPUT_TIFF_FILE_NAME, -1, -1);
+ else
+ t30_set_rx_file(t30, OUTPUT_TIFF_FILE_NAME, -1);
+ t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
+ t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
+ t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
+ t30_set_ecm_capability(t30, TRUE);
+ t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION | T30_SUPPORT_T85_COMPRESSION);
+
+ if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL))
+ exit(2);
+ /* Push the time along, to flush out any remaining activity from the application. */
+ now.tv_sec += 60;
+ t38_terminal_timing_update(NULL, &now);
+ }
+ else
+ {
+ 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);
+ }
+ }
+
+ if ((t38_gateway_state = t38_gateway_init(NULL, tx_packet_handler, NULL)) == NULL)
+ {
+ fprintf(stderr, "Cannot start the T.38 channel\n");
+ exit(2);
+ }
+ t38_core = t38_gateway_get_t38_core_state(t38_gateway_state);
+ t38_gateway_set_transmit_on_idle(t38_gateway_state, use_transmit_on_idle);
+ t38_set_t38_version(t38_core, t38_version);
+ t38_gateway_set_ecm_capability(t38_gateway_state, TRUE);
+
+ logging = t38_gateway_get_logging_state(t38_gateway_state);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "T.38");
+
+ logging = t38_core_get_logging_state(t38_core);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "T.38");
+
+ if ((fax_state = fax_init(NULL, caller)) == NULL)
+ {
+ fprintf(stderr, "Cannot start FAX\n");
+ exit(2);
+ }
+ t30 = fax_get_t30_state(fax_state);
+ fax_set_transmit_on_idle(fax_state, use_transmit_on_idle);
+ fax_set_tep_mode(fax_state, use_tep);
+ t30_set_supported_modems(t30, supported_modems);
+ t30_set_tx_ident(t30, "22222222");
+ t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
+ if (caller)
+ t30_set_tx_file(t30, INPUT_TIFF_FILE_NAME, -1, -1);
+ else
+ t30_set_rx_file(t30, OUTPUT_TIFF_FILE_NAME, -1);
+ t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B');
+ t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
+ t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
+ t30_set_ecm_capability(t30, TRUE);
+ t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
+
+ logging = fax_get_logging_state(fax_state);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "FAX ");
+
+ logging = t30_get_logging_state(t30);
+ span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
+ span_log_set_tag(logging, "FAX ");
+
+ if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_gateway_timing_update, process_packet, NULL))
+ exit(2);
+ /* Push the time along, to flush out any remaining activity from the application. */
+ now.tv_sec += 60;
+ t38_gateway_timing_update(NULL, &now);
+
+ fax_release(fax_state);
+ t38_gateway_release(t38_gateway_state);
+ if (log_audio)
+ {
+ if (sf_close_telephony(wave_handle))
+ {
+ fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
+ exit(2);
+ }
+ }
+ }
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H)
-#include <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)
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
succeeded[i - 'A'] = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12);
done[i - 'A'] = TRUE;
fax_release(fax_state_b);
if (log_audio)
{
- if (sf_close(wave_handle) != 0)
+ if (sf_close_telephony(wave_handle) != 0)
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
exit(2);
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H)
-#include <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)
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
succeeded[i - 'A'] = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12);
done[i - 'A'] = TRUE;
}
t38_gateway_release(t38_state_a);
t38_terminal_release(t38_state_b);
- if (sf_close(wave_handle) != 0)
+ if (sf_close_telephony(wave_handle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
t38_terminal_release(t38_state_b);
if (log_audio)
{
- if (sf_close(wave_handle) != 0)
+ if (sf_close_telephony(wave_handle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
exit(2);
*/
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <stdlib.h>
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H)
-#include <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)
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
succeeded[i - 'A'] = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12);
//done[i - 'A'] = TRUE;
//#define WITH_SPANDSP_INTERNALS
#if defined(HAVE_CONFIG_H)
-#include <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)
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase B", i);
printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_rx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
return T30_ERR_OK;
}
/*- End of function --------------------------------------------------------*/
i = (int) (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
t30_get_transfer_statistics(s, &t);
succeeded[i - 'A'] = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12);
done[i - 'A'] = TRUE;
fax_release(fax_state_b);
if (log_audio)
{
- if (sf_close(wave_handle) != 0)
+ if (sf_close_telephony(wave_handle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
exit(2);
count = 0;
}
}
- if (sf_close(inhandle) != 0)
+ if (sf_close(inhandle))
{
printf(" Cannot close audio file '%s'\n", in_file_name);
exit(2);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close(outhandle))
{
printf(" Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
outframes = sf_writef_short(outhandle, amp, len);
}
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit (2);
fi
}
-for TEST in PPS-MPS-lost-PPS ; do
+for TEST in PPS-MPS-lost-PPS
+do
run_tsb85_test
done
/*! \file */
#if defined(HAVE_CONFIG_H)
-#include <config.h>
+#include "config.h"
#endif
#include <inttypes.h>
#define OUTPUT_TIFF_FILE_NAME "tsb85.tif"
-#define OUTPUT_FILE_NAME_WAVE "tsb85.wav"
+#define OUTPUT_WAVE_FILE_NAME "tsb85.wav"
#define SAMPLES_PER_CHUNK 160
snprintf(tag, sizeof(tag), "%c: Phase D", i);
printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
if (use_receiver_not_ready)
t30_set_receiver_not_ready(s, 3);
i = (intptr_t) user_data;
snprintf(tag, sizeof(tag), "%c: Phase E", i);
printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result));
- log_transfer_statistics(s, tag);
- log_tx_parameters(s, tag);
- log_rx_parameters(s, tag);
+ fax_log_transfer_statistics(s, tag);
+ fax_log_tx_parameters(s, tag);
+ fax_log_rx_parameters(s, tag);
}
/*- End of function --------------------------------------------------------*/
else if (strcasecmp((const char *) tag, "TXFILE") == 0)
{
sprintf(next_tx_file, "%s/%s", image_path, (const char *) value);
-printf("Push '%s'\n", next_tx_file);
+ printf("Push '%s'\n", next_tx_file);
}
return 0;
}
if (log_audio)
{
- if ((out_handle = sf_open_telephony_write(OUTPUT_FILE_NAME_WAVE, 2)) == NULL)
+ if ((out_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
{
- fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
+ fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
printf("Test failed\n");
exit(2);
}
span_log_bump_samples(&s->logging, len);
- len = faxtester_tx(s, amp, 160);
+ len = faxtester_tx(s, amp, SAMPLES_PER_CHUNK);
if (fax_rx(fax, amp, len))
break;
/*endif*/
/*endfor*/
if (log_audio)
{
- if (sf_close(out_handle))
+ if (sf_close_telephony(out_handle))
{
- fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
+ fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
printf("Test failed\n");
exit(2);
}
fi
}
-for TEST in MRGN01 MRGN02 MRGN03 MRGN04 MRGN05 MRGN06a MRGN06b MRGN07 MRGN08 ; do
+for TEST in MRGN01 MRGN02 MRGN03 MRGN04 MRGN05 MRGN06a MRGN06b MRGN07 MRGN08
+do
run_tsb85_test
done
#MRGN16 fails because we don't adequately distinguish between receiving a
#bad image signal and receiving none at all.
-#for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN14 MRGN15 MRGN16 MRGN17 ; do
-for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN15 MRGN17 ; do
+#for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN14 MRGN15 MRGN16 MRGN17
+for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN15 MRGN17
+do
run_tsb85_test
done
-for TEST in ORGC01 ORGC02 ORGC03 ; do
+for TEST in ORGC01 ORGC02 ORGC03
+do
run_tsb85_test
done
-for TEST in OREN01 OREN02 OREN03 OREN04 OREN05 OREN06 OREN07 OREN08 OREN09 OREN10 ; do
+for TEST in OREN01 OREN02 OREN03 OREN04 OREN05 OREN06 OREN07 OREN08 OREN09 OREN10
+do
run_tsb85_test
done
# MRGX05 is failing because we don't distinguish MPS immediately after MCF from MPS after
# a corrupt image signal.
-#for TEST in MRGX01 MRGX02 MRGX03 MRGX04 MRGX05 MRGX06 MRGX07 MRGX08 ; do
-for TEST in MRGX01 MRGX02 MRGX04 MRGX06 MRGX07 MRGX08 ; do
+#for TEST in MRGX01 MRGX02 MRGX03 MRGX04 MRGX05 MRGX06 MRGX07 MRGX08
+for TEST in MRGX01 MRGX02 MRGX04 MRGX06 MRGX07 MRGX08
+do
run_tsb85_test
done
-for TEST in MRGX09 MRGX10 MRGX11 MRGX12 MRGX13 MRGX14 MRGX15 ; do
+for TEST in MRGX09 MRGX10 MRGX11 MRGX12 MRGX13 MRGX14 MRGX15
+do
run_tsb85_test
done
-for TEST in MTGP01 MTGP02 OTGP03 ; do
+for TEST in MTGP01 MTGP02 OTGP03
+do
run_tsb85_test
done
-for TEST in MTGN01 MTGN02 MTGN03 MTGN04 MTGN05 MTGN06 MTGN07 MTGN08 MTGN09 MTGN10 ; do
+for TEST in MTGN01 MTGN02 MTGN03 MTGN04 MTGN05 MTGN06 MTGN07 MTGN08 MTGN09 MTGN10
+do
run_tsb85_test
done
-for TEST in MTGN11 MTGN12 MTGN13 MTGN14 MTGN15 MTGN16 MTGN17 MTGN18 MTGN19 MTGN20 ; do
+for TEST in MTGN11 MTGN12 MTGN13 MTGN14 MTGN15 MTGN16 MTGN17 MTGN18 MTGN19 MTGN20
+do
run_tsb85_test
done
-for TEST in MTGN21 MTGN22 MTGN23 MTGN24 MTGN25 MTGN26 MTGN27 MTGN28 ; do
+for TEST in MTGN21 MTGN22 MTGN23 MTGN24 MTGN25 MTGN26 MTGN27 MTGN28
+do
run_tsb85_test
done
-for TEST in OTGC01 OTGC02 OTGC03 OTGC04 OTGC05 OTGC06 OTGC07 OTGC08 ; do
+for TEST in OTGC01 OTGC02 OTGC03 OTGC04 OTGC05 OTGC06 OTGC07 OTGC08
+do
run_tsb85_test
done
-for TEST in OTGC09-01 OTGC09-02 OTGC09-03 OTGC09-04 OTGC09-05 OTGC09-06 OTGC09-07 OTGC09-08 OTGC09-09 OTGC09-10 OTGC09-11 OTGC09-12 ; do
+for TEST in OTGC09-01 OTGC09-02 OTGC09-03 OTGC09-04 OTGC09-05 OTGC09-06 OTGC09-07 OTGC09-08 OTGC09-09 OTGC09-10 OTGC09-11 OTGC09-12
+do
run_tsb85_test
done
-for TEST in OTGC10 OTGC11 ; do
+for TEST in OTGC10 OTGC11
+do
run_tsb85_test
done
#OTEN02 fails because ?????
-#for TEST in OTEN01 OTEN02 OTEN03 OTEN04 OTEN05 OTEN06 ; do
-for TEST in OTEN01 OTEN03 OTEN04 OTEN05 OTEN06 ; do
+#for TEST in OTEN01 OTEN02 OTEN03 OTEN04 OTEN05 OTEN06
+for TEST in OTEN01 OTEN03 OTEN04 OTEN05 OTEN06
+do
run_tsb85_test
done
#MTGX02 fails because ?????
-#for TEST in MTGX01 MTGX02 MTGX03 MTGX04 MTGX05 MTGX06 MTGX07 MTGX08 ; do
-for TEST in MTGX01 MTGX03 MTGX04 MTGX05 MTGX06 MTGX07 MTGX08 ; do
+#for TEST in MTGX01 MTGX02 MTGX03 MTGX04 MTGX05 MTGX06 MTGX07 MTGX08
+for TEST in MTGX01 MTGX03 MTGX04 MTGX05 MTGX06 MTGX07 MTGX08
+do
run_tsb85_test
done
-for TEST in MTGX09 MTGX10 MTGX11 MTGX12 MTGX13 MTGX14 MTGX15 MTGX16 ; do
+for TEST in MTGX09 MTGX10 MTGX11 MTGX12 MTGX13 MTGX14 MTGX15 MTGX16
+do
run_tsb85_test
done
-for TEST in MTGX17 MTGX18 MTGX19 MTGX20 MTGX21 MTGX22 MTGX23 ; do
+for TEST in MTGX17 MTGX18 MTGX19 MTGX20 MTGX21 MTGX22 MTGX23
+do
run_tsb85_test
done
-for TEST in MRGP01 MRGP02 MRGP03 MRGP04 MRGP05 MRGP06 MRGP07 MRGP08 ; do
+for TEST in MRGP01 MRGP02 MRGP03 MRGP04 MRGP05 MRGP06 MRGP07 MRGP08
+do
run_tsb85_test
done
-for TEST in ORGP09 ORGP10 ; do
+for TEST in ORGP09 ORGP10
+do
run_tsb85_test
done
break;
v18_rx(v18_state, amp, len);
}
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
basic_tests(V18_MODE_5BIT_45);
if (log_audio)
{
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
#endif
if (decode_test_file)
{
- if (sf_close(inhandle))
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
}
if (log_audio)
{
- if (sf_close(outhandle) != 0)
+ if (sf_close_telephony(outhandle) != 0)
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
#endif
if (decode_test_file)
{
- if (sf_close(inhandle))
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
}
if (log_audio)
{
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
#endif
if (decode_test_file)
{
- if (sf_close(inhandle))
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file);
exit(2);
}
if (log_audio)
{
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME);
exit(2);
static void v42_status(void *user_data, int status)
{
- int x;
+ v42_state_t *s;
- x = (intptr_t) user_data;
+ s = (v42_state_t *) user_data;
if (status < 0)
- printf("%d: Status is '%s' (%d)\n", x, signal_status_to_str(status), status);
+ printf("%p: Status is '%s' (%d)\n", s, signal_status_to_str(status), status);
else
- printf("%d: Status is '%s' (%d)\n", x, lapm_status_to_str(status), status);
+ printf("%p: Status is '%s' (%d)\n", s, lapm_status_to_str(status), status);
}
/*- End of function --------------------------------------------------------*/
int j;
int k;
int x;
+ v42_state_t *s;
if (len < 0)
{
v42_status(user_data, len);
return 0;
}
- x = (intptr_t) user_data;
+ s = (v42_state_t *) user_data;
+ x = (s == &caller) ? 1 : 2;
if (variable_length)
{
j = make_mask32(len);
static void v42_put_frames(void *user_data, const uint8_t *msg, int len)
{
int i;
+ v42_state_t *s;
int x;
+ static int count = 0;
+ static int xxx = 0;
if (len < 0)
{
v42_status(user_data, len);
return;
}
- x = (intptr_t) user_data;
+ s = (v42_state_t *) user_data;
+ x = (s == &caller) ? 1 : 2;
for (i = 0; i < len; i++)
{
if (msg[i] != (rx_next[x] & 0xFF))
{
- printf("%d: Mismatch 0x%02X 0x%02X\n", x, msg[i], rx_next[x] & 0xFF);
+ printf("%p: Mismatch 0x%02X 0x%02X\n", user_data, msg[i], rx_next[x] & 0xFF);
exit(2);
}
rx_next[x]++;
}
- printf("%d: Got frame len %d\n", x, len);
+ printf("%p: Got frame len %d\n", user_data, len);
+ printf("%p: %d Far end busy status %d\n", user_data, count, v42_get_far_busy_status(s));
+ if (s == &caller)
+ {
+ if (++count == 5)
+ {
+ v42_set_local_busy_status(s, TRUE);
+ xxx = 1;
+ }
+ }
+ else
+ {
+ if (xxx && ++count == 45)
+ v42_set_local_busy_status(&caller, FALSE);
+ }
}
/*- End of function --------------------------------------------------------*/
}
}
- v42_init(&caller, TRUE, TRUE, v42_get_frames, v42_put_frames, (void *) 1);
- v42_init(&answerer, FALSE, TRUE, v42_get_frames, v42_put_frames, (void *) 2);
- v42_set_status_callback(&caller, v42_status, (void *) 1);
- v42_set_status_callback(&answerer, v42_status, (void *) 2);
+ v42_init(&caller, TRUE, TRUE, v42_get_frames, v42_put_frames, (void *) &caller);
+ v42_init(&answerer, FALSE, TRUE, v42_get_frames, v42_put_frames, (void *) &answerer);
+ v42_set_status_callback(&caller, v42_status, (void *) &caller);
+ v42_set_status_callback(&answerer, v42_status, (void *) &answerer);
v42_restart(&caller);
v42_restart(&answerer);
v8_free(v8_caller);
v8_free(v8_answerer);
- if (sf_close(inhandle) != 0)
+ if (sf_close_telephony(inhandle))
{
fprintf(stderr, " Cannot close speech file '%s'\n", decode_test_file);
exit(2);
if (outhandle)
{
- if (sf_close(outhandle))
+ if (sf_close_telephony(outhandle))
{
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);