Add the new routine for busydetect that you can choose to use in asterisk/Makefile
authorMartin Pycko <martinp@digium.com>
Tue, 17 Jun 2003 21:53:18 +0000 (21:53 +0000)
committerMartin Pycko <martinp@digium.com>
Tue, 17 Jun 2003 21:53:18 +0000 (21:53 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1103 65c4cc65-6c06-0410-ace0-fbb531ad65f3

Makefile
dsp.c

index fa86849..3c86b6a 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,18 @@ MALLOC_DEBUG = #-include $(PWD)/include/asterisk/astmm.h
 # Default -> leave empty
 INSTALL_PREFIX=
 
 # Default -> leave empty
 INSTALL_PREFIX=
 
+# Original busydetect routine
+BUSYDETECT = -DBUSYDETECT
+
+# Improved busydetect routine
+BUSYDETECT+= #-DBUSYDETECT_MARTIN 
+# Detect the busy signal looking only at tone lengths
+# For example if you have 3 beeps 100ms tone, 100ms silence separated by 500 ms of silence
+BUSYDETECT+= #-DBUSYDETECT_TONEONLY
+# Inforce the detection of busy singal (get rid of false hangups)
+# Don't use together with -DBUSYDETECT_TONEONLY
+BUSYDETECT+= #-DBUSYDETECT_COMPARE_TONE_AND_SILENCE
+
 ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
 ASTVARLIBDIR=$(INSTALL_PREFIX)/var/lib/asterisk
 ASTETCDIR=$(INSTALL_PREFIX)/etc/asterisk
 ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
 ASTVARLIBDIR=$(INSTALL_PREFIX)/var/lib/asterisk
 ASTETCDIR=$(INSTALL_PREFIX)/etc/asterisk
@@ -101,6 +113,7 @@ CFLAGS+=-DASTAGIDIR=\"$(AGI_DIR)\"
 CFLAGS+= $(DEBUG_THREADS)
 CFLAGS+= $(TRACE_FRAMES)
 CFLAGS+= $(MALLOC_DEBUG)
 CFLAGS+= $(DEBUG_THREADS)
 CFLAGS+= $(TRACE_FRAMES)
 CFLAGS+= $(MALLOC_DEBUG)
+CFLAGS+= $(BUSYDETECT)
 CFLAGS+=# -fomit-frame-pointer 
 SUBDIRS=res channels pbx apps codecs formats agi cdr astman
 ifeq (${OSARCH},Linux)
 CFLAGS+=# -fomit-frame-pointer 
 SUBDIRS=res channels pbx apps codecs formats agi cdr astman
 ifeq (${OSARCH},Linux)
diff --git a/dsp.c b/dsp.c
index cf3298f..7dc368c 100755 (executable)
--- a/dsp.c
+++ b/dsp.c
 
 #define DEFAULT_THRESHOLD 1024
 
 
 #define DEFAULT_THRESHOLD 1024
 
-#define BUSY_THRESHOLD 100             /* Max number of ms difference between max and min times in busy */
-#define BUSY_MIN               80              /* Busy must be at least 80 ms in half-cadence */
+#define BUSY_PERCENT           10      /* The percentage diffrence between the two last silence periods */
+#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 */
 
 #define BUSY_MAX               1100    /* Busy can't be longer than 1100 ms in half-cadence */
 
-/* Remember last 3 units */
-#define DSP_HISTORY 5
+/* Remember last 15 units */
+#define DSP_HISTORY 15
 
 /* Number of goertzels for progress detect */
 #define GSAMP_SIZE 183
 
 /* Number of goertzels for progress detect */
 #define GSAMP_SIZE 183
@@ -964,24 +965,41 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
        accum = 0;
        for (x=0;x<len; x++) 
                accum += abs(s[x]);
        accum = 0;
        for (x=0;x<len; x++) 
                accum += abs(s[x]);
-       accum /= x;
+       accum /= len;
        if (accum < dsp->threshold) {
                dsp->totalsilence += len/8;
                if (dsp->totalnoise) {
                        /* Move and save history */
        if (accum < dsp->threshold) {
                dsp->totalsilence += len/8;
                if (dsp->totalnoise) {
                        /* Move and save history */
-                       memmove(dsp->historicnoise, dsp->historicnoise + 1, sizeof(dsp->historicnoise) - sizeof(dsp->historicnoise[0]));
+                       memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*sizeof(dsp->historicnoise[0]));
                        dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
                        dsp->historicnoise[DSP_HISTORY - 1] = dsp->totalnoise;
+/* we don't want to check for busydetect that frequently */
+#if 0
                        dsp->busymaybe = 1;
                        dsp->busymaybe = 1;
+#endif
                }
                dsp->totalnoise = 0;
                res = 1;
        } else {
                dsp->totalnoise += len/8;
                if (dsp->totalsilence) {
                }
                dsp->totalnoise = 0;
                res = 1;
        } else {
                dsp->totalnoise += len/8;
                if (dsp->totalsilence) {
+                       int silence1 = dsp->historicsilence[DSP_HISTORY - 1];
+                       int silence2 = dsp->historicsilence[DSP_HISTORY - 2];
                        /* Move and save history */
                        /* Move and save history */
-                       memmove(dsp->historicsilence, dsp->historicsilence + 1, sizeof(dsp->historicsilence) - sizeof(dsp->historicsilence[0]));
+                       memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*sizeof(dsp->historicsilence[0]));
                        dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
                        dsp->historicsilence[DSP_HISTORY - 1] = dsp->totalsilence;
-                       dsp->busymaybe = 1;
+                       /* check if the previous sample differs only by BUSY_PERCENT from the one before it */
+                       if (silence1 < silence2) {
+                               if (silence1 + silence1/BUSY_PERCENT >= silence2)
+                                       dsp->busymaybe = 1;
+                               else 
+                                       dsp->busymaybe = 0;
+                       } else {
+                               if (silence1 - silence1/BUSY_PERCENT <= silence2)
+                                       dsp->busymaybe = 1;
+                               else 
+                                       dsp->busymaybe = 0;
+                       }
+                                       
                }
                dsp->totalsilence = 0;
        }
                }
                dsp->totalsilence = 0;
        }
