forked from Mirrors/freeswitch
Tweaks to spandsp tests
This commit is contained in:
parent
62f21d8d57
commit
32f70174f5
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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 ]
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user