diff --git a/CHANGES b/CHANGES index 78f0080b80e73ebc7e234c9d9750922290cc50d0..2f84e4cce352ba2d89468c552c94d572b4312829 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,11 @@ Skinny Changes Please have a look at configs/skinny.conf.sample and change your skinny.conf accordingly. +DAHDI Changes +------------- + * The UK option waitfordialtone has been added for use with BT analog + lines. + Dialplan Functions ------------------ * Added a new dialplan function, CURLOPT, which permits setting various diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 053e6755fa1303c7e79a584e65030fd8ff55575c..75734d8fe855ada9bc59bc8b81e0b5295572a49d 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -712,6 +712,8 @@ static struct dahdi_pvt { int busy_tonelength; int busy_quietlength; int callprogress; + int waitfordialtone; + struct timeval waitingfordt; /*!< Time we started waiting for dialtone */ struct timeval flashtime; /*!< Last flash-hook time */ struct ast_dsp *dsp; int cref; /*!< Call reference number */ @@ -2182,6 +2184,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) ast_mutex_unlock(&p->lock); return -1; } + p->waitingfordt.tv_sec = 0; p->dialednone = 0; if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ { @@ -2405,6 +2408,20 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; } else p->echobreak = 0; + + /* waitfordialtone ? */ +#ifdef HAVE_PRI + if (!p->pri) { +#endif + if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) { + ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone); + gettimeofday(&p->waitingfordt,NULL); + ast_setstate(ast, AST_STATE_OFFHOOK); + break; + } +#ifdef HAVE_PRI + } +#endif if (!res) { if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { int saveerr = errno; @@ -3446,6 +3463,7 @@ static int dahdi_hangup(struct ast_channel *ast) p->callwaitcas = 0; p->callwaiting = p->permcallwaiting; p->hidecallerid = p->permhidecallerid; + p->waitingfordt.tv_sec = 0; p->dialing = 0; p->rdnis[0] = '\0'; update_conf(p); @@ -5183,6 +5201,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) case DAHDI_EVENT_HOOKCOMPLETE: if (p->inalarm) break; if ((p->radio || (p->oprmode < 0))) break; + if (p->waitingfordt.tv_sec) break; switch (mysig) { case SIG_FXSLS: /* only interesting for FXS */ case SIG_FXSGS: @@ -5639,8 +5658,8 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) p->subs[idx].f.data.ptr = NULL; p->subs[idx].f.datalen= 0; } - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) { - /* Perform busy detection. etc on the dahdi line */ + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { + /* Perform busy detection etc on the dahdi line */ int mute; f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); @@ -5671,6 +5690,35 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) #endif /* DSP clears us of being pulse */ p->pulsedial = 0; + } else if (p->waitingfordt.tv_sec) { + if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { + p->waitingfordt.tv_sec = 0; + ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); + f=NULL; + } else if (f->frametype == AST_FRAME_VOICE) { + f->frametype = AST_FRAME_NULL; + f->subclass = 0; + if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) { + p->waitingfordt.tv_sec = 0; + p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; + ast_dsp_set_features(p->dsp, p->dsp_features); + ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); + if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ + res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); + if (res < 0) { + ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); + p->dop.dialstr[0] = '\0'; + return NULL; + } else { + ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); + p->dialing = 1; + p->dop.dialstr[0] = '\0'; + p->dop.op = DAHDI_DIAL_OP_REPLACE; + ast_setstate(ast, AST_STATE_DIALING); + } + } + } + } } } } else @@ -6094,6 +6142,8 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb features |= DSP_FEATURE_BUSY_DETECT; if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) features |= DSP_FEATURE_CALL_PROGRESS; + if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) + features |= DSP_FEATURE_WAITDIALTONE; if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { features |= DSP_FEATURE_FAX_DETECT; @@ -8809,6 +8859,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, tmp->busy_tonelength = conf->chan.busy_tonelength; tmp->busy_quietlength = conf->chan.busy_quietlength; tmp->callprogress = conf->chan.callprogress; + tmp->waitfordialtone = conf->chan.waitfordialtone; tmp->cancallforward = conf->chan.cancallforward; tmp->dtmfrelax = conf->chan.dtmfrelax; tmp->callwaiting = tmp->permcallwaiting; @@ -12471,6 +12522,7 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli } else { ast_cli(a->fd, "\tnone\n"); } + ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); if (tmp->master) ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); for (x = 0; x < MAX_SLAVES; x++) { @@ -13917,6 +13969,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; if (ast_true(v->value)) confp->chan.callprogress |= CALLPROGRESS_PROGRESS; + } else if (!strcasecmp(v->name, "waitfordialtone")) { + confp->chan.waitfordialtone = atoi(v->value); } else if (!strcasecmp(v->name, "faxdetect")) { confp->chan.callprogress &= ~CALLPROGRESS_FAX; if (!strcasecmp(v->value, "incoming")) { diff --git a/configs/chan_dahdi.conf.sample b/configs/chan_dahdi.conf.sample index 01da859c953113ec3b7807483dd0bcdc9052aa40..85087c504b4b15041c204ac3a7f8aad7d06c9dcc 100644 --- a/configs/chan_dahdi.conf.sample +++ b/configs/chan_dahdi.conf.sample @@ -361,6 +361,13 @@ usecallerid=yes ; ;hidecallerid=yes ; +; On UK analog lines, the caller hanging up determines the end of calls. So +; Asterisk hanging up the line may or may not end a call (DAHDI could just as +; easily be re-attaching to a prior incoming call that was not yet hung up). +; This option changes the hangup to wait for a dialtone on the line, before +; marking the line as once again available for use with outgoing calls. +;waitfordialtone=yes +; ; The following option enables receiving MWI on FXO lines. The default ; value is no. When this is enabled, and MWI notification indicates on or off, ; the script specified by the mwimonitornotify option is executed. Also, an diff --git a/include/asterisk/dsp.h b/include/asterisk/dsp.h index 5193ff4dd933d8a380a45ef9d4d6c4ff67f65685..5a599cc4b7fc2df40834969f43f0fc0df0d51fa8 100644 --- a/include/asterisk/dsp.h +++ b/include/asterisk/dsp.h @@ -41,6 +41,7 @@ #define DSP_PROGRESS_BUSY (1 << 18) /*!< Enable busy tone detection */ #define DSP_PROGRESS_CONGESTION (1 << 19) /*!< Enable congestion tone detection */ #define DSP_FEATURE_CALL_PROGRESS (DSP_PROGRESS_TALK | DSP_PROGRESS_RINGING | DSP_PROGRESS_BUSY | DSP_PROGRESS_CONGESTION) +#define DSP_FEATURE_WAITDIALTONE (1 << 20) /*!< Enable dial tone detection */ #define DSP_FAXMODE_DETECT_CNG (1 << 0) #define DSP_FAXMODE_DETECT_CED (1 << 1) diff --git a/main/dsp.c b/main/dsp.c index 6963bda2c2a4de3c937b0ce8b612b090a56656bd..6c0b013e469fdcbb2f72a3251da820dbf866fb24 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -82,7 +82,9 @@ enum freq_index { HZ_425 = 0, /*! For UK mode */ - HZ_400 = 0 + HZ_350UK = 0, + HZ_400UK, + HZ_440UK }; static struct progalias { @@ -102,7 +104,7 @@ static struct progress { } modes[] = { { GSAMP_SIZE_NA, { 350, 440, 480, 620, 950, 1400, 1800 } }, /*!< North America */ { GSAMP_SIZE_CR, { 425 } }, /*!< Costa Rica, Brazil */ - { GSAMP_SIZE_UK, { 400 } }, /*!< UK */ + { GSAMP_SIZE_UK, { 350, 400, 440 } }, /*!< UK */ }; /*!\brief This value is the minimum threshold, calculated by averaging all @@ -322,8 +324,9 @@ static inline void goertzel_update(goertzel_state_t *s, short *samps, int count) { int i; - for (i=0;i<count;i++) + for (i = 0; i < count; i++) { goertzel_sample(s, samps[i]); + } } @@ -481,8 +484,8 @@ static void ast_dtmf_detect_init (dtmf_detect_state_t *s) s->lasthit = 0; s->current_hit = 0; for (i = 0; i < 4; i++) { - goertzel_init (&s->row_out[i], dtmf_row[i], DTMF_GSIZE); - goertzel_init (&s->col_out[i], dtmf_col[i], DTMF_GSIZE); + goertzel_init(&s->row_out[i], dtmf_row[i], DTMF_GSIZE); + goertzel_init(&s->col_out[i], dtmf_col[i], DTMF_GSIZE); s->energy = 0.0; } s->current_sample = 0; @@ -511,10 +514,11 @@ static void ast_digit_detect_init(digit_detect_state_t *s, int mf) s->lost_digits = 0; s->digits[0] = '\0'; - if (mf) + if (mf) { ast_mf_detect_init(&s->td.mf); - else + } else { ast_dtmf_detect_init(&s->td.dtmf); + } } static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp, int samples) @@ -536,8 +540,9 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp for (start = 0; start < samples; start = end) { /* Process in blocks. */ limit = samples - start; - if (limit > s->samples_pending) + if (limit > s->samples_pending) { limit = s->samples_pending; + } end = start + limit; for (i = limit, ptr = amp ; i > 0; i--, ptr++) { @@ -567,8 +572,9 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp hit = 1; } - if (s->hit_count) + if (s->hit_count) { s->hit_count++; + } if (hit == s->last_hit) { if (!hit) { @@ -651,12 +657,13 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp } hit = 0; - for (sample = 0; sample < samples; sample = limit) { + for (sample = 0; sample < samples; sample = limit) { /* DTMF_GSIZE is optimised to meet the DTMF specs. */ - if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) + if ((samples - sample) >= (DTMF_GSIZE - s->td.dtmf.current_sample)) { limit = sample + (DTMF_GSIZE - s->td.dtmf.current_sample); - else + } else { limit = samples; + } /* The following unrolled loop takes only 35% (rough estimate) of the time of a rolled loop on the machine on which it was developed */ for (j = sample; j < limit; j++) { @@ -684,30 +691,32 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp for (best_row = best_col = 0, i = 1; i < 4; i++) { row_energy[i] = goertzel_result (&s->td.dtmf.row_out[i]); - if (row_energy[i] > row_energy[best_row]) + if (row_energy[i] > row_energy[best_row]) { best_row = i; + } col_energy[i] = goertzel_result (&s->td.dtmf.col_out[i]); - if (col_energy[i] > col_energy[best_col]) + if (col_energy[i] > col_energy[best_col]) { best_col = i; + } } hit = 0; /* Basic signal level test and the twist test */ if (row_energy[best_row] >= DTMF_THRESHOLD && col_energy[best_col] >= DTMF_THRESHOLD && - col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST && - col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) { + col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST && + col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) { /* Relative peak test */ for (i = 0; i < 4; i++) { if ((i != best_col && - col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || + col_energy[i] * DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) || (i != best_row - && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { + && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) { break; } } /* ... and fraction of total energy test */ if (i >= 4 && - (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY*s->td.dtmf.energy) { + (row_energy[best_row] + col_energy[best_col]) > DTMF_TO_TOTAL_ENERGY * s->td.dtmf.energy) { /* Got a hit */ hit = dtmf_positions[(best_row << 2) + best_col]; } @@ -758,7 +767,7 @@ static int dtmf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp } /* Reinitialise the detector for the next block */ - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { goertzel_reset(&s->td.dtmf.row_out[i]); goertzel_reset(&s->td.dtmf.col_out[i]); } @@ -800,10 +809,11 @@ static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[] for (sample = 0; sample < samples; sample = limit) { /* 80 is optimised to meet the MF specs. */ /* XXX So then why is MF_GSIZE defined as 120? */ - if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) + if ((samples - sample) >= (MF_GSIZE - s->td.mf.current_sample)) { limit = sample + (MF_GSIZE - s->td.mf.current_sample); - else + } else { limit = samples; + } /* The following unrolled loop takes only 35% (rough estimate) of the time of a rolled loop on the machine on which it was developed */ for (j = sample; j < limit; j++) { @@ -838,7 +848,7 @@ static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[] second_best = 0; } /*endif*/ - for (i=2;i<6;i++) { + for (i = 2; i < 6; i++) { energy[i] = goertzel_result(&s->td.mf.tone_out[i]); if (energy[i] >= energy[best]) { second_best = best; @@ -851,10 +861,10 @@ static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[] hit = 0; if (energy[best] >= BELL_MF_THRESHOLD && energy[second_best] >= BELL_MF_THRESHOLD && energy[best] < energy[second_best]*BELL_MF_TWIST - && energy[best]*BELL_MF_TWIST > energy[second_best]) { + && energy[best] * BELL_MF_TWIST > energy[second_best]) { /* Relative peak test */ hit = -1; - for (i=0;i<6;i++) { + for (i = 0; i < 6; i++) { if (i != best && i != second_best) { if (energy[i]*BELL_MF_RELATIVE_PEAK >= energy[second_best]) { /* The best two are not clearly the best */ @@ -871,7 +881,7 @@ static int mf_detect(struct ast_dsp *dsp, digit_detect_state_t *s, int16_t amp[] best = second_best; second_best = i; } - best = best*5 + second_best - 1; + best = best * 5 + second_best - 1; hit = bell_mf_positions[best]; /* Look for two successive similar results */ /* The logic in the next test is: @@ -930,18 +940,21 @@ static inline int pair_there(float p1, float p2, float i1, float i2, float e) { /* See if p1 and p2 are there, relative to i1 and i2 and total energy */ /* Make sure absolute levels are high enough */ - if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) + if ((p1 < TONE_MIN_THRESH) || (p2 < TONE_MIN_THRESH)) { return 0; + } /* Amplify ignored stuff */ i2 *= TONE_THRESH; i1 *= TONE_THRESH; e *= TONE_THRESH; /* Check first tone */ - if ((p1 < i1) || (p1 < i2) || (p1 < e)) + if ((p1 < i1) || (p1 < i2) || (p1 < e)) { return 0; + } /* And second */ - if ((p2 < i1) || (p2 < i2) || (p2 < e)) + if ((p2 < i1) || (p2 < i2) || (p2 < e)) { return 0; + } /* Guess it's there... */ return 1; } @@ -956,11 +969,13 @@ static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len) while (len) { /* Take the lesser of the number of samples we need and what we have */ pass = len; - if (pass > dsp->gsamp_size - dsp->gsamps) + if (pass > dsp->gsamp_size - dsp->gsamps) { pass = dsp->gsamp_size - dsp->gsamps; - for (x=0;x<pass;x++) { - for (y=0;y<dsp->freqcount;y++) + } + for (x = 0; x < pass; x++) { + for (y = 0; y < dsp->freqcount; y++) { goertzel_sample(&dsp->freqs[y], s[x]); + } dsp->genergy += s[x] * s[x]; } s += pass; @@ -968,8 +983,9 @@ static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len) len -= pass; if (dsp->gsamps == dsp->gsamp_size) { float hz[7]; - for (y=0;y<7;y++) + for (y = 0; y < 7; y++) { hz[y] = goertzel_result(&dsp->freqs[y]); + } switch (dsp->progmode) { case PROG_MODE_NA: if (pair_there(hz[HZ_480], hz[HZ_620], hz[HZ_350], hz[HZ_440], dsp->genergy)) { @@ -984,24 +1000,29 @@ static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len) if (dsp->tstate == DSP_TONE_STATE_SPECIAL1) newstate = DSP_TONE_STATE_SPECIAL2; } else if (hz[HZ_1800] > TONE_MIN_THRESH * TONE_THRESH) { - if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) + if (dsp->tstate == DSP_TONE_STATE_SPECIAL2) { newstate = DSP_TONE_STATE_SPECIAL3; + } } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { newstate = DSP_TONE_STATE_TALKING; - } else + } else { newstate = DSP_TONE_STATE_SILENCE; + } break; case PROG_MODE_CR: if (hz[HZ_425] > TONE_MIN_THRESH * TONE_THRESH) { newstate = DSP_TONE_STATE_RINGING; } else if (dsp->genergy > TONE_MIN_THRESH * TONE_THRESH) { newstate = DSP_TONE_STATE_TALKING; - } else + } else { newstate = DSP_TONE_STATE_SILENCE; + } break; case PROG_MODE_UK: - if (hz[HZ_400] > TONE_MIN_THRESH * TONE_THRESH) { + if (hz[HZ_400UK] > TONE_MIN_THRESH * TONE_THRESH) { newstate = DSP_TONE_STATE_HUNGUP; + } else if (pair_there(hz[HZ_350UK], hz[HZ_440UK], hz[HZ_400UK], hz[HZ_400UK], dsp->genergy)) { + newstate = DSP_TONE_STATE_DIALTONE; } break; default: @@ -1009,8 +1030,9 @@ static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len) } if (newstate == dsp->tstate) { dsp->tcount++; - if (dsp->ringtimeout) + if (dsp->ringtimeout) { dsp->ringtimeout++; + } switch (dsp->tstate) { case DSP_TONE_STATE_RINGING: if ((dsp->features & DSP_PROGRESS_RINGING) && @@ -1061,8 +1083,9 @@ static int __ast_dsp_call_progress(struct ast_dsp *dsp, short *s, int len) } /* Reset goertzel */ - for (x=0;x<7;x++) + for (x = 0; x < 7; x++) { dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; + } dsp->gsamps = 0; dsp->genergy = 0.0; } @@ -1090,18 +1113,20 @@ static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int * int x; int res = 0; - if (!len) + if (!len) { return 0; + } accum = 0; - for (x=0;x<len; x++) + for (x = 0; x < len; x++) { accum += abs(s[x]); + } accum /= len; if (accum < dsp->threshold) { /* Silent */ - dsp->totalsilence += len/8; + dsp->totalsilence += len / 8; if (dsp->totalnoise) { /* Move and save history */ - memmove(dsp->historicnoise + DSP_HISTORY - dsp->busycount, dsp->historicnoise + DSP_HISTORY - dsp->busycount +1, dsp->busycount*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; /* we don't want to check for busydetect that frequently */ #if 0 @@ -1112,32 +1137,36 @@ static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int * res = 1; } else { /* Not silent */ - dsp->totalnoise += len/8; + 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 */ - memmove(dsp->historicsilence + DSP_HISTORY - dsp->busycount, dsp->historicsilence + DSP_HISTORY - dsp->busycount + 1, dsp->busycount*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; /* check if the previous sample differs only by BUSY_PERCENT from the one before it */ if (silence1 < silence2) { - if (silence1 + silence1*BUSY_PERCENT/100 >= silence2) + if (silence1 + silence1 * BUSY_PERCENT / 100 >= silence2) { dsp->busymaybe = 1; - else + } else { dsp->busymaybe = 0; + } } else { - if (silence1 - silence1*BUSY_PERCENT/100 <= silence2) + if (silence1 - silence1 * BUSY_PERCENT / 100 <= silence2) { dsp->busymaybe = 1; - else + } else { dsp->busymaybe = 0; + } } } dsp->totalsilence = 0; } - if (totalsilence) + if (totalsilence) { *totalsilence = dsp->totalsilence; - if (totalnoise) + } + if (totalnoise) { *totalnoise = dsp->totalnoise; + } return res; } @@ -1148,9 +1177,10 @@ int ast_dsp_busydetect(struct ast_dsp *dsp) int avgsilence = 0, hitsilence = 0; #endif int avgtone = 0, hittone = 0; - if (!dsp->busymaybe) + if (!dsp->busymaybe) { return res; - for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { + } + for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { #ifndef BUSYDETECT_TONEONLY avgsilence += dsp->historicsilence[x]; #endif @@ -1160,22 +1190,26 @@ int ast_dsp_busydetect(struct ast_dsp *dsp) avgsilence /= dsp->busycount; #endif avgtone /= dsp->busycount; - for (x=DSP_HISTORY - dsp->busycount;x<DSP_HISTORY;x++) { + for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) { #ifndef BUSYDETECT_TONEONLY if (avgsilence > dsp->historicsilence[x]) { - if (avgsilence - (avgsilence*BUSY_PERCENT/100) <= dsp->historicsilence[x]) + if (avgsilence - (avgsilence * BUSY_PERCENT / 100) <= dsp->historicsilence[x]) { hitsilence++; + } } else { - if (avgsilence + (avgsilence*BUSY_PERCENT/100) >= dsp->historicsilence[x]) + if (avgsilence + (avgsilence * BUSY_PERCENT / 100) >= dsp->historicsilence[x]) { hitsilence++; + } } #endif if (avgtone > dsp->historicnoise[x]) { - if (avgtone - (avgtone*BUSY_PERCENT/100) <= dsp->historicnoise[x]) + if (avgtone - (avgtone * BUSY_PERCENT / 100) <= dsp->historicnoise[x]) { hittone++; + } } else { - if (avgtone + (avgtone*BUSY_PERCENT/100) >= dsp->historicnoise[x]) + if (avgtone + (avgtone * BUSY_PERCENT / 100) >= dsp->historicnoise[x]) { hittone++; + } } } #ifndef BUSYDETECT_TONEONLY @@ -1187,11 +1221,13 @@ int ast_dsp_busydetect(struct ast_dsp *dsp) #endif #ifdef BUSYDETECT_COMPARE_TONE_AND_SILENCE if (avgtone > avgsilence) { - if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) + if (avgtone - avgtone*BUSY_PERCENT/100 <= avgsilence) { res = 1; + } } else { - if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) + if (avgtone + avgtone*BUSY_PERCENT/100 >= avgsilence) { res = 1; + } } #else res = 1; @@ -1277,10 +1313,12 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, int len; struct ast_frame *outf = NULL; - if (!af) + if (!af) { return NULL; - if (af->frametype != AST_FRAME_VOICE) + } + if (af->frametype != AST_FRAME_VOICE) { return af; + } odata = af->data.ptr; len = af->datalen; @@ -1292,13 +1330,15 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, break; case AST_FORMAT_ULAW: shortdata = alloca(af->datalen * 2); - for (x = 0;x < len; x++) + for (x = 0;x < len; x++) { shortdata[x] = AST_MULAW(odata[x]); + } break; case AST_FORMAT_ALAW: shortdata = alloca(af->datalen * 2); - for (x = 0; x < len; x++) + for (x = 0; x < len; x++) { shortdata[x] = AST_ALAW(odata[x]); + } break; default: ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); @@ -1408,6 +1448,8 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, ast_log(LOG_WARNING, "Don't know how to represent call progress message %d\n", res); } } + } else if ((dsp->features & DSP_FEATURE_WAITDIALTONE)) { + res = __ast_dsp_call_progress(dsp, shortdata, len); } done: @@ -1420,18 +1462,21 @@ done: case AST_FORMAT_SLINEAR: break; case AST_FORMAT_ULAW: - for (x = 0; x < len; x++) + for (x = 0; x < len; x++) { odata[x] = AST_LIN2MU((unsigned short) shortdata[x]); + } break; case AST_FORMAT_ALAW: - for (x = 0; x < len; x++) + for (x = 0; x < len; x++) { odata[x] = AST_LIN2A((unsigned short) shortdata[x]); + } break; } if (outf) { - if (chan) + if (chan) { ast_queue_frame(chan, af); + } ast_frfree(af); ast_set_flag(outf, AST_FRFLAG_FROM_DSP); return outf; @@ -1504,10 +1549,12 @@ void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold) void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences) { - if (cadences < 4) + if (cadences < 4) { cadences = 4; - if (cadences > DSP_HISTORY) + } + if (cadences > DSP_HISTORY) { cadences = DSP_HISTORY; + } dsp->busycount = cadences; } @@ -1555,8 +1602,9 @@ void ast_dsp_reset(struct ast_dsp *dsp) dsp->totalsilence = 0; dsp->gsamps = 0; - for (x=0;x<4;x++) + for (x = 0; x < 4; x++) { dsp->freqs[x].v2 = dsp->freqs[x].v3 = 0.0; + } memset(dsp->historicsilence, 0, sizeof(dsp->historicsilence)); memset(dsp->historicnoise, 0, sizeof(dsp->historicnoise)); dsp->ringtimeout= 0; @@ -1632,8 +1680,9 @@ static int _dsp_init(int reload) if (value && sscanf(value, "%d", &thresholds[THRESHOLD_SILENCE]) != 1) { ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, value); thresholds[THRESHOLD_SILENCE] = 256; - } else if (!value) + } else if (!value) { thresholds[THRESHOLD_SILENCE] = 256; + } ast_config_destroy(cfg); }