mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-24 06:53:41 +00:00
Improve DTMF handling in ast_read() even more in response to a discussion on
the asterisk-dev mailing list. I changed the enforced minimum length of a digit from 100ms to 80ms. Furthermore, I made it now enforce a gap of 45ms in between digits. These values are not configurable in a configuration file right now, but they can be easily changed near the top of main/channel.c. git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@61781 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -428,7 +428,7 @@ struct ast_channel {
|
||||
|
||||
char emulate_dtmf_digit; /*!< Digit being emulated */
|
||||
unsigned int emulate_dtmf_duration; /*!< Number of ms left to emulate DTMF for */
|
||||
struct timeval dtmf_begin_tv; /*!< The time that an in process digit began */
|
||||
struct timeval dtmf_tv; /*!< The time that an in process digit began, or the last digit ended */
|
||||
|
||||
/*! \brief Data stores on the channel */
|
||||
AST_LIST_HEAD_NOLOCK(datastores, ast_datastore) datastores;
|
||||
|
@@ -104,9 +104,17 @@ unsigned long global_fin, global_fout;
|
||||
AST_THREADSTORAGE(state2str_threadbuf, state2str_threadbuf_init);
|
||||
#define STATE2STR_BUFSIZE 32
|
||||
|
||||
/*! 100ms */
|
||||
/*! Default amount of time to use when emulating a digit as a begin and end
|
||||
* 100ms */
|
||||
#define AST_DEFAULT_EMULATE_DTMF_DURATION 100
|
||||
|
||||
/*! Minimum allowed digit length - 80ms */
|
||||
#define AST_MIN_DTMF_DURATION 80
|
||||
|
||||
/*! Minimum amount of time between the end of the last digit and the beginning
|
||||
* of a new one - 45ms */
|
||||
#define AST_MIN_DTMF_GAP 45
|
||||
|
||||
struct chanlist {
|
||||
const struct ast_channel_tech *tech;
|
||||
AST_LIST_ENTRY(chanlist) list;
|
||||
@@ -2113,7 +2121,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
prestate = chan->_state;
|
||||
|
||||
if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) &&
|
||||
!ast_strlen_zero(chan->dtmfq)) {
|
||||
!ast_strlen_zero(chan->dtmfq) &&
|
||||
(ast_tvzero(chan->dtmf_tv) || ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) > AST_MIN_DTMF_GAP) ) {
|
||||
/* We have DTMF that has been deferred. Return it now */
|
||||
chan->dtmff.subclass = chan->dtmfq[0];
|
||||
/* Drop first digit from the buffer */
|
||||
@@ -2126,8 +2135,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
|
||||
chan->emulate_dtmf_digit = f->subclass;
|
||||
chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
|
||||
chan->dtmf_begin_tv = ast_tvnow();
|
||||
}
|
||||
chan->dtmf_tv = ast_tvnow();
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -2264,34 +2273,50 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
ast_frfree(f);
|
||||
f = &ast_null_frame;
|
||||
} else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) {
|
||||
if (!ast_tvzero(chan->dtmf_tv) &&
|
||||
ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) {
|
||||
/* If it hasn't been long enough, defer this digit */
|
||||
if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
|
||||
chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
|
||||
ast_frfree(f);
|
||||
f = &ast_null_frame;
|
||||
} else {
|
||||
/* There was no begin, turn this into a begin and send the end later */
|
||||
f->frametype = AST_FRAME_DTMF_BEGIN;
|
||||
ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
|
||||
chan->emulate_dtmf_digit = f->subclass;
|
||||
chan->dtmf_begin_tv = ast_tvnow();
|
||||
if (f->len && f->len > AST_DEFAULT_EMULATE_DTMF_DURATION)
|
||||
chan->dtmf_tv = ast_tvnow();
|
||||
if (f->len && f->len > AST_MIN_DTMF_DURATION)
|
||||
chan->emulate_dtmf_duration = f->len;
|
||||
else
|
||||
chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
|
||||
chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION;
|
||||
}
|
||||
} else {
|
||||
struct timeval now = ast_tvnow();
|
||||
ast_clear_flag(chan, AST_FLAG_IN_DTMF);
|
||||
if (!f->len)
|
||||
f->len = ast_tvdiff_ms(ast_tvnow(), chan->dtmf_begin_tv);
|
||||
if (f->len < AST_DEFAULT_EMULATE_DTMF_DURATION) {
|
||||
f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
|
||||
if (f->len < AST_MIN_DTMF_DURATION) {
|
||||
ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
|
||||
chan->emulate_dtmf_digit = f->subclass;
|
||||
chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION - f->len;
|
||||
chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION - f->len;
|
||||
f = &ast_null_frame;
|
||||
}
|
||||
} else
|
||||
chan->dtmf_tv = now;
|
||||
}
|
||||
break;
|
||||
case AST_FRAME_DTMF_BEGIN:
|
||||
ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name);
|
||||
if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY)) {
|
||||
if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY) ||
|
||||
(!ast_tvzero(chan->dtmf_tv) &&
|
||||
ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) ) {
|
||||
ast_frfree(f);
|
||||
f = &ast_null_frame;
|
||||
} else {
|
||||
ast_set_flag(chan, AST_FLAG_IN_DTMF);
|
||||
chan->dtmf_begin_tv = ast_tvnow();
|
||||
chan->dtmf_tv = ast_tvnow();
|
||||
}
|
||||
break;
|
||||
case AST_FRAME_VOICE:
|
||||
@@ -2309,10 +2334,12 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
|
||||
f = &ast_null_frame;
|
||||
} else if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) {
|
||||
if ((f->samples / 8) >= chan->emulate_dtmf_duration) { /* XXX 8kHz */
|
||||
struct timeval now = ast_tvnow();
|
||||
chan->emulate_dtmf_duration = 0;
|
||||
f->frametype = AST_FRAME_DTMF_END;
|
||||
f->subclass = chan->emulate_dtmf_digit;
|
||||
f->len = ast_tvdiff_ms(ast_tvnow(), chan->dtmf_begin_tv);
|
||||
f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
|
||||
chan->dtmf_tv = now;
|
||||
} else {
|
||||
chan->emulate_dtmf_duration -= f->samples / 8; /* XXX 8kHz */
|
||||
ast_frfree(f);
|
||||
|
Reference in New Issue
Block a user