Tweaks to spandsp tests

Addition of tones to modem connect tones
Repeat function for V.18 TDD
This commit is contained in:
Steve Underwood 2012-07-14 23:34:40 +08:00
parent 860b53183d
commit 287678bc56
21 changed files with 6702 additions and 235 deletions

View File

@ -19,8 +19,6 @@
AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
MAINTAINERCLEANFILES = Makefile.in
DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
$(srcdir)/math_fixed_tables.h \
$(srcdir)/v17_v32bis_rx_fixed_rrc.h \
@ -46,6 +44,10 @@ DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
$(srcdir)/v29tx_fixed_rrc.h \
$(srcdir)/v29tx_floating_rrc.h
CLEANFILES = ${DISTCLEANFILES}
MOSTLYCLEANFILES = ${DISTCLEANFILES}
MAINTAINERCLEANFILES = ${DISTCLEANFILES}
EXTRA_DIST = floating_fudge.h \
libspandsp.dsp \
libspandsp.2005.sln \
@ -322,7 +324,8 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
nodist_include_HEADERS = spandsp.h
noinst_HEADERS = faxfont.h \
noinst_HEADERS = cielab_luts.h \
faxfont.h \
filter_tools.h \
gsm0610_local.h \
lpc10_encdecs.h \

View File