@@ -989,12 +1007,83 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
                *totalsilence = dsp->totalsilence;
        return res;
 }
                *totalsilence = dsp->totalsilence;
        return res;
 }
+#ifdef BUSYDETECT_MARTIN
+int ast_dsp_busydetect(struct ast_dsp *dsp)
+{
+       int res = 0, x;
+#ifndef BUSYDETECT_TONEONLY
+       int avgsilence = 0, hitsilence = 0;
+#endif
+       int avgtone = 0, hittone = 0;
+       if (!dsp->busymaybe)
+               return res;
+       for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) {
+#ifndef BUSYDETECT_TONEONLY
+               avgsilence += dsp->historicsilence[x];
+#endif
+               avgtone += dsp->historicnoise[x];
+       }
+#ifndef BUSYDETECT_TONEONLY
+       avgsilence /= dsp->busycount;
+#endif
+       avgtone /= dsp->busycount;
+       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])
+                               hitsilence++;
+               } else {
+                       if (avgsilence + (avgsilence / BUSY_PERCENT) >= dsp->historicsilence[x])
+                               hitsilence++;
+               }
+#endif
+               if (avgtone > dsp->historicnoise[x]) {
+                       if (avgtone - (avgtone / BUSY_PERCENT) <= dsp->historicsilence[x])
+                               hittone++;
+               } else {
+                       if (avgtone + (avgtone / BUSY_PERCENT) >= dsp->historicsilence[x])
+                               hittone++;
+               }
+       }
+#ifndef BUSYDETECT_TONEONLY
+       if ((hittone >= dsp->busycount - 1) && (hitsilence >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX) && (avgsilence >= BUSY_MIN && avgsilence <= BUSY_MAX)) {
+#else
+       if ((hittone >= dsp->busycount - 1) && (avgtone >= BUSY_MIN && avgtone <= BUSY_MAX)) {
+#endif
+#ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE
+#ifdef BUSYDETECT_TONEONLY
+#error You can't use BUSYDETECT_TONEONLY together with BUSYDETECT_COMPARE_TONE_AND_SILENCE
+#endif
+               if (avgtone > avgsilence) {
+                       if (avgtone - avgtone/(BUSY_PERCENT*2) <= avgsilence)
+                               res = 1;
+               } else {
+                       if (avgtone + avgtone/(BUSY_PERCENT*2) >= avgsilence)
+                               res = 1;
+               }
+#else
+               res = 1;
+#endif
+       }
+#if 0
+       if (res)
+               ast_log(LOG_NOTICE, "detected busy, avgtone: %d, avgsilence %d\n", avgtone, avgsilence);
+#endif
+       return res;
+}
+#endif
 
 
+#ifdef BUSYDETECT
 int ast_dsp_busydetect(struct ast_dsp *dsp)
 {
        int x;
        int res = 0;
        int max, min;
 int ast_dsp_busydetect(struct ast_dsp *dsp)
 {
        int x;
        int res = 0;
        int max, min;
+
+#if 0
+       if (dsp->busy_hits > 5);
+       return 0;
+#endif
        if (dsp->busymaybe) {
 #if 0
                printf("Maybe busy!\n");
        if (dsp->busymaybe) {
 #if 0
                printf("Maybe busy!\n");
@@ -1027,6 +1116,7 @@ int ast_dsp_busydetect(struct ast_dsp *dsp)
        }
        return res;
 }
        }
        return res;
 }
