Various minor tweaks to spandsp and the ARM specific code now does fast top bit detection.

This commit is contained in:
Steve Underwood 2015-04-09 03:30:49 +08:00
parent d55c4a053b
commit 0d6c3a1d73
17 changed files with 234 additions and 92 deletions

View File

@ -755,7 +755,7 @@ SPAN_DECLARE(ademco_contactid_receiver_state_t *) ademco_contactid_receiver_init
{
if (s == NULL)
{
if ((s = (ademco_contactid_receiver_state_t *) span_alloc(sizeof (*s))) == NULL)
if ((s = (ademco_contactid_receiver_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
@ -1090,7 +1090,7 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade
{
if (s == NULL)
{
if ((s = (ademco_contactid_sender_state_t *) span_alloc(sizeof (*s))) == NULL)
if ((s = (ademco_contactid_sender_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));

View File

@ -417,7 +417,7 @@ SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s,
if (s == NULL)
{
if ((s = (dtmf_rx_state_t *) span_alloc(sizeof (*s))) == NULL)
if ((s = (dtmf_rx_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
@ -578,7 +578,7 @@ SPAN_DECLARE(dtmf_tx_state_t *) dtmf_tx_init(dtmf_tx_state_t *s,
{
if (s == NULL)
{
if ((s = (dtmf_tx_state_t *) span_alloc(sizeof (*s))) == NULL)
if ((s = (dtmf_tx_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));

View File

@ -116,12 +116,12 @@ SPAN_DECLARE(gsm0610_state_t *) gsm0610_init(gsm0610_state_t *s, int packing)
{
if (s == NULL)
{
if ((s = (gsm0610_state_t *) span_alloc(sizeof (*s))) == NULL)
if ((s = (gsm0610_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
/*endif*/
}
/*endif*/
memset((char *) s, '\0', sizeof (gsm0610_state_t));
memset((char *) s, '\0', sizeof(gsm0610_state_t));
s->nrp = 40;
s->packing = packing;
return s;

View File

@ -33,7 +33,7 @@ typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
#if !defined(INFINITY)
#if !defined(INFINITY) && _MSC_VER < 1800
#define INFINITY 0x7FFFFFFF
#endif

View File

@ -173,7 +173,6 @@ SPAN_DECLARE(void) at_set_class1_handler(at_state_t *s, at_class1_handler_t hand
\return A pointer to the logging context */
SPAN_DECLARE(logging_state_t *) at_get_logging_state(at_state_t *s);
SPAN_DECLARE(void) at_set_modem_control_handler(at_state_t *s,
at_modem_control_handler_t modem_control_handler,
void *modem_control_user_data);

View File

@ -53,13 +53,13 @@ static __inline__ int top_bit(uint32_t bits)
: [res] "=&r" (res)
: [bits] "rm" (bits));
return res;
#elif defined(__GNUC__x) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
#elif defined(__GNUC__) && (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7A__))
int res;
__asm__("clz %[res], %[bits]"
: [res] "=r" (res)
: [bits] "r" (bits));
return res;
return 31 - res;
#elif defined(__ppc__) || defined(__powerpc__)
int res;

View File

@ -38,8 +38,6 @@
#include "mmx.h"
#endif
#include "alloc.h"
/*!
16 bit integer FIR descriptor. This defines the working state for a single
instance of an FIR filter using 16 bit integer coefficients.

View File

@ -111,7 +111,6 @@ That's it!
*/
typedef struct plc_state_s plc_state_t;
#if defined(__cplusplus)
extern "C"
{

View File

@ -34,15 +34,27 @@
/*! Audio time scaling descriptor. */
struct time_scale_state_s
{
/*! \brief The sample rate of both the incoming and outgoing signal */
int sample_rate;
/*! \brief The minimum pitch we will search for, in samples per cycle */
int min_pitch;
/*! \brief The maximum pitch we will search for, in samples per cycle */
int max_pitch;
int buf_len;
/*! \brief The playout speed, as the fraction output time/input time.
(i.e. >1.0 == slow down, 1.0 == no speed change, <1.0 == speed up) */
float playout_rate;
/*! \brief */
double rcomp;
/*! \brief The fractional sample adjustment, to allow for non-integer values of lcp. */
double rate_nudge;
int fill;
/*! \brief */
int lcp;
/*! \brief The active length of buf at the current sample rate. */
int buf_len;
/*! \brief The number of samples in buf */
int fill;
/*! \brief Buffer for residual samples kept over from one call of time_scale() to
the next. */
int16_t buf[TIME_SCALE_BUF_LEN];
};

View File

@ -28,11 +28,33 @@
#if !defined(_SPANDSP_T30_API_H_)
#define _SPANDSP_T30_API_H_
enum
{
T33_NONE = 0,
T33_SST = 1,
T33_EXT = 2
};
#if defined(__cplusplus)
extern "C"
{
#endif
/*! Get the specified field from a T.33 formatted string.
\brief Get the specified field from a T.33 formatted string.
\param field The extracted field.
\param t33 The T.33 formatted string.
\param field_no The field number to extract. The first field is 0.
\return The extracted field type. -1 indicates a over length or badly formatted field. */
SPAN_DECLARE(int) t33_sub_address_extract_field(uint8_t field[21], const uint8_t t33[], int field_no);
/*! Append the specified field to a T.33 formatted string.
\brief Append the specified field to a T.33 formatted string.
\param t33 The T.33 formatted string.
\param field The field to be adppended.
\param type The type of the field to be appended. */
SPAN_DECLARE(void) t33_sub_address_add_field(uint8_t t33[], const uint8_t field[], int type);
/*! Set the transmitted NSF frame to be associated with a T.30 context.
\brief Set the transmitted NSF frame to be associated with a T.30 context.
\param s The T.30 context.

View File

@ -62,25 +62,6 @@ extern "C"
{
#endif
/*! Initialise a time scale context. This must be called before the first
use of the context, to initialise its contents.
\brief Initialise a time scale context.
\param s The time scale context.
\param sample_rate The sample rate of the signal.
\param playout_rate The ratio between the output speed and the input speed.
\return A pointer to the context, or NULL if there was a problem. */
SPAN_DECLARE(time_scale_state_t *) time_scale_init(time_scale_state_t *s, int sample_rate, float playout_rate);
/*! \brief Release a time scale context.
\param s The time scale context.
\return 0 for OK, else -1. */
SPAN_DECLARE(int) time_scale_release(time_scale_state_t *s);
/*! \brief Free a time scale context.
\param s The time scale context.
\return 0 for OK, else -1. */
SPAN_DECLARE(int) time_scale_free(time_scale_state_t *s);
/*! Change the time scale rate.
\brief Change the time scale rate.
\param s The time scale context.
@ -108,6 +89,27 @@ SPAN_DECLARE(int) time_scale_max_output_len(time_scale_state_t *s, int input_len
*/
SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[], int len);
SPAN_DECLARE(int) time_scale_flush(time_scale_state_t *s, int16_t out[]);
/*! Initialise a time scale context. This must be called before the first
use of the context, to initialise its contents.
\brief Initialise a time scale context.
\param s The time scale context.
\param sample_rate The sample rate of the signal.
\param playout_rate The ratio between the output speed and the input speed.
\return A pointer to the context, or NULL if there was a problem. */
SPAN_DECLARE(time_scale_state_t *) time_scale_init(time_scale_state_t *s, int sample_rate, float playout_rate);
/*! \brief Release a time scale context.
\param s The time scale context.
\return 0 for OK, else -1. */
SPAN_DECLARE(int) time_scale_release(time_scale_state_t *s);
/*! \brief Free a time scale context.
\param s The time scale context.
\return 0 for OK, else -1. */
SPAN_DECLARE(int) time_scale_free(time_scale_state_t *s);
#if defined(__cplusplus)
}
#endif

View File

@ -436,6 +436,7 @@ static void decode_20digit_msg(t30_state_t *s, char *msg, const uint8_t *pkt, in
static void decode_url_msg(t30_state_t *s, char *msg, const uint8_t *pkt, int len);
static int decode_nsf_nss_nsc(t30_state_t *s, uint8_t *msg[], const uint8_t *pkt, int len);
static void set_min_scan_time(t30_state_t *s);
static int send_cfr_sequence(t30_state_t *s, int start);
static int build_dcs(t30_state_t *s);
static void timer_t2_start(t30_state_t *s);
static void timer_t2a_start(t30_state_t *s);
@ -1309,7 +1310,6 @@ int t30_build_dis_or_dtc(t30_state_t *s)
/* No Document transfer mode (DTM) */
/* No Electronic data interchange (EDI) */
/* No Basic transfer mode (BTM) */
/* No mixed mode (polling) */
/* No character mode */
/* No mixed mode (T.4/Annex E) */
@ -5492,9 +5492,9 @@ static void timer_t2_expired(t30_state_t *s)
/* We didn't receive a response to our T30_MCF after T30_EOM, so we must be OK
to proceed to phase B, and pretty much act like its the beginning of a call. */
span_log(&s->logging, SPAN_LOG_FLOW, "Returning to phase B after %s\n", t30_frametype(s->next_rx_step));
s->dis_received = false;
set_phase(s, T30_PHASE_B_TX);
timer_t2_start(s);
s->dis_received = false;
send_dis_or_dtc_sequence(s, true);
return;
}
@ -5548,6 +5548,13 @@ static void timer_t2a_expired(t30_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "T2A expired in phase %s, state %s. An HDLC frame lasted too long.\n", phase_names[s->phase], state_names[s->state]);
t30_set_status(s, T30_ERR_HDLC_CARRIER);
/* T.30 says we should retry at this point, but we can't. We would need to
wait for the far end to go quiet before sending. Experience says you only
get here when the far end is buggy, and it will not go quiet unless you
hang up. If we were to retry, how long should we wait for the line to go
quiet? T.30 doesn't specify things like that. The only effective strategy,
when trying to deal with problems found in logs from real world systems,
is to abandon the call. */
terminate_call(s);
}
/*- End of function --------------------------------------------------------*/
@ -5571,7 +5578,8 @@ static void timer_t4_expired(t30_state_t *s)
{
/* There was no response (or only a corrupt response) to a command,
within the T4 timeout period. */
span_log(&s->logging, SPAN_LOG_FLOW, "T4 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]);
if (s->timer_t2_t4_is == TIMER_IS_T4)
span_log(&s->logging, SPAN_LOG_FLOW, "T4 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]);
/* Of course, things might just be a little late, especially if there are T.38
links in the path. There is no point in simply timing out, and resending,
if we are currently receiving something from the far end - its a half-duplex
@ -6143,9 +6151,9 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
{
case T30_STATE_ANSWERING:
span_log(&s->logging, SPAN_LOG_FLOW, "Starting answer mode\n");
s->dis_received = false;
set_phase(s, T30_PHASE_B_TX);
timer_t2_start(s);
s->dis_received = false;
send_dis_or_dtc_sequence(s, true);
break;
case T30_STATE_R:

View File

@ -95,6 +95,65 @@
#include "t30_local.h"
SPAN_DECLARE(int) t33_sub_address_extract_field(uint8_t num[21], const uint8_t t33[], int field_no)
{
int i;
int j;
int k;
int ch;
int type;
num[0] = '\0';
k = 0;
for (i = 0; t33[i]; )
{
if (k++ == field_no)
{
ch = t33[i++];
j = 0;
if (ch != '#')
{
num[j++] = ch;
type = T33_EXT;
}
else
{
type = T33_SST;
}
while (t33[i])
{
ch = t33[i++];
if (ch == '#')
break;
num[j++] = ch;
if (j >= 20)
return -1;
}
num[j] = '\0';
return type;
}
/* Skip this field */
i++;
while (t33[i])
{
if (t33[i++] == '#')
break;
}
}
return T33_NONE;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t33_sub_address_add_field(uint8_t t33[], const uint8_t field[], int type)
{
if (t33[0] != '\0')
strcat((char *) t33, "#");
if (type == T33_SST)
strcat((char *) t33, "#");
strcat((char *) t33, (const char *) field);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t30_set_tx_ident(t30_state_t *s, const char *id)
{
if (id == NULL)

View File

@ -2994,7 +2994,7 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
alloced = false;
if (s == NULL)
{
if ((s = (t31_state_t *) span_alloc(sizeof (*s))) == NULL)
if ((s = (t31_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
/*endif*/
alloced = true;

View File

@ -662,8 +662,8 @@ static void monitor_control_messages(t38_gateway_state_t *s,
/*endif*/
}
/*endfor*/
/* If we are processing a message from the modem side, the contents determine the fast receive modem.
we are to use. If it comes from the T.38 side the contents do not. */
/* If we are processing a message from the modem side, the contents determine the fast
receive modem we are to use. If it comes from the T.38 side the contents do not. */
s->core.fast_bit_rate = modem_codes[i].bit_rate;
if (from_modem)
s->core.fast_rx_modem = modem_codes[i].modem_type;
@ -700,8 +700,9 @@ static void monitor_control_messages(t38_gateway_state_t *s,
/*endif*/
}
/*endfor*/
/* If we are processing a message from the modem side, the contents determine the fast receive modem.
we are to use. If it comes from the T.38 side the contents do not. */
/* If we are processing a DCS message from the modem side, the contents determine the fast
receive modem we are to use. If it comes from the T.38 side the contents do not. For a
DTC message this is reversed. */
s->core.fast_bit_rate = modem_codes[i].bit_rate;
if ((buf[2] == T30_DTC && !from_modem) || (buf[2] != T30_DTC && from_modem))
s->core.fast_rx_modem = modem_codes[i].modem_type;

View File

@ -78,12 +78,15 @@ static __inline__ int amdf_pitch(int min_pitch, int max_pitch, int16_t amp[], in
acc = 0;
for (j = 0; j < len; j++)
acc += abs(amp[i + j] - amp[j]);
/*endfor*/
if (acc < min_acc)
{
min_acc = acc;
pitch = i;
}
/*endif*/
}
/*endfor*/
return pitch;
}
/*- End of function --------------------------------------------------------*/
@ -102,6 +105,7 @@ static __inline__ void overlap_add(int16_t amp1[], int16_t amp2[], int len)
amp2[i] = (int16_t) ((float) amp1[i]*(1.0f - weight) + (float) amp2[i]*weight);
weight += step;
}
/*endfor*/
}
/*- End of function --------------------------------------------------------*/
@ -130,52 +134,6 @@ SPAN_DECLARE(int) time_scale_rate(time_scale_state_t *s, float playout_rate)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(time_scale_state_t *) time_scale_init(time_scale_state_t *s, int sample_rate, float playout_rate)
{
bool alloced;
if (sample_rate > TIME_SCALE_MAX_SAMPLE_RATE)
return NULL;
alloced = false;
if (s == NULL)
{
if ((s = (time_scale_state_t *) span_alloc(sizeof (*s))) == NULL)
return NULL;
/*endif*/
alloced = true;
}
/*endif*/
s->sample_rate = sample_rate;
s->min_pitch = sample_rate/TIME_SCALE_MIN_PITCH;
s->max_pitch = sample_rate/TIME_SCALE_MAX_PITCH;
s->buf_len = 2*sample_rate/TIME_SCALE_MIN_PITCH;
if (time_scale_rate(s, playout_rate))
{
if (alloced)
span_free(s);
return NULL;
}
/*endif*/
s->rate_nudge = 0.0f;
s->fill = 0;
s->lcp = 0;
return s;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale_release(time_scale_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale_free(time_scale_state_t *s)
{
span_free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[], int len)
{
double lcpf;
@ -191,10 +149,12 @@ SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[],
if (s->fill + len < s->buf_len)
{
/* Cannot continue without more samples */
/* Save the residual signal for next time. */
vec_copyi16(&s->buf[s->fill], in, len);
s->fill += len;
return out_len;
}
/*endif*/
k = s->buf_len - s->fill;
vec_copyi16(&s->buf[s->fill], in, k);
in_len += k;
@ -208,15 +168,18 @@ SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[],
if (len - in_len < s->buf_len)
{
/* Cannot continue without more samples */
/* Save the residual signal for next time. */
vec_copyi16(s->buf, &in[in_len], len - in_len);
s->fill = len - in_len;
s->lcp -= s->buf_len;
return out_len;
}
/*endif*/
vec_copyi16(s->buf, &in[in_len], s->buf_len);
in_len += s->buf_len;
s->lcp -= s->buf_len;
}
/*endwhile*/
if (s->lcp > 0)
{
vec_copyi16(&out[out_len], s->buf, s->lcp);
@ -225,15 +188,18 @@ SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[],
if (len - in_len < s->lcp)
{
/* Cannot continue without more samples */
/* Save the residual signal for next time. */
vec_copyi16(&s->buf[s->buf_len - s->lcp], &in[in_len], len - in_len);
s->fill = s->buf_len - s->lcp + len - in_len;
s->lcp = 0;
return out_len;
}
/*endif*/
vec_copyi16(&s->buf[s->buf_len - s->lcp], &in[in_len], s->lcp);
in_len += s->lcp;
s->lcp = 0;
}
/*endif*/
if (s->playout_rate == 1.0f)
{
s->lcp = 0x7FFFFFFF;
@ -256,6 +222,7 @@ SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[],
s->lcp++;
s->rate_nudge += 1.0f;
}
/*endif*/
if (s->playout_rate < 1.0f)
{
/* Speed up - drop a chunk of data */
@ -264,10 +231,12 @@ SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[],
if (len - in_len < pitch)
{
/* Cannot continue without more samples */
/* Save the residual signal for next time. */
vec_copyi16(&s->buf[s->buf_len - pitch], &in[in_len], len - in_len);
s->fill += (len - in_len - pitch);
return out_len;
}
/*endif*/
vec_copyi16(&s->buf[s->buf_len - pitch], &in[in_len], pitch);
in_len += pitch;
}
@ -278,15 +247,88 @@ SPAN_DECLARE(int) time_scale(time_scale_state_t *s, int16_t out[], int16_t in[],
out_len += pitch;
overlap_add(&s->buf[pitch], s->buf, pitch);
}
/*endif*/
}
/*endif*/
}
/*endwhile*/
return out_len;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale_flush(time_scale_state_t *s, int16_t out[])
{
int len;
int pad;
if (s->playout_rate < 1.0f)
return 0;
/*endif*/
vec_copyi16(out, s->buf, s->fill);
len = s->fill;
if (s->playout_rate > 1.0f)
{
pad = s->fill*(s->playout_rate - 1.0f);
vec_zeroi16(&out[len], pad);
len += pad;
}
/*endif*/
s->fill = 0;
return len;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale_max_output_len(time_scale_state_t *s, int input_len)
{
return (int) (input_len*s->playout_rate + s->min_pitch + 1);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(time_scale_state_t *) time_scale_init(time_scale_state_t *s, int sample_rate, float playout_rate)
{
bool alloced;
if (sample_rate > TIME_SCALE_MAX_SAMPLE_RATE)
return NULL;
/*endif*/
alloced = false;
if (s == NULL)
{
if ((s = (time_scale_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
/*endif*/
alloced = true;
}
/*endif*/
s->sample_rate = sample_rate;
s->min_pitch = sample_rate/TIME_SCALE_MIN_PITCH;
s->max_pitch = sample_rate/TIME_SCALE_MAX_PITCH;
s->buf_len = 2*sample_rate/TIME_SCALE_MIN_PITCH;
if (time_scale_rate(s, playout_rate))
{
if (alloced)
span_free(s);
/*endif*/
return NULL;
}
/*endif*/
s->rate_nudge = 0.0f;
s->fill = 0;
s->lcp = 0;
return s;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale_release(time_scale_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) time_scale_free(time_scale_state_t *s)
{
span_free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -579,7 +579,7 @@ static __inline__ void process_half_baud(v22bis_state_t *s, const complexf_t *sa
s->rx.gardner_step = 32;
break;
case V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES:
/* Calling modem only */
/* Calling modem only. */
/* The calling modem should initially receive unscrambled ones at 1200bps */
target = &v22bis_constellation[nearest];
track_carrier(s, &z, target);
@ -621,7 +621,7 @@ static __inline__ void process_half_baud(v22bis_state_t *s, const complexf_t *sa
}
break;
case V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES_SUSTAINING:
/* Calling modem only */
/* Calling modem only. */
/* Wait for the end of the unscrambled ones at 1200bps. */
target = &v22bis_constellation[nearest];
track_carrier(s, &z, target);
@ -682,7 +682,7 @@ static __inline__ void process_half_baud(v22bis_state_t *s, const complexf_t *sa
/* The transmit side needs to sustain the scrambled ones for a timed period. */
s->tx.training_count = 0;
s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
/* Normal reception starts immediately */
/* Normal reception starts immediately. */
s->rx.training = V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION;
#if defined(SPANDSP_USE_FIXED_POINT)
s->rx.carrier_track_i = 8;