@ -179,27 +179,30 @@ SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
{
/* Align the received value */
if (s->data_bits < 8)
s->byte_in_progress >>= (8 - s->data_bits);
s->byte_in_progress = (s->byte_in_progress & 0xFF) >> (8 - s->data_bits);
s->put_byte(s->user_data, s->byte_in_progress);
s->bitpos = 0;
}
else if (s->use_v14)
{
/* This is actually the start bit for the next character, and
the stop bit has been dropped from the stream. This is the
rate adaption specified in V.14 */
/* Align the received value */
if (s->data_bits < 8)
s->byte_in_progress >>= (8 - s->data_bits);
s->put_byte(s->user_data, s->byte_in_progress);
s->bitpos = 1;
s->parity_bit = 0;
s->byte_in_progress = 0;
}
else
{
s->framing_errors++;
s->bitpos = 0;
if (s->use_v14)
{
/* This is actually the start bit for the next character, and
the stop bit has been dropped from the stream. This is the
rate adaption specified in V.14 */
/* Align the received value */
if (s->data_bits < 8)
s->byte_in_progress = (s->byte_in_progress & 0xFF) >> (8 - s->data_bits);
s->put_byte(s->user_data, s->byte_in_progress);
s->bitpos = 1;
s->parity_bit = 0;
s->byte_in_progress = 0;
}
else
{
s->framing_errors++;
s->bitpos = 0;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -336,6 +336,7 @@ SPAN_DECLARE(int) fax_modems_free(fax_modems_state_t *s)
{
if (s)
free(s);
/*endif*/
return 0;
}
/*- End of function --------------------------------------------------------*/

View File

@ -70,16 +70,16 @@ const fsk_spec_t preset_fsk_specs[] =
},
{
"V23 ch 1",
2100,
1300,
1700 + 400,
1700 - 400,
-14,
-30,
1200*100
},
{
"V23 ch 2",
450,
390,
420 + 30,
420 - 30,
-14,
-30,
75*100
@ -102,27 +102,35 @@ const fsk_spec_t preset_fsk_specs[] =
},
{
"Bell202",
2200,
1200,
1700 + 500,
1700 - 500,
-14,
-30,
1200*100
},
{
"Weitbrecht 45.45", /* Used for TDD (Telecoms Device for the Deaf) */
1800,
1400,
"Weitbrecht 45.45", /* Used for US TDD (Telecoms Device for the Deaf) */
1600 + 200,
1600 - 200,
-14,
-30,
4545
},
{
"Weitbrecht 50", /* Used for TDD (Telecoms Device for the Deaf) */
1800,
1400,
"Weitbrecht 50", /* Used for Internatioal TDD (Telecoms Device for the Deaf) */
1600 + 200,
1600 - 200,
-14,
-30,
5000
50*100
},
{
"V21 (110bps) ch 1",
1080 + 100,
1080 - 100,
-14,
-30,
110*100
}
};
@ -476,6 +484,10 @@ SPAN_DECLARE_NONSTD(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
s->put_bit(s->put_bit_user_data, baudstate);
}
break;
case FSK_FRAME_MODE_5N1_FRAMES:
case FSK_FRAME_MODE_7N1_FRAMES:
case FSK_FRAME_MODE_7E1_FRAMES:
case FSK_FRAME_MODE_7E2_FRAMES:
default:
/* Gather the specified number of bits, with robust checking to ensure reasonable voice immunity.
The first bit should be a start bit (0), and the last bit should be a stop bit (1) */
@ -527,24 +539,22 @@ SPAN_DECLARE_NONSTD(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
state as the next bit */
if (s->last_bit == baudstate)
{
s->frame_bits |= (baudstate << s->framing_mode);
s->frame_bits >>= 1;
s->baud_phase -= (SAMPLE_RATE*100);
if (++s->frame_state > s->framing_mode)
{
/* Check we have a stop bit */
if (baudstate == 1)
/* Check we have a stop bit and a start bit */
if (baudstate == 1 && (s->frame_bits & 0x02) == 0)
{
/* Check we have a start bit */
if ((s->frame_bits & 1) == 0)
{
/* Drop the start bit, and pass the rest back */
s->frame_bits >>= 1;
s->put_bit(s->put_bit_user_data, s->frame_bits);
}
/* Drop the start bit, and pass the rest back */
s->put_bit(s->put_bit_user_data, s->frame_bits >> 2);
}
s->frame_state = 0;
}
else
{
s->frame_bits |= (baudstate << s->framing_mode);
s->frame_bits >>= 1;
}
s->baud_phase -= (SAMPLE_RATE*100);
}
else
{

View File

@ -94,6 +94,8 @@ SPAN_DECLARE(const char *) modem_connect_tone_to_str(int tone)
return "FAX preamble";
case MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE:
return "FAX CED or preamble";
case MODEM_CONNECT_TONES_BELL_ANS:
return "Bell ANS";
case MODEM_CONNECT_TONES_CALLING_TONE:
return "Calling tone";
}
@ -206,6 +208,20 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *
}
s->duration_timer -= len;
break;
case MODEM_CONNECT_TONES_BELL_ANS:
if (s->duration_timer < len)
len = s->duration_timer;
if (s->duration_timer > ms_to_samples(2600))
{
/* There is some initial silence to be generated. */
if ((i = s->duration_timer - ms_to_samples(2600)) > len)
i = len;
memset(amp, 0, sizeof(int16_t)*i);
}
for ( ; i < len; i++)
amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0);
s->duration_timer -= len;
break;
case MODEM_CONNECT_TONES_CALLING_TONE:
for ( ; i < len; i++)
{
@ -301,6 +317,17 @@ SPAN_DECLARE(modem_connect_tones_tx_state_t *) modem_connect_tones_tx_init(modem
s->mod_phase = 0;
s->hop_timer = ms_to_samples(450);
break;
case MODEM_CONNECT_TONES_BELL_ANS:
/* 0.2s of silence, then 2.6s to 4s of 2225Hz+-15Hz tone, then 75ms of silence. */
s->tone_phase_rate = dds_phase_rate(2225.0);
s->level = dds_scaling_dbm0(-11);
s->mod_phase_rate = 0;
s->mod_level = 0;
s->duration_timer = ms_to_samples(200 + 2600);
s->tone_phase = 0;
s->mod_phase = 0;
s->hop_timer = 0;
break;
case MODEM_CONNECT_TONES_CALLING_TONE:
/* 0.6s of 1300Hz+-15Hz + 2.0s of silence repeating. */
s->tone_phase_rate = dds_phase_rate(1300.0);
@ -441,7 +468,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
/* A Cauer notch at 1100Hz, spread just wide enough to meet our detection bandwidth
criteria. */
/* Poles 0.736618498*exp(+-1047/4000 * PI * j)
Zeroes exp(+-1099.5 * PI * j) */
Zeroes exp(+-1099.5/4000 * PI * j) */
v1 = 0.792928f*famp + 1.0018744927985f*s->znotch_1 - 0.54196833412465f*s->znotch_2;
famp = v1 - 1.2994747954630f*s->znotch_1 + s->znotch_2;
s->znotch_2 = s->znotch_1;
@ -487,7 +514,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
famp = amp[i];
/* A Cauer bandpass at 15Hz, with which we demodulate the AM signal. */
/* Poles 0.9983989*exp(+-15/4000 * PI * j)
Zeroes exp(0 * PI * j) */
Zeroes exp(0/4000 * PI * j) */
v1 = fabs(famp) + 1.996667f*s->z15hz_1 - 0.9968004f*s->z15hz_2;
filtered = 0.001599787f*(v1 - s->z15hz_2);
s->z15hz_2 = s->z15hz_1;
@ -497,8 +524,8 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
/* A Cauer notch at 2100Hz, spread just wide enough to meet our detection bandwidth
criteria. */
/* Poles 0.7144255*exp(+-2105.612/4000 * PI * j)
Zeroes exp(+-2099.9 * PI * j) */
v1 = 0.76000f*famp - 0.1183852f*s->znotch_1 - 0.5104039f*s->znotch_2;
Zeroes exp(+-2099.9/4000 * PI * j) */
v1 = 0.7552f*famp - 0.1183852f*s->znotch_1 - 0.5104039f*s->znotch_2;
famp = v1 + 0.1567596f*s->znotch_1 + s->znotch_2;
s->znotch_2 = s->znotch_1;
s->znotch_1 = v1;
@ -585,6 +612,44 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
}
}
break;
case MODEM_CONNECT_TONES_BELL_ANS:
for (i = 0; i < len; i++)
{
famp = amp[i];
/* A Cauer notch at 2225Hz, spread just wide enough to meet our detection bandwidth
criteria. */
/* Poles 0.7144255*exp(+-2230.612/4000 * PI * j)
Zeroes exp(+-2224.9/4000 * PI * j) */
v1 = 0.739651f*famp - 0.257384f*s->znotch_1 - 0.510404f*s->znotch_2;
famp = v1 + 0.351437f*s->znotch_1 + s->znotch_2;
s->znotch_2 = s->znotch_1;
s->znotch_1 = v1;
notched = (int16_t) lfastrintf(famp);
/* Estimate the overall energy in the channel, and the energy in
the notch (i.e. overall channel energy - tone energy => noise).
Use abs instead of multiply for speed (is it really faster?). */
s->channel_level += ((abs(amp[i]) - s->channel_level) >> 5);
s->notch_level += ((abs(notched) - s->notch_level) >> 5);
if (s->channel_level > 70 && s->notch_level*6 < s->channel_level)
{
/* There is adequate energy in the channel, and it is mostly at 2225Hz. */
if (s->tone_present != MODEM_CONNECT_TONES_BELL_ANS)
{
if (++s->tone_cycle_duration >= ms_to_samples(415))
report_tone_state(s, MODEM_CONNECT_TONES_BELL_ANS, lfastrintf(log10f(s->channel_level/32768.0f)*20.0f + DBM0_MAX_POWER + 0.8f));
}
}
else
{
/* If the signal looks wrong, even for a moment, we consider this the
end of the tone. */
if (s->tone_present == MODEM_CONNECT_TONES_BELL_ANS)
report_tone_state(s, MODEM_CONNECT_TONES_NONE, -99);
s->tone_cycle_duration = 0;
}
}
break;
case MODEM_CONNECT_TONES_CALLING_TONE:
for (i = 0; i < len; i++)
{
@ -592,7 +657,7 @@ SPAN_DECLARE_NONSTD(int) modem_connect_tones_rx(modem_connect_tones_rx_state_t *
/* A Cauer notch at 1300Hz, spread just wide enough to meet our detection bandwidth
criteria. */
/* Poles 0.736618498*exp(+-1247/4000 * PI * j)
Zeroes exp(+-1299.5 * PI * j) */
Zeroes exp(+-1299.5/4000 * PI * j) */
v1 = 0.755582f*famp + 0.820887174515f*s->znotch_1 - 0.541968324778f*s->znotch_2;
famp = v1 - 1.0456667108f*s->znotch_1 + s->znotch_2;
s->znotch_2 = s->znotch_1;

View File

@ -110,7 +110,8 @@ enum
FSK_BELL103CH2,
FSK_BELL202,
FSK_WEITBRECHT, /* 45.45 baud version, used for TDD (Telecom Device for the Deaf) */
FSK_WEITBRECHT50 /* 50 baud version, used for TDD (Telecom Device for the Deaf) */
FSK_WEITBRECHT50, /* 50 baud version, used for TDD (Telecom Device for the Deaf) */
FSK_V21CH1_110 /* 110 bps version of V.21 channel 1, as used by V.18 */
};
enum
@ -119,7 +120,8 @@ enum
FSK_FRAME_MODE_SYNC = 1,
FSK_FRAME_MODE_5N1_FRAMES = 7, /* 5 bits of data + start bit + stop bit */
FSK_FRAME_MODE_7N1_FRAMES = 9, /* 7 bits of data + start bit + stop bit */
FSK_FRAME_MODE_8N1_FRAMES = 10 /* 8 bits of data + start bit + stop bit */
FSK_FRAME_MODE_7E1_FRAMES = 10, /* 7 bits of data + even parity + start bit + stop bit */
FSK_FRAME_MODE_7E2_FRAMES = 11 /* 7 bits of data + even parity + start bit + 2 stop bits */
};
SPAN_DECLARE_DATA extern const fsk_spec_t preset_fsk_specs[];

