Tweaks to spandsp tests

This commit is contained in:
Steve Underwood 2011-12-06 01:00:22 +08:00
parent 62f21d8d57
commit 32f70174f5
8 changed files with 218 additions and 96 deletions

View File

@ -1,11 +1,11 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* fax_tests.c
* fax_tests.c - Tests for the audio and T.38 FAX modules.
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2003 Steve Underwood
* Copyright (C) 2005, 2006, 2009, 2010 Steve Underwood
*
* All rights reserved.
*
@ -23,6 +23,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
/*! \page fax_tests_page FAX tests
\section fax_tests_page_sec_1 What does it do?
\section fax_tests_page_sec_2 How does it work?
@ -33,11 +35,16 @@
#endif
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sndfile.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
//#if defined(WITH_SPANDSP_INTERNALS)
#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
@ -206,6 +213,7 @@ int main(int argc, char *argv[])
time_t end_time;
int scan_line_time;
char *page_header_info;
char *page_header_tz;
int opt;
t30_state_t *t30;
logging_state_t *logging;
@ -218,6 +226,7 @@ int main(int argc, char *argv[])
use_tep = FALSE;
polled_mode = FALSE;
page_header_info = NULL;
page_header_tz = NULL;
reverse_flow = FALSE;
use_transmit_on_idle = TRUE;
use_receiver_not_ready = FALSE;
@ -226,7 +235,7 @@ int main(int argc, char *argv[])
noise_level = -99;
scan_line_time = 0;
supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
while ((opt = getopt(argc, argv, "ehH:i:I:lm:n:prRs:S:tTw:")) != -1)
while ((opt = getopt(argc, argv, "ehH:i:I:lm:n:prRs:S:tTw:z:")) != -1)
{
switch (opt)
{
@ -278,6 +287,9 @@ int main(int argc, char *argv[])
case 'w':
t30_state_to_wreck = atoi(optarg);
break;
case 'z':
page_header_tz = optarg;
break;
default:
//usage();
exit(2);
@ -335,6 +347,8 @@ int main(int argc, char *argv[])
t30_set_tx_polled_sub_address(t30, "Polled sub-address");
t30_set_tx_selective_polling_address(t30, "Selective polling address");
t30_set_tx_page_header_info(t30, page_header_info);
if (page_header_tz)
t30_set_tx_page_header_tz(t30, page_header_tz);
t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
t30_set_ecm_capability(t30, use_ecm);
t30_set_supported_t30_features(t30,

View File

@ -18,8 +18,8 @@
run_fax_test()
{
rm -f fax_tests_1.tif
echo -i ${FILE} ${OPTS}
./fax_tests -i ${FILE} ${OPTS} >xyzzy 2>xyzzy2
echo ./fax_tests ${OPTS} -i ${FILE}
./fax_tests ${OPTS} -i ${FILE} >xyzzy 2>xyzzy2
RETVAL=$?
if [ $RETVAL != 0 ]
then

View File

@ -131,8 +131,8 @@ int main(int argc, char *argv[])
int16_t noise_sound[8830];
int16_t silence_sound[8192];
int i;
int outframes;
int voiced_length;
int randy;
double f;
double pk;
double ms;
@ -155,6 +155,18 @@ int main(int argc, char *argv[])
}
printf("Generate C1\n");
/* The sequence is
48.62ms of voiced sound from table C.1 of G.168
200.0ms of pseudo-noise
101.38ms of silence
The above is then repeated phase inverted.
The voice comes straight from C.1, repeated enough times to
fill out the 48.62ms period - i.e. 16 copies of the sequence.
The pseudo noise section is random numbers filtered by the spectral
pattern in Figure C.2 */
/* The set of C1 voice samples is ready for use in the output file. */
voiced_length = sizeof(css_c1)/sizeof(css_c1[0]);
for (i = 0; i < voiced_length; i++)
@ -208,13 +220,12 @@ int main(int argc, char *argv[])
#else
scale = 0.0;
#endif
randy = ((rand() >> 10) & 0x1) ? 1.0 : -1.0;
#if defined(HAVE_FFTW3_H)
in[i][0] = ((rand() >> 10) & 0x1) ? 1.0 : -1.0;
in[i][0] *= pow(10.0, scale/20.0)*35.0; //305360
in[i][0] = randy*pow(10.0, scale/20.0)*35.0;
in[8192 - i][0] = -in[i][0];
#else
in[i].re = ((rand() >> 10) & 0x1) ? 1.0 : -1.0;
in[i].re *= pow(10.0, scale/20.0)*35.0; //305360
in[i].re = randy*pow(10.0, scale/20.0)*35.0;
in[8192 - i].re = -in[i].re;
#endif
}
@ -233,38 +244,34 @@ int main(int argc, char *argv[])
}
pk = peak(noise_sound, 8192);
ms = rms(noise_sound, 8192);
printf("Noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
printf("Filtered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
for (i = 0; i < 8192; i++)
silence_sound[i] = 0.0;
for (i = 0; i < 16; i++)
outframes = sf_writef_short(filehandle, voiced_sound, voiced_length);
sf_writef_short(filehandle, voiced_sound, voiced_length);
printf("%d samples of voice\n", 16*voiced_length);
outframes = sf_writef_short(filehandle, noise_sound, 8192);
outframes = sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192);
sf_writef_short(filehandle, noise_sound, 8192);
sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192);
printf("%d samples of noise\n", C1_NOISE_SAMPLES);
outframes = sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES);
sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES);
printf("%d samples of silence\n", C1_SILENCE_SAMPLES);
/* Now phase invert the C1 set of voice samples. */
/* Now phase invert the C1 set of samples. */
voiced_length = sizeof(css_c1)/sizeof(css_c1[0]);
for (i = 0; i < voiced_length; i++)
voiced_sound[i] = -css_c1[i];
pk = peak(voiced_sound, voiced_length);
ms = rms(voiced_sound, voiced_length);
printf("Voiced level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
for (i = 0; i < 8192; i++)
noise_sound[i] = -noise_sound[i];
for (i = 0; i < 16; i++)
outframes = sf_writef_short(filehandle, voiced_sound, voiced_length);
sf_writef_short(filehandle, voiced_sound, voiced_length);
printf("%d samples of voice\n", 16*voiced_length);
outframes = sf_writef_short(filehandle, noise_sound, 8192);
outframes = sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192);
sf_writef_short(filehandle, noise_sound, 8192);
sf_writef_short(filehandle, noise_sound, C1_NOISE_SAMPLES - 8192);
printf("%d samples of noise\n", C1_NOISE_SAMPLES);
outframes = sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES);
sf_writef_short(filehandle, silence_sound, C1_SILENCE_SAMPLES);
printf("%d samples of silence\n", C1_SILENCE_SAMPLES);
if (sf_close(filehandle))
@ -287,6 +294,21 @@ int main(int argc, char *argv[])
}
printf("Generate C3\n");
/* The sequence is
72.69ms of voiced sound from table C.3 of G.168
200.0ms of pseudo-noise
127.31ms of silence
The above is then repeated phase inverted.
The voice comes straight from C.3, repeated enough times to
fill out the 72.69ms period - i.e. 14 copies of the sequence.
The pseudo noise section is AWGN filtered by the spectral
pattern in Figure C.2. Since AWGN has the quality of being its
own Fourier transform, we can use an approach like the one above
for the C1 signal, using AWGN samples instead of randomly alternating
ones and zeros. */
/* Take the supplied set of C3 voice samples. */
voiced_length = (sizeof(css_c3)/sizeof(css_c3[0]));
for (i = 0; i < voiced_length; i++)
@ -300,37 +322,102 @@ int main(int argc, char *argv[])
noise_sound[i] = awgn(&noise_source);
pk = peak(noise_sound, 8192);
ms = rms(noise_sound, 8192);
printf("Noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
printf("Unfiltered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
/* Now filter them */
#if defined(HAVE_FFTW3_H)
p = fftw_plan_dft_1d(8192, in, out, FFTW_BACKWARD, FFTW_ESTIMATE);
#else
p = fftw_create_plan(8192, FFTW_BACKWARD, FFTW_ESTIMATE);
#endif
for (i = 0; i < 8192; i++)
{
#if defined(HAVE_FFTW3_H)
in[i][0] = 0.0;
in[i][1] = 0.0;
#else
in[i].re = 0.0;
in[i].im = 0.0;
#endif
}
for (i = 1; i <= 3715; i++)
{
f = FAST_SAMPLE_RATE*i/8192.0;
#if 1
if (f < 50.0)
scale = -60.0;
else if (f < 100.0)
scale = scaling(f, 50.0, 100.0, -25.8, -12.8);
else if (f < 200.0)
scale = scaling(f, 100.0, 200.0, -12.8, 17.4);
else if (f < 215.0)
scale = scaling(f, 200.0, 215.0, 17.4, 17.8);
else if (f < 500.0)
scale = scaling(f, 215.0, 500.0, 17.8, 12.2);
else if (f < 1000.0)
scale = scaling(f, 500.0, 1000.0, 12.2, 7.2);
else if (f < 2850.0)
scale = scaling(f, 1000.0, 2850.0, 7.2, 0.0);
else if (f < 3600.0)
scale = scaling(f, 2850.0, 3600.0, 0.0, -2.0);
else if (f < 3660.0)
scale = scaling(f, 3600.0, 3660.0, -2.0, -20.0);
else if (f < 3680.0)
scale = scaling(f, 3600.0, 3680.0, -20.0, -30.0);
else
scale = -60.0;
#else
scale = 0.0;
#endif
#if defined(HAVE_FFTW3_H)
in[i][0] = noise_sound[i]*pow(10.0, scale/20.0)*0.0106;
in[8192 - i][0] = -in[i][0];
#else
in[i].re = noise_sound[i]*pow(10.0, scale/20.0)*0.0106;
in[8192 - i].re = -in[i].re;
#endif
}
#if defined(HAVE_FFTW3_H)
fftw_execute(p);
#else
fftw_one(p, in, out);
#endif
for (i = 0; i < 8192; i++)
{
#if defined(HAVE_FFTW3_H)
noise_sound[i] = out[i][1];
#else
noise_sound[i] = out[i].im;
#endif
}
pk = peak(noise_sound, 8192);
ms = rms(noise_sound, 8192);
printf("Filtered noise level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
for (i = 0; i < 14; i++)
outframes = sf_writef_short(filehandle, voiced_sound, voiced_length);
sf_writef_short(filehandle, voiced_sound, voiced_length);
printf("%d samples of voice\n", 14*voiced_length);
outframes = sf_writef_short(filehandle, noise_sound, 8192);
outframes = sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192);
sf_writef_short(filehandle, noise_sound, 8192);
sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192);
printf("%d samples of noise\n", C3_NOISE_SAMPLES);
outframes = sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES);
sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES);
printf("%d samples of silence\n", C3_SILENCE_SAMPLES);
/* Now phase invert the set of voice samples. */
/* Now phase invert the C3 set of samples. */
voiced_length = (sizeof(css_c3)/sizeof(css_c3[0]));
for (i = 0; i < voiced_length; i++)
voiced_sound[i] = -css_c3[i];
pk = peak(voiced_sound, voiced_length);
ms = rms(voiced_sound, voiced_length);
printf("Voiced level = %.2fdB, crest factor = %.2fdB\n", rms_to_dbm0(ms), rms_to_db(pk/ms));
/* Now phase invert the set of noise samples. */
for (i = 0; i < 8192; i++)
noise_sound[i] = -noise_sound[i];
for (i = 0; i < 14; i++)
outframes = sf_writef_short(filehandle, voiced_sound, voiced_length);
printf("%d samples of voice\n", 14*i);
outframes = sf_writef_short(filehandle, noise_sound, 8192);
outframes = sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192);
sf_writef_short(filehandle, voiced_sound, voiced_length);
printf("%d samples of voice\n", 14*voiced_length);
sf_writef_short(filehandle, noise_sound, 8192);
sf_writef_short(filehandle, noise_sound, C3_NOISE_SAMPLES - 8192);
printf("%d samples of noise\n", C3_NOISE_SAMPLES);
outframes = sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES);
sf_writef_short(filehandle, silence_sound, C3_SILENCE_SAMPLES);
printf("%d samples of silence\n", C3_SILENCE_SAMPLES);
if (sf_close(filehandle))