+#endif
 
 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 {
 
 int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
 {
@@ -1118,6 +1208,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                memset(&dsp->f, 0, sizeof(dsp->f));
                dsp->f.frametype = AST_FRAME_CONTROL;
                dsp->f.subclass = AST_CONTROL_BUSY;
                memset(&dsp->f, 0, sizeof(dsp->f));
                dsp->f.frametype = AST_FRAME_CONTROL;
                dsp->f.subclass = AST_CONTROL_BUSY;
+               ast_log(LOG_DEBUG, "Requesting Hangup because the busy tone was detected on channel %s\n", chan->name);
                return &dsp->f;
        }
        if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
                return &dsp->f;
        }
        if ((dsp->features & DSP_FEATURE_DTMF_DETECT)) {
@@ -1243,7 +1334,7 @@ struct ast_dsp *ast_dsp_new(void)
                memset(dsp, 0, sizeof(struct ast_dsp));
                dsp->threshold = DEFAULT_THRESHOLD;
                dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
                memset(dsp, 0, sizeof(struct ast_dsp));
                dsp->threshold = DEFAULT_THRESHOLD;
                dsp->features = DSP_FEATURE_SILENCE_SUPPRESS;
-               dsp->busycount = 3;
+               dsp->busycount = DSP_HISTORY;
                /* Initialize goertzels */
                goertzel_init(&dsp->freqs[HZ_350], 350.0);
                goertzel_init(&dsp->freqs[HZ_440], 440.0);
                /* Initialize goertzels */
                goertzel_init(&dsp->freqs[HZ_350], 350.0);
                goertzel_init(&dsp->freqs[HZ_440], 440.0);
@@ -1275,8 +1366,8 @@ void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
 
 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
 {
 
 void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
 {
-       if (cadences < 1)
-               cadences = 1;
+       if (cadences < 4)
+               cadences = 4;
        if (cadences > DSP_HISTORY)
                cadences = DSP_HISTORY;
        dsp->busycount = cadences;
        if (cadences > DSP_HISTORY)
                cadences = DSP_HISTORY;
        dsp->busycount = cadences;
@@ -1342,3 +1433,4 @@ int ast_dsp_digitmode(struct ast_dsp *dsp, int digitmode)
        dsp->digitmode = digitmode;
        return 0;
 }
        dsp->digitmode = digitmode;
        return 0;
 }
+