View File

@ -76,9 +76,11 @@ enum
This is only valid as a tone type to receive. It is never reported as a detected tone
type. The report will either be for FAX preamble or CED/ANS tone. */
MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE = 7,
/*! \brief Bell ANS tone is a pure continuous 2225Hz+-15Hz tone for 3.3s+-0.7s. */
MODEM_CONNECT_TONES_BELL_ANS = 8,
/*! \brief Calling tone is a pure 1300Hz tone, in 0.6s bursts, with 2s silences in between. The
bursts repeat for as long as is required. */
MODEM_CONNECT_TONES_CALLING_TONE = 8
MODEM_CONNECT_TONES_CALLING_TONE = 9
};
/*! \brief FAX CED tone is the same as ANS tone. */

View File

@ -45,7 +45,7 @@ struct async_tx_state_s
void *user_data;
/*! \brief A current, partially transmitted, character. */
int byte_in_progress;
unsigned int byte_in_progress;
/*! \brief The current bit position within a partially transmitted character. */
int bitpos;
/*! \brief Parity bit. */
@ -73,7 +73,7 @@ struct async_rx_state_s
void *user_data;
/*! \brief A current, partially complete, character. */
int byte_in_progress;
unsigned int byte_in_progress;
/*! \brief The current bit position within a partially complete character. */
int bitpos;
/*! \brief Parity bit. */

View File

@ -56,6 +56,7 @@ struct v18_state_s
int rx_msg_len;
int bit_pos;
int in_progress;
int repeat_shifts;
/*! \brief Error and flow logging control */
logging_state_t logging;

View File