View File

@ -334,6 +334,15 @@ then
fi
echo lpc10_tests completed OK
./math_fixed_tests >$STDOUT_DEST 2>$STDERR_DEST
RETVAL=$?
if [ $RETVAL != 0 ]
then
echo math_fixed_tests failed!
exit $RETVAL
fi
echo math_fixed_tests completed OK
./modem_echo_tests >$STDOUT_DEST 2>$STDERR_DEST
RETVAL=$?
if [ $RETVAL != 0 ]

View File

@ -311,6 +311,7 @@ int main(int argc, char *argv[])
const char *in_file_name;
const char *decode_file_name;
const char *page_header_tz;
tz_t tz;
int opt;
int i;
int bit_error_rate;
@ -678,7 +679,10 @@ int main(int argc, char *argv[])
else
t4_tx_set_header_info(&send_state, NULL);
if (page_header_tz && page_header_tz[0])
t4_tx_set_header_tz(&send_state, page_header_tz);
{
if (tz_init(&tz, page_header_tz))
t4_tx_set_header_tz(&send_state, &tz);
}
//t4_tx_set_header_overlays_image(&send_state, overlay_page_headers);
if (restart_pages && (sends & 1))
{

View File

@ -82,7 +82,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try a different tone pair */
@ -104,7 +104,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try a different tone pair */
@ -126,7 +126,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try a single tone */
@ -148,7 +148,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try a single non-repeating tone */
@ -170,7 +170,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try a single non-repeating tone at 0dBm0 */
@ -192,7 +192,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try an AM modulated tone at a modest modulation level (25%) */
@ -214,7 +214,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
/* Try an AM modulated tone at maximum modulation level (100%) */
@ -236,7 +236,7 @@ int main(int argc, char *argv[])
printf("Generated %d samples\n", len);
if (len <= 0)
break;
outframes = sf_writef_short(outhandle, amp, len);
sf_writef_short(outhandle, amp, len);
}
if (sf_close_telephony(outhandle))

