diff --git a/CHANGES b/CHANGES index 6e3a49bda..3a4ca5ec6 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,11 @@ Asterisk HTTP Server -------------------------- * The HTTP Server can bind to IPv6 addresses. +chan_dahdi +-------------------------- + * Busy tone patterns featuring 2 silence and 2 tone lengths can now be used + with busydetect. usage example: busypattern=200,200,200,600 + CLI Changes -------------------------- * New 'gtalk show settings' command showing the current settings loaded from diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 39ecbfed6..1e10d4e94 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -1115,15 +1115,10 @@ struct dahdi_pvt { */ int busycount; /*! - * \brief Length of "busy" tone on time. - * \note Set from the "busypattern" value read in from chan_dahdi.conf + * \brief Busy cadence pattern description. + * \note Set from the "busypattern" value read from chan_dahdi.conf */ - int busy_tonelength; - /*! - * \brief Length of "busy" tone off time. - * \note Set from the "busypattern" value read in from chan_dahdi.conf - */ - int busy_quietlength; + struct ast_dsp_busy_pattern busy_cadence; /*! * \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values. * \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf @@ -9542,7 +9537,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb 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); + ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence); } } } @@ -12615,8 +12610,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, } tmp->busydetect = conf->chan.busydetect; tmp->busycount = conf->chan.busycount; - tmp->busy_tonelength = conf->chan.busy_tonelength; - tmp->busy_quietlength = conf->chan.busy_quietlength; + tmp->busy_cadence = conf->chan.busy_cadence; tmp->callprogress = conf->chan.callprogress; tmp->waitfordialtone = conf->chan.waitfordialtone; tmp->cancallforward = conf->chan.cancallforward; @@ -15120,7 +15114,7 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); #endif ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); - ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength); + ast_cli(a->fd, " Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0); } ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); @@ -16664,6 +16658,40 @@ static unsigned long dahdi_display_text_option(const char *value) /*! process_dahdi() - No warnings on non-existing cofiguration keywords */ #define PROC_DAHDI_OPT_NOWARN (1 << 1) +static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence) +{ + int count_pattern = 0; + int norval = 0; + char *temp = NULL; + + for (; ;) { + /* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */ + if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) { ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno); + break; + } + + busy_cadence->pattern[count_pattern] = norval; + + count_pattern++; + if (count_pattern == 4) { + break; + } + + temp = strchr(v->value, ','); + if (temp == NULL) { + break; + } + v->value = temp + 1; + } + busy_cadence->length = count_pattern; + + if (count_pattern % 2 != 0) { + /* The pattern length must be divisible by two */ + ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno); + } + +} + static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options) { struct dahdi_pvt *tmp; @@ -16789,9 +16817,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct } else if (!strcasecmp(v->name, "busycount")) { confp->chan.busycount = atoi(v->value); } else if (!strcasecmp(v->name, "busypattern")) { - if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) { - ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); - } + parse_busy_pattern(v, &confp->chan.busy_cadence); } else if (!strcasecmp(v->name, "callprogress")) { confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; if (ast_true(v->value)) diff --git a/include/asterisk/dsp.h b/include/asterisk/dsp.h index bea0e6f5e..10ada9955 100644 --- a/include/asterisk/dsp.h +++ b/include/asterisk/dsp.h @@ -59,6 +59,13 @@ struct ast_dsp; +struct ast_dsp_busy_pattern { + /*! Number of elements. */ + int length; + /*! Pattern elements in on/off time durations. */ + int pattern[4]; +}; + enum threshold { /* Array offsets */ THRESHOLD_SILENCE = 0, @@ -76,7 +83,7 @@ void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold); void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences); /*! \brief Set expected lengths of the busy tone */ -void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength); +void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence); /*! \brief Scans for progress indication in audio */ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf); diff --git a/main/dsp.c b/main/dsp.c index 69989afe8..a83adc2a0 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -378,8 +378,7 @@ struct ast_dsp { int ringtimeout; int busymaybe; int busycount; - int busy_tonelength; - int busy_quietlength; + struct ast_dsp_busy_pattern busy_cadence; int historicnoise[DSP_HISTORY]; int historicsilence[DSP_HISTORY]; goertzel_state_t freqs[7]; @@ -1183,9 +1182,14 @@ int ast_dsp_busydetect(struct ast_dsp *dsp) int avgsilence = 0, hitsilence = 0; #endif int avgtone = 0, hittone = 0; - if (!dsp->busymaybe) { - return res; + + /* if we have a 4 length pattern, the way busymaybe is set doesn't help us. */ + if (dsp->busy_cadence.length != 4) { + if (!dsp->busymaybe) { + return res; + } } + for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { #ifndef BUSYDETECT_TONEONLY avgsilence += dsp->historicsilence[x]; @@ -1239,23 +1243,60 @@ int ast_dsp_busydetect(struct ast_dsp *dsp) res = 1; #endif } + + /* If we have a 4-length pattern, we can go ahead and just check it in a different way. */ + if (dsp->busy_cadence.length == 4) { + int x; + int errors = 0; + int errors_max = ((4 * dsp->busycount) / 100.0) * BUSY_PAT_PERCENT; + + for (x = DSP_HISTORY - (dsp->busycount); x < DSP_HISTORY; x += 2) { + int temp_error; + temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.pattern[0]); + if ((temp_error * 100) / dsp->busy_cadence.pattern[0] > BUSY_PERCENT) { + errors++; + } + + temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.pattern[2]); + if ((temp_error * 100) / dsp->busy_cadence.pattern[2] > BUSY_PERCENT) { + errors++; + } + + temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.pattern[1]); + if ((temp_error * 100) / dsp->busy_cadence.pattern[1] > BUSY_PERCENT) { + errors++; + } + + temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.pattern[3]); + if ((temp_error * 100) / dsp->busy_cadence.pattern[3] > BUSY_PERCENT) { + errors++; + } + } + + ast_debug(5, "errors = %d max = %d\n", errors, errors_max); + + if (errors <= errors_max) { + return 1; + } + } + /* 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 (res && (dsp->busy_cadence.pattern[0] > 0)) { + if (abs(avgtone - dsp->busy_cadence.pattern[0]) > (dsp->busy_cadence.pattern[0]*BUSY_PAT_PERCENT/100)) { #ifdef BUSYDETECT_DEBUG ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n", - avgtone, dsp->busy_tonelength); + avgtone, dsp->busy_cadence.pattern[0]); #endif res = 0; } } #ifndef BUSYDETECT_TONEONLY /* 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 (res && (dsp->busy_cadence.pattern[1] > 0)) { + if (abs(avgsilence - dsp->busy_cadence.pattern[1]) > (dsp->busy_cadence.pattern[1] * BUSY_PAT_PERCENT / 100)) { #ifdef BUSYDETECT_DEBUG ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n", - avgsilence, dsp->busy_quietlength); + avgsilence, dsp->busy_cadence.pattern[1]); #endif res = 0; } @@ -1571,11 +1612,10 @@ 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) +void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence) { - dsp->busy_tonelength = tonelength; - dsp->busy_quietlength = quietlength; - ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength); + dsp->busy_cadence = *cadence; + ast_debug(1, "dsp busy pattern set to %d,%d,%d,%d\n", cadence->pattern[0], cadence->pattern[1], (cadence->length == 4) ? cadence->pattern[2] : 0, (cadence->length == 4) ? cadence->pattern[3] : 0); } void ast_dsp_digitreset(struct ast_dsp *dsp)