@ -69,6 +69,55 @@
#include <stdlib.h>
/*
Ways in which a V.18 call may start
-----------------------------------
Originate:
ANS
Silence for 0.5s then send TXP
DTMF
Proceed as Annex B
1650Hz (V21 ch 2 low)
Proceed as Annex F in call mode
1300Hz (Calling tone)
Proceed as Annex E in call mode
1400Hz/1800Hz (Weitbrecht)
Detect rate and proceed as Annex A
980Hz/1180Hz (V21 ch 1)
Start timer Tr
2225Hz (Bell ANS)
Proceed as Annex D call mode
1270Hz (Bell103 ch 2 high)
Proceed as Annex D answer mode
390Hz (V23 ch 2 low)
Proceed as Annex E answer mode
Answer:
ANS
Monitor as caller for 980Hz or 1300Hz
CI/XCI
Respond with ANSam
1300Hz
Probe
Timer Ta (3s)
Probe
1400Hz/1800Hz (Weitbrecht)
Detect rate and proceed as Annex A
DTMF
Proceed as Annex B
980Hz (V21 ch 1 low)
Start timer Te
1270Hz (Bell103 ch 2 high)
Proceed as Annex D answer mode
2225Hz (Bell ANS)
Proceed as Annex D call mode
1650Hz (V21 ch 2 low)
Proceed as Annex F answer mode
ANSam
Proceed as V.8 caller Annex G
*/
/*! The baudot code to shift from alpha to digits and symbols */
#define BAUDOT_FIGURE_SHIFT 0x1B
/*! The baudot code to shift from digits and symbols to alpha */
@ -310,6 +359,20 @@ static const char *ascii_to_dtmf[128] =
"*0" /* DEL >> BACK SPACE */
};
static const uint8_t txp[] = "1111111111000101011100001101110000010101";
/* XCI is:
400 ms mark;
XCI marker;
800 ms mark;
XCI marker;
800 ms mark;
XCI marker;
800 ms mark;
XCI marker;
100 ms mark. */
static const uint8_t xci[] = "01111111110111111111";
static int cmp(const void *s, const void *t)
{
const char *ss;
@ -319,6 +382,7 @@ static int cmp(const void *s, const void *t)
tt = (struct dtmf_to_ascii_s *) t;
return strncmp(ss, tt->dtmf, strlen(tt->dtmf));
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
{
@ -525,14 +589,14 @@ SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
/* Need to allow for a possible character set change. */
if ((ch & 0x80))
{
if (s->baudot_tx_shift == 1)
if (!s->repeat_shifts && s->baudot_tx_shift == 1)
return ch & 0x1F;
s->baudot_tx_shift = 1;
shift = BAUDOT_FIGURE_SHIFT;
}
else
{
if (s->baudot_tx_shift == 0)
if (!s->repeat_shifts && s->baudot_tx_shift == 0)
return ch & 0x1F;
s->baudot_tx_shift = 0;
shift = BAUDOT_LETTER_SHIFT;
@ -592,13 +656,18 @@ static int v18_tdd_get_async_byte(void *user_data)
}
/*- End of function --------------------------------------------------------*/
static int v18_edt_get_async_byte(void *user_data)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
static void v18_tdd_put_async_byte(void *user_data, int byte)
{
v18_state_t *s;
uint8_t octet;
s = (v18_state_t *) user_data;
//printf("Rx byte %x\n", byte);
if (byte < 0)
{
/* Special conditions */
@ -626,7 +695,8 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
}
return;
}
if ((octet = v18_decode_baudot(s, (uint8_t) (byte & 0x1F))))
span_log(&s->logging, SPAN_LOG_FLOW, "Rx byte %x\n", byte);
if ((octet = v18_decode_baudot(s, byte)))
s->rx_msg[s->rx_msg_len++] = octet;
if (s->rx_msg_len >= 256)
{
@ -637,24 +707,44 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
}
/*- End of function --------------------------------------------------------*/
static void v18_edt_put_async_byte(void *user_data, int byte)
{
}
/*- End of function --------------------------------------------------------*/
static void v18_bell103_put_async_byte(void *user_data, int byte)
{
}
/*- End of function --------------------------------------------------------*/
static void v18_videotex_put_async_byte(void *user_data, int byte)
{
}
/*- End of function --------------------------------------------------------*/
static void v18_textphone_put_async_byte(void *user_data, int byte)
{
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
{
int len;
int lenx;
len = tone_gen(&(s->alert_tone_gen), amp, max_len);
len = tone_gen(&s->alert_tone_gen, amp, max_len);
if (s->tx_signal_on)
{
switch (s->mode)
{
case V18_MODE_DTMF:
if (len < max_len)
len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
len += dtmf_tx(&s->dtmftx, amp, max_len - len);
break;
default:
if (len < max_len)
{
if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
if ((lenx = fsk_tx(&s->fsktx, amp + len, max_len - len)) <= 0)
s->tx_signal_on = FALSE;
len += lenx;
}
@ -674,10 +764,10 @@ SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
s->in_progress -= len;
if (s->in_progress <= 0)
s->rx_msg_len = 0;
dtmf_rx(&(s->dtmfrx), amp, len);
dtmf_rx(&s->dtmfrx, amp, len);
break;
default:
fsk_rx(&(s->fskrx), amp, len);
fsk_rx(&s->fskrx, amp, len);
break;
}
return 0;
@ -744,45 +834,62 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
}
memset(s, 0, sizeof(*s));
s->calling_party = calling_party;
s->mode = mode;
s->mode = mode & 0xFF;
s->put_msg = put_msg;
s->user_data = user_data;
switch (s->mode)
{
case V18_MODE_5BIT_45:
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
s->baudot_tx_shift = 2;
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
ride over the fraction. */
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->repeat_shifts = mode & 0x100;
break;
case V18_MODE_5BIT_50:
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &(s->asynctx));
async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
s->baudot_tx_shift = 2;
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
ride over the fraction. */
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->repeat_shifts = mode & 0x100;
break;
case V18_MODE_DTMF:
dtmf_tx_init(&(s->dtmftx));
dtmf_rx_init(&(s->dtmfrx), v18_rx_dtmf, s);
dtmf_tx_init(&s->dtmftx);
dtmf_rx_init(&s->dtmfrx, v18_rx_dtmf, s);
break;
case V18_MODE_EDT:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1_110], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 2, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V21CH1_110], FSK_FRAME_MODE_7E2_FRAMES, v18_edt_put_async_byte, s);
break;
case V18_MODE_BELL103:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_BELL103CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_BELL103CH2], FSK_FRAME_MODE_7E1_FRAMES, v18_bell103_put_async_byte, s);
break;
case V18_MODE_V23VIDEOTEX:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V23CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V23CH2], FSK_FRAME_MODE_7E1_FRAMES, v18_videotex_put_async_byte, s);
break;
case V18_MODE_V21TEXTPHONE:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V21CH1], FSK_FRAME_MODE_7E1_FRAMES, v18_textphone_put_async_byte, s);
break;
case V18_MODE_V18TEXTPHONE:
fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1], async_tx_get_bit, &s->asynctx);
async_tx_init(&s->asynctx, 7, ASYNC_PARITY_EVEN, 1, FALSE, v18_edt_get_async_byte, s);
fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_V21CH1], FSK_FRAME_MODE_7E1_FRAMES, v18_textphone_put_async_byte, s);
break;
}
queue_init(&s->queue.queue, 128, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC);
@ -805,7 +912,7 @@ SPAN_DECLARE(int) v18_free(v18_state_t *s)
SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
{
switch (mode)
switch (mode & 0xFF)
{
case V18_MODE_NONE:
return "None";

View File

@ -49,30 +49,38 @@ These tests...
#include "spandsp.h"
#include "spandsp-sim.h"
#define SAMPLES_PER_CHUNK 160
#define SAMPLES_PER_CHUNK 160
#define OUTPUT_FILE_NAME "modem_connect_tones.wav"
#define OUTPUT_FILE_NAME "modem_connect_tones.wav"
#define MITEL_DIR "../test-data/mitel/"
#define BELLCORE_DIR "../test-data/bellcore/"
#define MITEL_DIR "../test-data/mitel/"
#define BELLCORE_DIR "../test-data/bellcore/"
#define FALSE 0
#define TRUE (!FALSE)
#define LEVEL_MAX -5
#define LEVEL_MIN -48
#define LEVEL_MIN_ACCEPT -43
#define LEVEL_MIN_REJECT -44
#define LEVEL_MAX -5
#define LEVEL_MIN -48
#define LEVEL_MIN_ACCEPT -43
#define LEVEL_MIN_REJECT -44
/* The 1100Hz tone is supposed to be within 38Hz, according to T.30. Allow another 8Hz for FDM, even though
you rarely see that used today. */
#define CED_FREQ_TOLERANCE (38 + 8)
#define CED_FREQ_BLACKOUT (80)
#define CED_FREQ_TOLERANCE (38 + 8)
#define CED_FREQ_BLACKOUT (80)
/* The 2100Hz tone is supposed to be within 15Hz, according to T.30. Allow another 8Hz for FDM, even though
you rarely see that used today. */
#define CNG_FREQ_TOLERANCE (15 + 8)
#define CNG_FREQ_BLACKOUT (80)
#define AM_FREQ_TOLERANCE (1)
#define CNG_FREQ_TOLERANCE (15 + 8)
#define CNG_FREQ_BLACKOUT (80)
#define AM_FREQ_TOLERANCE (1)
/* The 2225Hz tone is supposed to be within 15Hz. Allow another 8Hz for FDM, even though
you rarely see that used today. */
#define BELL_ANS_FREQ_TOLERANCE (15 + 8)
#define BELL_ANS_FREQ_BLACKOUT (80)
/* The 1300Hz tone is supposed to be within 15Hz, according to V.25. Allow another 8Hz for FDM, even though
you rarely see that used today. */
#define CALLING_TONE_FREQ_TOLERANCE (15 + 8)
#define CALLING_TONE_FREQ_BLACKOUT (80)
const char *bellcore_files[] =
{
@ -93,24 +101,30 @@ enum
PERFORM_TEST_1C = (1 << 3),
PERFORM_TEST_1D = (1 << 4),
PERFORM_TEST_1E = (1 << 5),
PERFORM_TEST_2A = (1 << 6),
PERFORM_TEST_2B = (1 << 7),
PERFORM_TEST_2C = (1 << 8),
PERFORM_TEST_2D = (1 << 9),
PERFORM_TEST_2E = (1 << 10),
PERFORM_TEST_3A = (1 << 11),
PERFORM_TEST_3B = (1 << 12),
PERFORM_TEST_3C = (1 << 13),
PERFORM_TEST_3D = (1 << 14),
PERFORM_TEST_3E = (1 << 15),
PERFORM_TEST_4 = (1 << 16),
PERFORM_TEST_5A = (1 << 17),
PERFORM_TEST_5B = (1 << 18),
PERFORM_TEST_6A = (1 << 19),
PERFORM_TEST_6B = (1 << 20),
PERFORM_TEST_7A = (1 << 21),
PERFORM_TEST_7B = (1 << 22),
PERFORM_TEST_8 = (1 << 23)
PERFORM_TEST_1F = (1 << 6),
PERFORM_TEST_1G = (1 << 7),
PERFORM_TEST_2A = (1 << 8),
PERFORM_TEST_2B = (1 << 9),
PERFORM_TEST_2C = (1 << 10),
PERFORM_TEST_2D = (1 << 11),
PERFORM_TEST_2E = (1 << 12),
PERFORM_TEST_2F = (1 << 13),
PERFORM_TEST_2G = (1 << 14),
PERFORM_TEST_3A = (1 << 15),
PERFORM_TEST_3B = (1 << 16),
PERFORM_TEST_3C = (1 << 17),
PERFORM_TEST_3D = (1 << 18),
PERFORM_TEST_3E = (1 << 19),
PERFORM_TEST_3F = (1 << 20),
PERFORM_TEST_3G = (1 << 21),
PERFORM_TEST_4 = (1 << 22),
PERFORM_TEST_5A = (1 << 23),
PERFORM_TEST_5B = (1 << 24),
PERFORM_TEST_6A = (1 << 25),
PERFORM_TEST_6B = (1 << 26),
PERFORM_TEST_7A = (1 << 27),
PERFORM_TEST_7B = (1 << 28),
PERFORM_TEST_8 = (1 << 29)
};
int preamble_count = 0;
@ -184,6 +198,22 @@ static void ans_pr_detected(void *user_data, int tone, int level, int delay)
}
/*- End of function --------------------------------------------------------*/
static void bell_ans_detected(void *user_data, int tone, int level, int delay)
{
printf("%s (%d) declared at %fs, delay %d (%ddBm0)\n", modem_connect_tone_to_str(tone), tone, (float) when/SAMPLE_RATE, delay, level);
if (tone == MODEM_CONNECT_TONES_BELL_ANS)
hits++;
}
/*- End of function --------------------------------------------------------*/
static void calling_tone_detected(void *user_data, int tone, int level, int delay)
{
printf("%s (%d) declared at %fs, delay %d (%ddBm0)\n", modem_connect_tone_to_str(tone), tone, (float) when/SAMPLE_RATE, delay, level);
if (tone == MODEM_CONNECT_TONES_CALLING_TONE)
hits++;
}
/*- End of function --------------------------------------------------------*/
int main(int argc, char *argv[])
{
int i;
@ -198,6 +228,8 @@ int main(int argc, char *argv[])
modem_connect_tones_rx_state_t ced_rx;
modem_connect_tones_rx_state_t ans_pr_rx;
modem_connect_tones_tx_state_t modem_tone_tx;
modem_connect_tones_rx_state_t calling_tone_rx;
modem_connect_tones_rx_state_t bell_ans_rx;
awgn_state_t chan_noise_source;
SNDFILE *inhandle;
SNDFILE *outhandle;
@ -207,9 +239,6 @@ int main(int argc, char *argv[])
int hit;
int false_hit;
int false_miss;
power_meter_t power_state;
int power;
int max_power;
int level2;
int max_level2;
int tone_type;
@ -247,6 +276,10 @@ int main(int argc, char *argv[])
test_list |= PERFORM_TEST_1D;
else if (strcasecmp(argv[i], "1e") == 0)
test_list |= PERFORM_TEST_1E;
else if (strcasecmp(argv[i], "1f") == 0)
test_list |= PERFORM_TEST_1F;
else if (strcasecmp(argv[i], "1g") == 0)
test_list |= PERFORM_TEST_1G;
else if (strcasecmp(argv[i], "2a") == 0)
test_list |= PERFORM_TEST_2A;
else if (strcasecmp(argv[i], "2b") == 0)
@ -257,6 +290,10 @@ int main(int argc, char *argv[])
test_list |= PERFORM_TEST_2D;
else if (strcasecmp(argv[i], "2e") == 0)
test_list |= PERFORM_TEST_2E;
else if (strcasecmp(argv[i], "2f") == 0)
test_list |= PERFORM_TEST_2F;
else if (strcasecmp(argv[i], "2g") == 0)
test_list |= PERFORM_TEST_2G;
else if (strcasecmp(argv[i], "3a") == 0)
test_list |= PERFORM_TEST_3A;
else if (strcasecmp(argv[i], "3b") == 0)
@ -267,6 +304,10 @@ int main(int argc, char *argv[])
test_list |= PERFORM_TEST_3D;
else if (strcasecmp(argv[i], "3e") == 0)
test_list |= PERFORM_TEST_3E;
else if (strcasecmp(argv[i], "3f") == 0)
test_list |= PERFORM_TEST_3F;
else if (strcasecmp(argv[i], "3g") == 0)
test_list |= PERFORM_TEST_3G;
else if (strcasecmp(argv[i], "4") == 0)
test_list |= PERFORM_TEST_4;
else if (strcasecmp(argv[i], "5a") == 0)
@ -316,7 +357,7 @@ int main(int argc, char *argv[])
/*endfor*/
}
/*endif*/
if ((test_list & PERFORM_TEST_1B))
{
printf("Test 1b: CED/ANS generation to a file\n");
@ -375,7 +416,7 @@ int main(int argc, char *argv[])
/*endfor*/
}
/*endif*/
if ((test_list & PERFORM_TEST_1E))
{
printf("Test 1e: ANSam/ (Modulated EC-disable) generation to a file\n");
@ -396,13 +437,51 @@ int main(int argc, char *argv[])
}
/*endif*/
if ((test_list & PERFORM_TEST_1F))
{
printf("Test 1f: Bell answer tone generation to a file\n");
modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_BELL_ANS);
for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
{
samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
outframes = sf_writef_short(outhandle, amp, samples);
if (outframes != samples)
{
fprintf(stderr, " Error writing audio file\n");
exit(2);
}
/*endif*/
}
/*endfor*/
}
/*endif*/
if ((test_list & PERFORM_TEST_1G))
{
printf("Test 1g: Calling tone generation to a file\n");
modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_CALLING_TONE);
for (i = 0; i < 20*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
{
samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
outframes = sf_writef_short(outhandle, amp, samples);
if (outframes != samples)
{
fprintf(stderr, " Error writing audio file\n");
exit(2);
}
/*endif*/
}
/*endfor*/
}
/*endif*/
if (sf_close_telephony(outhandle))
{
printf(" Cannot close audio file '%s'\n", OUTPUT_FILE_NAME);
exit(2);
}
/*endif*/
if ((test_list & PERFORM_TEST_2A))
{
printf("Test 2a: CNG detection with frequency\n");
@ -410,16 +489,13 @@ int main(int argc, char *argv[])
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 600; pitch <= 1600; pitch++)
for (pitch = 1100 - 500; pitch <= 1100 + 500; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
/* Fudge things for the test */
modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
modem_connect_tones_rx_init(&cng_rx, tone_type, NULL, NULL);
power_meter_init(&power_state, 5);
power = 0;
max_power = 0;
level2 = 0;
max_level2 = 0;
for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
@ -428,10 +504,6 @@ int main(int argc, char *argv[])
for (j = 0; j < samples; j++)
{
amp[j] += awgn(&chan_noise_source);
power = power_meter_update(&power_state, amp[j]);
if (power > max_power)
max_power = power;
/*endif*/
level2 += ((abs(amp[j]) - level2) >> 5);
if (level2 > max_level2)
max_level2 = level2;
@ -455,7 +527,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, cng_rx.channel_level, cng_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, cng_rx.channel_level, cng_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -475,7 +547,7 @@ int main(int argc, char *argv[])
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 1600; pitch < 2600; pitch++)
for (pitch = 2100 - 500; pitch < 2100 + 500; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, MODEM_CONNECT_TONES_ANS);
@ -506,7 +578,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ced_rx.channel_level, ced_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ced_rx.channel_level, ced_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
if (false_hit || false_miss)
@ -526,7 +598,7 @@ int main(int argc, char *argv[])
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 2000; pitch <= 2200; pitch++)
for (pitch = 2100 - 100; pitch <= 2100 + 100; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
@ -557,7 +629,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -578,7 +650,7 @@ int main(int argc, char *argv[])
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 2000; pitch <= 2200; pitch++)
for (pitch = 2100 - 100; pitch <= 2100 + 100; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
@ -609,7 +681,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -630,7 +702,7 @@ int main(int argc, char *argv[])
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 2000; pitch <= 2200; pitch++)
for (pitch = 2100 - 100; pitch <= 2100 + 100; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
@ -661,7 +733,125 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
if (false_hit || false_miss)
{
printf("Test failed.\n");
exit(2);
}
/*endif*/
printf("Test passed.\n");
}
/*endif*/
if ((test_list & PERFORM_TEST_2F))
{
printf("Test 2f: Bell answer tone detection with frequency\n");
tone_type = MODEM_CONNECT_TONES_BELL_ANS;
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 2225 - 500; pitch <= 2225 + 500; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
/* Fudge things for the test */
modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
modem_connect_tones_rx_init(&bell_ans_rx, tone_type, NULL, NULL);
level2 = 0;
max_level2 = 0;
for (i = 0; i < 8000; i += SAMPLES_PER_CHUNK)
{
samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
for (j = 0; j < samples; j++)
{
amp[j] += awgn(&chan_noise_source);
level2 += ((abs(amp[j]) - level2) >> 5);
if (level2 > max_level2)
max_level2 = level2;
}
/*endfor*/
modem_connect_tones_rx(&bell_ans_rx, amp, samples);
}
/*endfor*/
hit = modem_connect_tones_rx_get(&bell_ans_rx);
if (pitch < (2225 - BELL_ANS_FREQ_BLACKOUT) || pitch > (2225 + BELL_ANS_FREQ_BLACKOUT))
{
if (hit != MODEM_CONNECT_TONES_NONE)
false_hit = TRUE;
/*endif*/
}
else if (pitch > (2225 - BELL_ANS_FREQ_TOLERANCE) && pitch < (2225 + BELL_ANS_FREQ_TOLERANCE))
{
if (hit != tone_type)
false_miss = TRUE;
/*endif*/
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, bell_ans_rx.channel_level, bell_ans_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
if (false_hit || false_miss)
{
printf("Test failed.\n");
exit(2);
}
/*endif*/
printf("Test passed.\n");
}
/*endif*/
if ((test_list & PERFORM_TEST_2G))
{
printf("Test 2g: Calling tone detection with frequency\n");
tone_type = MODEM_CONNECT_TONES_CALLING_TONE;
awgn_init_dbm0(&chan_noise_source, 7162534, -50.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 1300 - 500; pitch <= 1300 + 500; pitch++)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
/* Fudge things for the test */
modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
modem_connect_tones_rx_init(&calling_tone_rx, tone_type, NULL, NULL);
level2 = 0;
max_level2 = 0;
for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
{
samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
for (j = 0; j < samples; j++)
{
amp[j] += awgn(&chan_noise_source);
level2 += ((abs(amp[j]) - level2) >> 5);
if (level2 > max_level2)
max_level2 = level2;
}
/*endfor*/
modem_connect_tones_rx(&calling_tone_rx, amp, samples);
}
/*endfor*/
hit = modem_connect_tones_rx_get(&calling_tone_rx);
if (pitch < (1300 - CALLING_TONE_FREQ_BLACKOUT) || pitch > (1300 + CALLING_TONE_FREQ_BLACKOUT))
{
if (hit != MODEM_CONNECT_TONES_NONE)
false_hit = TRUE;
/*endif*/
}
else if (pitch > (1300 - CALLING_TONE_FREQ_TOLERANCE) && pitch < (1300 + CALLING_TONE_FREQ_TOLERANCE))
{
if (hit != tone_type)
false_miss = TRUE;
/*endif*/
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, calling_tone_rx.channel_level, calling_tone_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -716,7 +906,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, cng_rx.channel_level, cng_rx.notch_level, hit);
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, cng_rx.channel_level, cng_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -773,7 +963,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ced_rx.channel_level, ced_rx.notch_level, hit);
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, ced_rx.channel_level, ced_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -831,8 +1021,8 @@ int main(int argc, char *argv[])
/*endif*/
}
/*endif*/
//if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -889,7 +1079,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -947,7 +1137,121 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %d\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
}
/*endfor*/
if (false_hit || false_miss)
{
printf("Test failed.\n");
exit(2);
}
/*endif*/
printf("Test passed.\n");
}
/*endif*/
if ((test_list & PERFORM_TEST_3F))
{
printf("Test 3f: Bell answer tone detection with level\n");
tone_type = MODEM_CONNECT_TONES_BELL_ANS;
awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 2225 - BELL_ANS_FREQ_TOLERANCE; pitch <= 2225 + BELL_ANS_FREQ_TOLERANCE; pitch += 2*BELL_ANS_FREQ_TOLERANCE)
{
for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
/* Fudge things for the test */
modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
modem_tone_tx.level = dds_scaling_dbm0(level);
modem_connect_tones_rx_init(&calling_tone_rx, tone_type, NULL, NULL);
for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
{
samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
for (j = 0; j < samples; j++)
amp[j] += awgn(&chan_noise_source);
/*endfor*/
modem_connect_tones_rx(&calling_tone_rx, amp, samples);
}
/*endfor*/
hit = modem_connect_tones_rx_get(&calling_tone_rx);
if (level < LEVEL_MIN_REJECT)
{
if (hit != MODEM_CONNECT_TONES_NONE)
false_hit = TRUE;
/*endif*/
}
else if (level > LEVEL_MIN_ACCEPT)
{
if (hit != tone_type)
false_miss = TRUE;
/*endif*/
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, calling_tone_rx.channel_level, calling_tone_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
}
/*endfor*/
if (false_hit || false_miss)
{
printf("Test failed.\n");
exit(2);
}
/*endif*/
printf("Test passed.\n");
}
/*endif*/
if ((test_list & PERFORM_TEST_3G))
{
printf("Test 3g: Calling tone detection with level\n");
tone_type = MODEM_CONNECT_TONES_CALLING_TONE;
awgn_init_dbm0(&chan_noise_source, 7162534, -60.0f);
false_hit = FALSE;
false_miss = FALSE;
for (pitch = 1300 - CALLING_TONE_FREQ_TOLERANCE; pitch <= 1300 + CALLING_TONE_FREQ_TOLERANCE; pitch += 2*CALLING_TONE_FREQ_TOLERANCE)
{
for (level = LEVEL_MAX; level >= LEVEL_MIN; level--)
{
/* Use the transmitter to test the receiver */
modem_connect_tones_tx_init(&modem_tone_tx, tone_type);
/* Fudge things for the test */
modem_tone_tx.tone_phase_rate = dds_phase_rate(pitch);
modem_tone_tx.level = dds_scaling_dbm0(level);
modem_connect_tones_rx_init(&calling_tone_rx, tone_type, NULL, NULL);
for (i = 0; i < 10*SAMPLE_RATE; i += SAMPLES_PER_CHUNK)
{
samples = modem_connect_tones_tx(&modem_tone_tx, amp, SAMPLES_PER_CHUNK);
for (j = 0; j < samples; j++)
amp[j] += awgn(&chan_noise_source);
/*endfor*/
modem_connect_tones_rx(&calling_tone_rx, amp, samples);
}
/*endfor*/
hit = modem_connect_tones_rx_get(&calling_tone_rx);
if (level < LEVEL_MIN_REJECT)
{
if (hit != MODEM_CONNECT_TONES_NONE)
false_hit = TRUE;
/*endif*/
}
else if (level > LEVEL_MIN_ACCEPT)
{
if (hit != tone_type)
false_miss = TRUE;
/*endif*/
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %4ddB %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, level, calling_tone_rx.channel_level, calling_tone_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -1146,7 +1450,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -1198,7 +1502,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -1251,7 +1555,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -1304,7 +1608,7 @@ int main(int argc, char *argv[])
}
/*endif*/
if (hit != MODEM_CONNECT_TONES_NONE)
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %d\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, hit);
printf("Detected at %5dHz %12" PRId32 " %12" PRId32 " %s (%d)\n", pitch, ans_pr_rx.channel_level, ans_pr_rx.notch_level, modem_connect_tone_to_str(hit), hit);
/*endif*/
}
/*endfor*/
@ -1331,6 +1635,8 @@ int main(int argc, char *argv[])
modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, NULL, NULL);
modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
modem_connect_tones_rx_init(&ans_pr_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
modem_connect_tones_rx_init(&bell_ans_rx, MODEM_CONNECT_TONES_BELL_ANS, NULL, NULL);
modem_connect_tones_rx_init(&calling_tone_rx, MODEM_CONNECT_TONES_CALLING_TONE, NULL, NULL);
for (j = 0; bellcore_files[j][0]; j++)
{
if ((inhandle = sf_open_telephony_read(bellcore_files[j], 1)) == NULL)
@ -1348,6 +1654,8 @@ int main(int argc, char *argv[])
modem_connect_tones_rx(&cng_rx, amp, frames);
modem_connect_tones_rx(&ced_rx, amp, frames);
modem_connect_tones_rx(&ans_pr_rx, amp, frames);
modem_connect_tones_rx(&bell_ans_rx, amp, frames);
modem_connect_tones_rx(&calling_tone_rx, amp, frames);
if (modem_connect_tones_rx_get(&cng_rx) != MODEM_CONNECT_TONES_NONE)
{
/* This is not a true measure of hits, as there might be more
@ -1372,6 +1680,20 @@ int main(int argc, char *argv[])
modem_connect_tones_rx_init(&ans_pr_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
}
/*endif*/
if (modem_connect_tones_rx_get(&bell_ans_rx) != MODEM_CONNECT_TONES_NONE)
{
printf("Hit calling tone at %ds\n", when);
hits++;
modem_connect_tones_rx_init(&bell_ans_rx, MODEM_CONNECT_TONES_BELL_ANS, NULL, NULL);
}
/*endif*/
if (modem_connect_tones_rx_get(&calling_tone_rx) != MODEM_CONNECT_TONES_NONE)
{
printf("Hit calling tone at %ds\n", when);
hits++;
modem_connect_tones_rx_init(&calling_tone_rx, MODEM_CONNECT_TONES_CALLING_TONE, NULL, NULL);
}
/*endif*/
}
/*endwhile*/
if (sf_close_telephony(inhandle))
@ -1399,6 +1721,8 @@ int main(int argc, char *argv[])
modem_connect_tones_rx_init(&cng_rx, MODEM_CONNECT_TONES_FAX_CNG, cng_detected, NULL);
modem_connect_tones_rx_init(&ced_rx, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, ced_detected, NULL);
modem_connect_tones_rx_init(&ans_pr_rx, MODEM_CONNECT_TONES_ANS_PR, ans_pr_detected, NULL);
modem_connect_tones_rx_init(&bell_ans_rx, MODEM_CONNECT_TONES_BELL_ANS, bell_ans_detected, NULL);
modem_connect_tones_rx_init(&calling_tone_rx, MODEM_CONNECT_TONES_CALLING_TONE, calling_tone_detected, NULL);
hits = 0;
if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
{
@ -1415,6 +1739,8 @@ int main(int argc, char *argv[])
modem_connect_tones_rx(&cng_rx, amp, frames);
modem_connect_tones_rx(&ced_rx, amp, frames);
modem_connect_tones_rx(&ans_pr_rx, amp, frames);
modem_connect_tones_rx(&bell_ans_rx, amp, frames);
modem_connect_tones_rx(&calling_tone_rx, amp, frames);
}
/*endwhile*/
if (sf_close_telephony(inhandle))

View File

@ -479,7 +479,7 @@ int main(int argc, char *argv[])
int attack_packets;
int opt;
attack_packets = 10000000;
attack_packets = 100000;
while ((opt = getopt(argc, argv, "a:")) != -1)
{
switch (opt)

View File

@ -62,7 +62,7 @@ t4_state_t receive_state;
#define FILL_670 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_70
#define FILL_980 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_100 FILL_80
static const char t4_test_patterns[][1728 + 1] =
static const char t4_t6_test_patterns[][1728 + 1] =
{
"XXXXXX " FILL_980 " XXX XXX X " FILL_670 " XXXX",
"XXXXXX " FILL_980 " XXX X " FILL_670 " XXXX",
@ -145,7 +145,7 @@ static int row_read_handler(void *user_data, uint8_t buf[], size_t len)
/* Send the test pattern. */
if (rows_read >= 16)
return 0;
s = t4_test_patterns[rows_read++];
s = t4_t6_test_patterns[rows_read++];
memset(buf, 0, len);
for (i = 0; i < len; i++)
{
@ -171,7 +171,7 @@ static int row_write_handler(void *user_data, const uint8_t buf[], size_t len)
/* Verify that what is received matches the test pattern. */
if (len == 0)
return 0;
s = t4_test_patterns[rows_written++];
s = t4_t6_test_patterns[rows_written++];
memset(ref, 0, len);
for (i = 0; i < len; i++)
{

View File

@ -972,7 +972,6 @@ static int next_step(faxtester_state_t *s)
printf("Test failed\n");
exit(2);
}
t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
t4_tx_set_header_info(&t4_tx_state, NULL);
compression_type = T4_COMPRESSION_ITU_T4_1D;
if (compression)
@ -983,6 +982,7 @@ static int next_step(faxtester_state_t *s)
compression_type = T4_COMPRESSION_ITU_T6;
}
t4_tx_set_tx_encoding(&t4_tx_state, compression_type);
t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
if (t4_tx_start_page(&t4_tx_state))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
@ -996,7 +996,7 @@ static int next_step(faxtester_state_t *s)
corrupt_image(s, image, len, (const char *) bad_rows);
}
t4_tx_release(&t4_tx_state);
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM image is %d bytes\n", len);
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM image is %d bytes (min row bits %d)\n", len, min_row_bits);
faxtester_set_non_ecm_image_buffer(s, image, len);
}
else if (strcasecmp((const char *) type, "PP") == 0)
@ -1012,7 +1012,6 @@ static int next_step(faxtester_state_t *s)
printf("Test failed\n");
exit(2);
}
t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
t4_tx_set_header_info(&t4_tx_state, NULL);
compression_type = T4_COMPRESSION_ITU_T4_1D;
if (compression)
@ -1023,6 +1022,7 @@ static int next_step(faxtester_state_t *s)
compression_type = T4_COMPRESSION_ITU_T6;
}
t4_tx_set_tx_encoding(&t4_tx_state, compression_type);
t4_tx_set_min_bits_per_row(&t4_tx_state, min_row_bits);
if (t4_tx_start_page(&t4_tx_state))
{
span_log(&s->logging, SPAN_LOG_FLOW, "Failed to start T.4 send\n");
@ -1038,7 +1038,7 @@ static int next_step(faxtester_state_t *s)
}
/*endif*/
t4_tx_release(&t4_tx_state);
span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes\n", len);
span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes (min row bits %d)\n", len, min_row_bits);
faxtester_set_ecm_image_buffer(s, image, len, ecm_block, ecm_frame_size, i);
}
else