View File

@ -2,11 +2,12 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* udptl.c
* udptl.c - An implementation of the UDPTL protocol defined in T.38,
* less the packet exchange part
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2009 Steve Underwood
* Copyright (C) 2005 Steve Underwood
*
* All rights reserved.
*
@ -62,15 +63,14 @@ static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue)
}
/*- End of function --------------------------------------------------------*/
static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t ** p_object, int *p_num_octets)
static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets)
{
int octet_cnt;
int octet_idx;
int stat;
int i;
const uint8_t **pbuf;
for (octet_idx = 0, *p_num_octets = 0;; octet_idx += octet_cnt)
for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt)
{
if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0)
return -1;
@ -79,7 +79,6 @@ static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8
*p_num_octets += octet_cnt;
pbuf = &p_object[octet_idx];
i = 0;
/* Make sure the buffer contains at least the number of bits requested */
if ((*len + octet_cnt) > limit)
return -1;
@ -113,7 +112,7 @@ static int encode_length(uint8_t *buf, int *len, int value)
return value;
}
/* Fragmentation */
multiplier = (value < 0x10000) ? (value >> 14) : 4;
multiplier = (value < 0x10000) ? (value >> 14) : 4;
/* Set the first 2 bits of the octet */
buf[(*len)++] = 0xC0 | multiplier;
return multiplier << 14;
@ -134,7 +133,7 @@ static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num
num_octets = 1;
}
/* Encode the open type */
for (octet_idx = 0;; num_octets -= enclen, octet_idx += enclen)
for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen)
{
if ((enclen = encode_length(buf, len, num_octets)) < 0)
return -1;
@ -192,7 +191,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
if (msg_len > LOCAL_FAX_MAX_DATAGRAM)
return -1;
/* Update any missed slots in the buffer */
for (i = s->rx_seq_no; seq_no > i; i++)
for (i = s->rx_seq_no; seq_no > i; i++)
{
x = i & UDPTL_BUF_MASK;
s->rx[x].buf_len = -1;
@ -219,7 +218,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
{
if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
return -1;
for (i = 0; i < count; i++)
for (i = 0; i < count; i++)
{
if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
return -1;
@ -235,12 +234,12 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
/* We received a later packet than we expected, so we need to check if we can fill in the gap from the
secondary packets. */
/* Step through in reverse order, so we go oldest to newest */
for (i = total_count; i > 0; i--)
for (i = total_count; i > 0; i--)
{
if (seq_no - i >= s->rx_seq_no)
{
/* This one wasn't seen before */
/* Decode the secondary packet */
/* Process the secondary packet */
#if defined(UDPTL_DEBUG)
fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
#endif
@ -286,7 +285,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
s->rx[x].fec_entries = entries;
/* Decode the elements */
for (i = 0; i < entries; i++)
for (i = 0; i < entries; i++)
{
if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
return -1;
@ -297,7 +296,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
#if 0
fprintf(stderr, "FEC: ");
for (j = 0; j < s->rx[x].fec_len[i]; j++)
for (j = 0; j < s->rx[x].fec_len[i]; j++)
fprintf(stderr, "%02X ", data[j]);
fprintf(stderr, "\n");
#endif
@ -307,28 +306,32 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
return -1;
/* See if we can reconstruct anything which is missing */
/* TODO: this does not comprehensively hunt back and repair everything that is possible */
for (l = x; l != ((x - (16 - span * entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK)
for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK)
{
if (s->rx[l].fec_len[0] <= 0)
continue;
for (m = 0; m < s->rx[l].fec_entries; m++)
for (m = 0; m < s->rx[l].fec_entries; m++)
{
limit = (l + m) & UDPTL_BUF_MASK;
for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit;
k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
for (which = -1, k = (limit - s->rx[l].fec_span*s->rx[l].fec_entries) & UDPTL_BUF_MASK;
k != limit;
k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
{
if (s->rx[k].buf_len <= 0)
which = (which == -1) ? k : -2;
which = (which == -1) ? k : -2;
}
if (which >= 0)
{
/* Repairable */
for (j = 0; j < s->rx[l].fec_len[m]; j++)
for (j = 0; j < s->rx[l].fec_len[m]; j++)
{
s->rx[which].buf[j] = s->rx[l].fec[m][j];
for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit;
k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
for (k = (limit - s->rx[l].fec_span*s->rx[l].fec_entries) & UDPTL_BUF_MASK;
k != limit;
k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
{
s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
}
}
s->rx[which].buf_len = s->rx[l].fec_len[m];
repaired[which] = TRUE;
@ -336,7 +339,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
}
}
/* Now play any new packets forwards in time */
for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++)
for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++)
{
if (repaired[l])
{
@ -348,8 +351,8 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
}
}
}
/* If packets are received out of sequence, we may have already processed this packet from the error
recovery information in a packet already received. */
/* If packets are received out of sequence, we may have already processed this packet
from the error recovery information in a packet already received. */
if (seq_no >= s->rx_seq_no)
{
/* Decode the primary packet */
@ -381,7 +384,7 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
/* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their
maximum length. */
if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM)
if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM)
return -1;
seq = s->tx_seq_no & 0xFFFF;
@ -427,7 +430,7 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
if (encode_length(buf, &len, entries) < 0)
return -1;
/* Encode the elements */
for (i = 0; i < entries; i++)
for (i = 0; i < entries; i++)
{
j = (entry - i - 1) & UDPTL_BUF_MASK;
if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0)
@ -437,10 +440,10 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
case UDPTL_ERROR_CORRECTION_FEC:
span = s->error_correction_span;
entries = s->error_correction_entries;
if (seq < s->error_correction_span * s->error_correction_entries)
if (seq < s->error_correction_span*s->error_correction_entries)
{
/* In the initial stages, wind up the FEC smoothly */
entries = seq / s->error_correction_span;
entries = seq/s->error_correction_span;
if (seq < s->error_correction_span)
span = 0;
}
@ -453,24 +456,24 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
/* The number of entries is defined as a length, but will only ever be a small
value. Treat it as such. */
buf[len++] = entries;
for (m = 0; m < entries; m++)
for (m = 0; m < entries; m++)
{
/* Make an XOR'ed entry the maximum length */
limit = (entry + m) & UDPTL_BUF_MASK;
high_tide = 0;
for (i = (limit - span * entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK)
for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK)
{
if (high_tide < s->tx[i].buf_len)
{
for (j = 0; j < high_tide; j++)
for (j = 0; j < high_tide; j++)
fec[j] ^= s->tx[i].buf[j];
for (; j < s->tx[i].buf_len; j++)
for ( ; j < s->tx[i].buf_len; j++)
fec[j] = s->tx[i].buf[j];
high_tide = s->tx[i].buf_len;
}
else
{
for (j = 0; j < s->tx[i].buf_len; j++)
for (j = 0; j < s->tx[i].buf_len; j++)
fec[j] ^= s->tx[i].buf[j];
}
}
@ -487,7 +490,10 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
}
/*- End of function --------------------------------------------------------*/
int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries)
int udptl_set_error_correction(udptl_state_t *s,
int ec_scheme,
int span,
int entries)
{
switch (ec_scheme)
{
@ -548,7 +554,12 @@ int udptl_get_far_max_datagram(udptl_state_t *s)
}
/*- End of function --------------------------------------------------------*/
udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data)
udptl_state_t *udptl_init(udptl_state_t *s,
int ec_scheme,
int span,
int entries,
udptl_rx_packet_handler_t rx_packet_handler,
void *user_data)
{
int i;
@ -571,7 +582,7 @@ udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries
memset(&s->rx, 0, sizeof(s->rx));
memset(&s->tx, 0, sizeof(s->tx));
for (i = 0; i <= UDPTL_BUF_MASK; i++)
for (i = 0; i <= UDPTL_BUF_MASK; i++)
{
s->rx[i].buf_len = -1;
s->tx[i].buf_len = -1;

View File

@ -119,17 +119,17 @@ static void reporter(void *user_data, int reason, bert_results_t *results)
static void v17_rx_status(void *user_data, int status)
{
v17_rx_state_t *rx;
v17_rx_state_t *s;
int i;
int len;
complexf_t *coeffs;
printf("V.17 rx status is %s (%d)\n", signal_status_to_str(status), status);
rx = (v17_rx_state_t *) user_data;
s = (v17_rx_state_t *) user_data;
switch (status)
{
case SIG_STATUS_TRAINING_SUCCEEDED:
len = v17_rx_equalizer_state(rx, &coeffs);
len = v17_rx_equalizer_state(s, &coeffs);
printf("Equalizer:\n");
for (i = 0; i < len; i++)
printf("%3d (%15.5f, %15.5f) -> %15.5f\n", i, coeffs[i].re, coeffs[i].im, powerf(&coeffs[i]));
@ -140,15 +140,12 @@ static void v17_rx_status(void *user_data, int status)
static void v17putbit(void *user_data, int bit)
{
v17_rx_state_t *rx;
if (bit < 0)
{
v17_rx_status(user_data, bit);
return;
}
rx = (v17_rx_state_t *) user_data;
if (decode_test_file)
printf("Rx bit %d - %d\n", rx_bits++, bit);
else