Merge steve's busy detect stuff (bug #4830)
authorMark Spencer <markster@digium.com>
Mon, 8 Aug 2005 00:08:48 +0000 (00:08 +0000)
committerMark Spencer <markster@digium.com>
Mon, 8 Aug 2005 00:08:48 +0000 (00:08 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6304 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_zap.c
configs/zapata.conf.sample
dsp.c
include/asterisk/dsp.h

index b8425eb..0874a31 100755 (executable)
@@ -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;
index c18edc2..4eca285 100755 (executable)
@@ -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 3f370f3..9c74467 100755 (executable)
--- 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_HISTORY;x++) {
 #ifndef BUSYDETECT_TONEONLY
                if (avgsilence > 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;
index d335b18..07e74c9 100755 (executable)
@@ -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);