View File

@ -227,11 +227,13 @@ static void qam_report(void *user_data, const complexf_t *constel, const complex
#endif
#if defined(ENABLE_GUI)
if (use_gui)
{
#if defined(SPANDSP_USE_FIXED_POINTx)
qam_monitor_update_int_equalizer(qam_monitor, coeffs, len);
#else
qam_monitor_update_equalizer(qam_monitor, coeffs, len);
#endif
}
#endif
update_interval = 100;
}

File diff suppressed because it is too large Load Diff

View File

@ -228,11 +228,13 @@ static void qam_report(void *user_data, const complexf_t *constel, const complex
#endif
#if defined(ENABLE_GUI)
if (use_gui)
{
#if defined(SPANDSP_USE_FIXED_POINTx)
qam_monitor_update_int_equalizer(s->qam_monitor, coeffs, len);
#else
qam_monitor_update_equalizer(s->qam_monitor, coeffs, len);
#endif
}
#endif
}
}

View File

@ -260,11 +260,13 @@ static void qam_report(void *user_data, const complexf_t *constel, const complex
#endif
#if defined(ENABLE_GUI)
if (use_gui)
{
#if defined(SPANDSP_USE_FIXED_POINTx)
qam_monitor_update_int_equalizer(qam_monitor, coeffs, len);
#else
qam_monitor_update_equalizer(qam_monitor, coeffs, len);
#endif
}
#endif
}
}

