mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 11:58:52 +00:00
Merge steve's busy detect stuff (bug #4830)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6304 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -234,6 +234,8 @@ static int echocanbridged = 0;
|
|||||||
static int busydetect = 0;
|
static int busydetect = 0;
|
||||||
|
|
||||||
static int busycount = 3;
|
static int busycount = 3;
|
||||||
|
static int busy_tonelength = 0;
|
||||||
|
static int busy_quietlength = 0;
|
||||||
|
|
||||||
static int callprogress = 0;
|
static int callprogress = 0;
|
||||||
|
|
||||||
@@ -611,6 +613,8 @@ static struct zt_pvt {
|
|||||||
int echotraining;
|
int echotraining;
|
||||||
char echorest[20];
|
char echorest[20];
|
||||||
int busycount;
|
int busycount;
|
||||||
|
int busy_tonelength;
|
||||||
|
int busy_quietlength;
|
||||||
int callprogress;
|
int callprogress;
|
||||||
struct timeval flashtime; /* Last flash-hook time */
|
struct timeval flashtime; /* Last flash-hook time */
|
||||||
struct ast_dsp *dsp;
|
struct ast_dsp *dsp;
|
||||||
@@ -4824,6 +4828,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
|
|||||||
ast_dsp_set_call_progress_zone(i->dsp, progzone);
|
ast_dsp_set_call_progress_zone(i->dsp, progzone);
|
||||||
if (i->busydetect && CANBUSYDETECT(i)) {
|
if (i->busydetect && CANBUSYDETECT(i)) {
|
||||||
ast_dsp_set_busy_count(i->dsp, i->busycount);
|
ast_dsp_set_busy_count(i->dsp, i->busycount);
|
||||||
|
ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6871,6 +6876,8 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p
|
|||||||
tmp->echocanbridged = echocanbridged;
|
tmp->echocanbridged = echocanbridged;
|
||||||
tmp->busydetect = busydetect;
|
tmp->busydetect = busydetect;
|
||||||
tmp->busycount = busycount;
|
tmp->busycount = busycount;
|
||||||
|
tmp->busy_tonelength = busy_tonelength;
|
||||||
|
tmp->busy_quietlength = busy_quietlength;
|
||||||
tmp->callprogress = callprogress;
|
tmp->callprogress = callprogress;
|
||||||
tmp->cancallforward = cancallforward;
|
tmp->cancallforward = cancallforward;
|
||||||
tmp->dtmfrelax = relaxdtmf;
|
tmp->dtmfrelax = relaxdtmf;
|
||||||
@@ -10054,6 +10061,10 @@ static int setup_zap(int reload)
|
|||||||
busydetect = ast_true(v->value);
|
busydetect = ast_true(v->value);
|
||||||
} else if (!strcasecmp(v->name, "busycount")) {
|
} else if (!strcasecmp(v->name, "busycount")) {
|
||||||
busycount = atoi(v->value);
|
busycount = atoi(v->value);
|
||||||
|
} else if (!strcasecmp(v->name, "busypattern")) {
|
||||||
|
if (sscanf(v->value, "%d,%d", &busy_tonelength, &busy_quietlength) != 2) {
|
||||||
|
ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
|
||||||
|
}
|
||||||
} else if (!strcasecmp(v->name, "callprogress")) {
|
} else if (!strcasecmp(v->name, "callprogress")) {
|
||||||
if (ast_true(v->value))
|
if (ast_true(v->value))
|
||||||
callprogress |= 1;
|
callprogress |= 1;
|
||||||
|
@@ -366,18 +366,36 @@ immediate=no
|
|||||||
;
|
;
|
||||||
; On trunk interfaces (FXS) and E&M interfaces (E&M, Wink, Feature Group D
|
; On trunk interfaces (FXS) and E&M interfaces (E&M, Wink, Feature Group D
|
||||||
; etc, it can be useful to perform busy detection either in an effort to
|
; etc, it can be useful to perform busy detection either in an effort to
|
||||||
; detect hangup or for detecting busies
|
; detect hangup or for detecting busies. This enables listening for
|
||||||
|
; the beep-beep busy pattern.
|
||||||
;
|
;
|
||||||
;busydetect=yes
|
;busydetect=yes
|
||||||
;
|
;
|
||||||
; If busydetect is enabled, is also possible to specify how many
|
; If busydetect is enabled, is also possible to specify how many
|
||||||
; busy tones to wait before hanging up. The default is 4, but
|
; busy tones to wait for before hanging up. The default is 4, but
|
||||||
; better results can be achieved if set to 6 or even 8. Mind that
|
; better results can be achieved if set to 6 or even 8. Mind that
|
||||||
; higher the number, more time is needed to hangup a channel, but
|
; higher the number, more time is needed to hangup a channel, but
|
||||||
; lower is probability to get random hangups
|
; lower is probability to get random hangups
|
||||||
;
|
;
|
||||||
;busycount=4
|
;busycount=4
|
||||||
;
|
;
|
||||||
|
; If busydetect is enabled, is also possible to specify the
|
||||||
|
; cadence of your busy signal. In many countries it is 500mec
|
||||||
|
; on, 500msec off.
|
||||||
|
; Without busypattern specified, we'll accept any regular
|
||||||
|
; sound-silence pattern than repeats busycount times as a busy
|
||||||
|
; signal.
|
||||||
|
; If you specify busypattern then we'll further check the length
|
||||||
|
; of the sound (tone) and silence, which will further reduce the
|
||||||
|
; chance of a false positive.
|
||||||
|
;
|
||||||
|
;busypattern=500,500
|
||||||
|
;
|
||||||
|
; NOTE: In the Asterisk Makefile you'll find further options to tweak
|
||||||
|
; the busy detector. If your country has a busy tone with the same
|
||||||
|
; lengh tone and silence (as many countries do), consider defining
|
||||||
|
; the -DBUSYDETECT_COMPARE_TONE_AND_SILENCE option.
|
||||||
|
;
|
||||||
; Use a polarity reversal to mark when a outgoing call is answered by the
|
; Use a polarity reversal to mark when a outgoing call is answered by the
|
||||||
; remote party.
|
; remote party.
|
||||||
;
|
;
|
||||||
|
53
dsp.c
53
dsp.c
@@ -93,7 +93,8 @@ static struct progress {
|
|||||||
|
|
||||||
#define DEFAULT_THRESHOLD 512
|
#define DEFAULT_THRESHOLD 512
|
||||||
|
|
||||||
#define BUSY_PERCENT 10 /* The percentage diffrence between the two last silence periods */
|
#define BUSY_PERCENT 10 /* The percentage difference between the two last silence periods */
|
||||||
|
#define BUSY_PAT_PERCENT 7 /* The percentage difference between measured and actual pattern */
|
||||||
#define BUSY_THRESHOLD 100 /* Max number of ms difference between max and min times in busy */
|
#define BUSY_THRESHOLD 100 /* Max number of ms difference between max and min times in busy */
|
||||||
#define BUSY_MIN 75 /* Busy must be at least 80 ms in half-cadence */
|
#define BUSY_MIN 75 /* Busy must be at least 80 ms in half-cadence */
|
||||||
#define BUSY_MAX 1100 /* Busy can't be longer than 1100 ms in half-cadence */
|
#define BUSY_MAX 1100 /* Busy can't be longer than 1100 ms in half-cadence */
|
||||||
@@ -304,6 +305,8 @@ struct ast_dsp {
|
|||||||
int features;
|
int features;
|
||||||
int busymaybe;
|
int busymaybe;
|
||||||
int busycount;
|
int busycount;
|
||||||
|
int busy_tonelength;
|
||||||
|
int busy_quietlength;
|
||||||
int historicnoise[DSP_HISTORY];
|
int historicnoise[DSP_HISTORY];
|
||||||
int historicsilence[DSP_HISTORY];
|
int historicsilence[DSP_HISTORY];
|
||||||
goertzel_state_t freqs[7];
|
goertzel_state_t freqs[7];
|
||||||
@@ -1154,6 +1157,7 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
|
|||||||
accum += abs(s[x]);
|
accum += abs(s[x]);
|
||||||
accum /= len;
|
accum /= len;
|
||||||
if (accum < dsp->threshold) {
|
if (accum < dsp->threshold) {
|
||||||
|
/* Silent */
|
||||||
dsp->totalsilence += len/8;
|
dsp->totalsilence += len/8;
|
||||||
if (dsp->totalnoise) {
|
if (dsp->totalnoise) {
|
||||||
/* Move and save history */
|
/* Move and save history */
|
||||||
@@ -1167,6 +1171,7 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
|
|||||||
dsp->totalnoise = 0;
|
dsp->totalnoise = 0;
|
||||||
res = 1;
|
res = 1;
|
||||||
} else {
|
} else {
|
||||||
|
/* Not silent */
|
||||||
dsp->totalnoise += len/8;
|
dsp->totalnoise += len/8;
|
||||||
if (dsp->totalsilence) {
|
if (dsp->totalsilence) {
|
||||||
int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
|
int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
|
||||||
@@ -1176,12 +1181,12 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
|
|||||||
dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
|
dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
|
||||||
/* check if the previous sample differs only by BUSY_PERCENT from the one before it */
|
/* check if the previous sample differs only by BUSY_PERCENT from the one before it */
|
||||||
if (silence1 < silence2) {
|
if (silence1 < silence2) {
|
||||||
if (silence1 + silence1/BUSY_PERCENT >= silence2)
|
if (silence1 + silence1*BUSY_PERCENT/100 >= silence2)
|
||||||
dsp->busymaybe = 1;
|
dsp->busymaybe = 1;
|
||||||
else
|
else
|
||||||
dsp->busymaybe = 0;
|
dsp->busymaybe = 0;
|
||||||
} else {
|
} else {
|
||||||
if (silence1 - silence1/BUSY_PERCENT <= silence2)
|
if (silence1 - silence1*BUSY_PERCENT/100 <= silence2)
|
||||||
dsp->busymaybe = 1;
|
dsp->busymaybe = 1;
|
||||||
else
|
else
|
||||||
dsp->busymaybe = 0;
|
dsp->busymaybe = 0;
|
||||||
@@ -1193,6 +1198,7 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
|
|||||||
*totalsilence = dsp->totalsilence;
|
*totalsilence = dsp->totalsilence;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUSYDETECT_MARTIN
|
#ifdef BUSYDETECT_MARTIN
|
||||||
int ast_dsp_busydetect(struct ast_dsp *dsp)
|
int ast_dsp_busydetect(struct ast_dsp *dsp)
|
||||||
{
|
{
|
||||||
@@ -1216,18 +1222,18 @@ int ast_dsp_busydetect(struct ast_dsp *dsp)
|
|||||||
for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
|
for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
|
||||||
#ifndef BUSYDETECT_TONEONLY
|
#ifndef BUSYDETECT_TONEONLY
|
||||||
if (avgsilence > dsp->historicsilence[x]) {
|
if (avgsilence > dsp->historicsilence[x]) {
|
||||||
if (avgsilence - (avgsilence / BUSY_PERCENT) <= dsp->historicsilence[x])
|
if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x])
|
||||||
hitsilence++;
|
hitsilence++;
|
||||||
} else {
|
} else {
|
||||||
if (avgsilence + (avgsilence / BUSY_PERCENT) >= dsp->historicsilence[x])
|
if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x])
|
||||||
hitsilence++;
|
hitsilence++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (avgtone > dsp->historicnoise[x]) {
|
if (avgtone > dsp->historicnoise[x]) {
|
||||||
if (avgtone - (avgtone / BUSY_PERCENT) <= dsp->historicnoise[x])
|
if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x])
|
||||||
hittone++;
|
hittone++;
|
||||||
} else {
|
} else {
|
||||||
if (avgtone + (avgtone / BUSY_PERCENT) >= dsp->historicnoise[x])
|
if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x])
|
||||||
hittone++;
|
hittone++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1243,19 +1249,39 @@ int ast_dsp_busydetect(struct ast_dsp *dsp)
|
|||||||
#error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
|
#error You cant use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
|
||||||
#endif
|
#endif
|
||||||
if (avgtone > avgsilence) {
|
if (avgtone > avgsilence) {
|
||||||
if (avgtone - avgtone/(BUSY_PERCENT*2) <= avgsilence)
|
if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence)
|
||||||
res = 1;
|
res = 1;
|
||||||
} else {
|
} else {
|
||||||
if (avgtone + avgtone/(BUSY_PERCENT*2) >= avgsilence)
|
if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence)
|
||||||
res = 1;
|
res = 1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
res = 1;
|
res = 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
/* If we know the expected busy tone length, check we are in the range */
|
||||||
|
if (res && (dsp->busy_tonelength > 0)) {
|
||||||
|
if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
|
||||||
#if 0
|
#if 0
|
||||||
|
ast_log(LOG_NOTICE, "busy detector: avgtone of %d not close enough to desired %d\n",
|
||||||
|
avgtone, dsp->busy_tonelength);
|
||||||
|
#endif
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If we know the expected busy tone silent-period length, check we are in the range */
|
||||||
|
if (res && (dsp->busy_quietlength > 0)) {
|
||||||
|
if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
|
||||||
|
#if 0
|
||||||
|
ast_log(LOG_NOTICE, "busy detector: avgsilence of %d not close enough to desired %d\n",
|
||||||
|
avgsilence, dsp->busy_quietlength);
|
||||||
|
#endif
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
if (res)
|
if (res)
|
||||||
ast_log(LOG_NOTICE, "detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
|
ast_log(LOG_DEBUG, "ast_dsp_busydetect detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
|
||||||
#endif
|
#endif
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1576,6 +1602,13 @@ void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
|
|||||||
dsp->busycount = cadences;
|
dsp->busycount = cadences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
|
||||||
|
{
|
||||||
|
dsp->busy_tonelength = tonelength;
|
||||||
|
dsp->busy_quietlength = quietlength;
|
||||||
|
ast_log(LOG_DEBUG, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
|
||||||
|
}
|
||||||
|
|
||||||
void ast_dsp_digitreset(struct ast_dsp *dsp)
|
void ast_dsp_digitreset(struct ast_dsp *dsp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@@ -53,6 +53,9 @@ void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold);
|
|||||||
/* Set number of required cadences for busy */
|
/* Set number of required cadences for busy */
|
||||||
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences);
|
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences);
|
||||||
|
|
||||||
|
/* Set expected lengths of the busy tone */
|
||||||
|
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength);
|
||||||
|
|
||||||
/* Scans for progress indication in audio */
|
/* Scans for progress indication in audio */
|
||||||
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf);
|
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user