From 6e782fbe4270ad11f6224fc809065cc916582ad6 Mon Sep 17 00:00:00 2001 From: markster Date: Mon, 8 Aug 2005 00:08:48 +0000 Subject: Merge steve's busy detect stuff (bug #4830) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@6304 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_zap.c | 11 ++++++++++ configs/zapata.conf.sample | 22 +++++++++++++++++-- dsp.c | 53 +++++++++++++++++++++++++++++++++++++--------- include/asterisk/dsp.h | 3 +++ 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/channels/chan_zap.c b/channels/chan_zap.c index b8425eb59..0874a3118 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -234,6 +234,8 @@ static int echocanbridged = 0; static int busydetect = 0; static int busycount = 3; +static int busy_tonelength = 0; +static int busy_quietlength = 0; static int callprogress = 0; @@ -611,6 +613,8 @@ static struct zt_pvt { int echotraining; char echorest[20]; int busycount; + int busy_tonelength; + int busy_quietlength; int callprogress; struct timeval flashtime; /* Last flash-hook time */ 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); if (i->busydetect && CANBUSYDETECT(i)) { 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->busydetect = busydetect; tmp->busycount = busycount; + tmp->busy_tonelength = busy_tonelength; + tmp->busy_quietlength = busy_quietlength; tmp->callprogress = callprogress; tmp->cancallforward = cancallforward; tmp->dtmfrelax = relaxdtmf; @@ -10054,6 +10061,10 @@ static int setup_zap(int reload) busydetect = ast_true(v->value); } else if (!strcasecmp(v->name, "busycount")) { 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")) { if (ast_true(v->value)) callprogress |= 1; diff --git a/configs/zapata.conf.sample b/configs/zapata.conf.sample index c18edc2c0..4eca285c6 100755 --- a/configs/zapata.conf.sample +++ b/configs/zapata.conf.sample @@ -366,18 +366,36 @@ immediate=no ; ; 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 -; detect hangup or for detecting busies +; detect hangup or for detecting busies. This enables listening for +; the beep-beep busy pattern. ; ;busydetect=yes ; ; 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 ; higher the number, more time is needed to hangup a channel, but ; lower is probability to get random hangups ; ;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 ; remote party. ; diff --git a/dsp.c b/dsp.c index 3f370f372..9c74467ed 100755 --- a/dsp.c +++ b/dsp.c @@ -93,7 +93,8 @@ static struct progress { #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_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 */ @@ -304,6 +305,8 @@ struct ast_dsp { int features; int busymaybe; int busycount; + int busy_tonelength; + int busy_quietlength; int historicnoise[DSP_HISTORY]; int historicsilence[DSP_HISTORY]; 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 /= len; if (accum < dsp->threshold) { + /* Silent */ dsp->totalsilence += len/8; if (dsp->totalnoise) { /* 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; res = 1; } else { + /* Not silent */ dsp->totalnoise += len/8; if (dsp->totalsilence) { 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; /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ if (silence1 < silence2) { - if (silence1 + silence1/BUSY_PERCENT >= silence2) + if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) dsp->busymaybe = 1; else dsp->busymaybe = 0; } else { - if (silence1 - silence1/BUSY_PERCENT <= silence2) + if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) dsp->busymaybe = 1; else 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; return res; } + #ifdef BUSYDETECT_MARTIN 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->historicsilence[x]) { - if (avgsilence - (avgsilence / BUSY_PERCENT) <= dsp->historicsilence[x]) + if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) hitsilence++; } else { - if (avgsilence + (avgsilence / BUSY_PERCENT) >= dsp->historicsilence[x]) + if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) hitsilence++; } #endif if (avgtone > dsp->historicnoise[x]) { - if (avgtone - (avgtone / BUSY_PERCENT) <= dsp->historicnoise[x]) + if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) hittone++; } else { - if (avgtone + (avgtone / BUSY_PERCENT) >= dsp->historicnoise[x]) + if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) 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 #endif if (avgtone > avgsilence) { - if (avgtone - avgtone/(BUSY_PERCENT*2) <= avgsilence) + if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) res = 1; } else { - if (avgtone + avgtone/(BUSY_PERCENT*2) >= avgsilence) + if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) res = 1; } #else res = 1; #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 + 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) - 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 return res; } @@ -1576,6 +1602,13 @@ void ast_dsp_set_busy_count(struct ast_dsp *dsp, int 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) { int i; diff --git a/include/asterisk/dsp.h b/include/asterisk/dsp.h index d335b18bf..07e74c947 100755 --- a/include/asterisk/dsp.h +++ b/include/asterisk/dsp.h @@ -53,6 +53,9 @@ void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold); /* Set number of required cadences for busy */ 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 */ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf); -- cgit v1.2.3