View File

@ -244,11 +244,13 @@ static void qam_report(void *user_data, const complexf_t *constel, const complex
#endif
#if defined(ENABLE_GUI)
if (use_gui)
{
#if defined(SPANDSP_USE_FIXED_POINT)
qam_monitor_update_int_equalizer(qam_monitor, coeffs, len);
#else
qam_monitor_update_equalizer(qam_monitor, coeffs, len);
#endif
}
#endif
update_interval = 100;
}

View File

@ -206,6 +206,8 @@ static int v8_calls_v8_tests(SNDFILE *outhandle)
negotiations_ok = 0;
v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
v8_call_parms.send_ci = TRUE;
v8_call_parms.v92 = -1;
v8_call_parms.call_function = V8_CALL_V_SERIES;
v8_call_parms.modulations = caller_available_modulations;
v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42;
@ -219,6 +221,8 @@ static int v8_calls_v8_tests(SNDFILE *outhandle)
handler,
(void *) "caller");
v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_answer_parms.send_ci = TRUE;
v8_answer_parms.v92 = -1;
v8_answer_parms.call_function = V8_CALL_V_SERIES;
v8_answer_parms.modulations = answerer_available_modulations;
v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42;
@ -329,6 +333,8 @@ static int non_v8_calls_v8_tests(SNDFILE *outhandle)
non_v8_caller_rx = modem_connect_tones_rx_init(NULL, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_answer_parms.send_ci = TRUE;
v8_answer_parms.v92 = -1;
v8_answer_parms.call_function = V8_CALL_V_SERIES;
v8_answer_parms.modulations = answerer_available_modulations;
v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42;
@ -439,6 +445,8 @@ static int v8_calls_non_v8_tests(SNDFILE *outhandle)
negotiations_ok = 0;
v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
v8_call_parms.send_ci = TRUE;
v8_call_parms.v92 = -1;
v8_call_parms.call_function = V8_CALL_V_SERIES;
v8_call_parms.modulations = caller_available_modulations;
v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42;
@ -578,6 +586,8 @@ int main(int argc, char *argv[])
printf("Decode file '%s'\n", decode_test_file);
v8_call_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
v8_call_parms.send_ci = TRUE;
v8_call_parms.v92 = -1;
v8_call_parms.call_function = V8_CALL_V_SERIES;
v8_call_parms.modulations = caller_available_modulations;
v8_call_parms.protocol = V8_PROTOCOL_LAPM_V42;
@ -595,6 +605,8 @@ int main(int argc, char *argv[])
span_log_set_tag(logging, "caller");
v8_answer_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_answer_parms.send_ci = TRUE;
v8_answer_parms.v92 = -1;
v8_answer_parms.call_function = V8_CALL_V_SERIES;
v8_answer_parms.modulations = answerer_available_modulations;
v8_answer_parms.protocol = V8_PROTOCOL_LAPM_V42;