Skip to content
Snippets Groups Projects
Commit 9d403c37 authored by Tilghman Lesher's avatar Tilghman Lesher
Browse files

Add an option, specifying maximum analysis time for talk detection.

(closes issue #12149)
 Reported by: davevg
 Patches: 
       app_talkdetect.c.diff uploaded by davevg (license 209)
       (Plus a few additional cleanups by moi)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@123544 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent b0b8bcd3
Branches
Tags
No related merge requests found
...@@ -44,15 +44,15 @@ static char *app = "BackgroundDetect"; ...@@ -44,15 +44,15 @@ static char *app = "BackgroundDetect";
static char *synopsis = "Background a file with talk detect"; static char *synopsis = "Background a file with talk detect";
static char *descrip = static char *descrip =
" BackgroundDetect(filename[,sil[,min,[max]]]): Plays back a given\n" " BackgroundDetect(<filename>[,<sil>[,<min>[,<max>[,<analysistime>]]]]):\n"
"filename, waiting for interruption from a given digit (the digit must\n" "Plays back <filename>, waiting for interruption from a given digit (the digit\n"
"start the beginning of a valid extension, or it will be ignored).\n" "must start the beginning of a valid extension, or it will be ignored). During\n"
"During the playback of the file, audio is monitored in the receive\n" "the playback of the file, audio is monitored in the receive direction, and if\n"
"direction, and if a period of non-silence which is greater than 'min' ms\n" "a period of non-silence which is greater than <min> ms yet less than <max> ms\n"
"yet less than 'max' ms is followed by silence for at least 'sil' ms then\n" "is followed by silence for at least <sil> ms, which occurs during the first\n"
"the audio playback is aborted and processing jumps to the 'talk' extension\n" "<analysistime> ms, then the audio playback is aborted and processing jumps to\n"
"if available. If unspecified, sil, min, and max default to 1000, 100, and\n" "the <talk> extension, if available. If unspecified, <sil>, <min>, <max>, and\n"
"infinity respectively.\n"; "<analysistime> default to 1000, 100, infinity, and infinity respectively.\n";
static int background_detect_exec(struct ast_channel *chan, void *data) static int background_detect_exec(struct ast_channel *chan, void *data)
...@@ -61,18 +61,22 @@ static int background_detect_exec(struct ast_channel *chan, void *data) ...@@ -61,18 +61,22 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
char *tmp; char *tmp;
struct ast_frame *fr; struct ast_frame *fr;
int notsilent = 0; int notsilent = 0;
struct timeval start = { 0, 0}; struct timeval start = { 0, 0 };
struct timeval detection_start = { 0, 0 };
int sil = 1000; int sil = 1000;
int min = 100; int min = 100;
int max = -1; int max = -1;
int analysistime = -1;
int continue_analysis = 1;
int x; int x;
int origrformat=0; int origrformat = 0;
struct ast_dsp *dsp = NULL; struct ast_dsp *dsp = NULL;
AST_DECLARE_APP_ARGS(args, AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename); AST_APP_ARG(filename);
AST_APP_ARG(silence); AST_APP_ARG(silence);
AST_APP_ARG(min); AST_APP_ARG(min);
AST_APP_ARG(max); AST_APP_ARG(max);
AST_APP_ARG(analysistime);
); );
if (ast_strlen_zero(data)) { if (ast_strlen_zero(data)) {
...@@ -83,18 +87,25 @@ static int background_detect_exec(struct ast_channel *chan, void *data) ...@@ -83,18 +87,25 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
tmp = ast_strdupa(data); tmp = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, tmp); AST_STANDARD_APP_ARGS(args, tmp);
if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%d", &x) == 1) && (x > 0)) if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%d", &x) == 1) && (x > 0)) {
sil = x; sil = x;
if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%d", &x) == 1) && (x > 0)) }
if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%d", &x) == 1) && (x > 0)) {
min = x; min = x;
if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%d", &x) == 1) && (x > 0)) }
if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%d", &x) == 1) && (x > 0)) {
max = x; max = x;
}
if (!ast_strlen_zero(args.analysistime) && (sscanf(args.analysistime, "%d", &x) == 1) && (x > 0)) {
analysistime = x;
}
ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d\n", args.filename, sil, min, max); ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d, analysistime=%d\n", args.filename, sil, min, max, analysistime);
do { do {
if (chan->_state != AST_STATE_UP) { if (chan->_state != AST_STATE_UP) {
if ((res = ast_answer(chan))) if ((res = ast_answer(chan))) {
break; break;
}
} }
origrformat = chan->readformat; origrformat = chan->readformat;
...@@ -114,21 +125,31 @@ static int background_detect_exec(struct ast_channel *chan, void *data) ...@@ -114,21 +125,31 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data); ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
break; break;
} }
detection_start = ast_tvnow();
while (chan->stream) { while (chan->stream) {
res = ast_sched_wait(chan->sched); res = ast_sched_wait(chan->sched);
if ((res < 0) && !chan->timingfunc) { if ((res < 0) && !chan->timingfunc) {
res = 0; res = 0;
break; break;
} }
if (res < 0) if (res < 0) {
res = 1000; res = 1000;
}
res = ast_waitfor(chan, res); res = ast_waitfor(chan, res);
if (res < 0) { if (res < 0) {
ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name); ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
break; break;
} else if (res > 0) { } else if (res > 0) {
fr = ast_read(chan); fr = ast_read(chan);
if (continue_analysis && analysistime >= 0) {
/* If we have a limit for the time to analyze voice
* frames and the time has not expired */
if (ast_tvdiff_ms(ast_tvnow(), detection_start) >= analysistime) {
continue_analysis = 0;
ast_verb(3, "BackgroundDetect: Talk analysis time complete on %s.\n", chan->name);
}
}
if (!fr) { if (!fr) {
res = -1; res = -1;
break; break;
...@@ -142,7 +163,7 @@ static int background_detect_exec(struct ast_channel *chan, void *data) ...@@ -142,7 +163,7 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
ast_frfree(fr); ast_frfree(fr);
break; break;
} }
} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) { } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && continue_analysis) {
int totalsilence; int totalsilence;
int ms; int ms;
res = ast_dsp_silence(dsp, fr, &totalsilence); res = ast_dsp_silence(dsp, fr, &totalsilence);
...@@ -155,11 +176,11 @@ static int background_detect_exec(struct ast_channel *chan, void *data) ...@@ -155,11 +176,11 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
if (ms < 0) if (ms < 0)
ms = 0; ms = 0;
if ((ms > min) && ((max < 0) || (ms < max))) { if ((ms > min) && ((max < 0) || (ms < max))) {
char ms_str[10]; char ms_str[12];
ast_debug(1, "Found qualified token of %d ms\n", ms); ast_debug(1, "Found qualified token of %d ms\n", ms);
/* Save detected talk time (in milliseconds) */ /* Save detected talk time (in milliseconds) */
sprintf(ms_str, "%d", ms ); snprintf(ms_str, sizeof(ms_str), "%d", ms);
pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str); pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
ast_goto_if_exists(chan, chan->context, "talk", 1); ast_goto_if_exists(chan, chan->context, "talk", 1);
...@@ -193,8 +214,9 @@ static int background_detect_exec(struct ast_channel *chan, void *data) ...@@ -193,8 +214,9 @@ static int background_detect_exec(struct ast_channel *chan, void *data)
chan->name, ast_getformatname(origrformat)); chan->name, ast_getformatname(origrformat));
} }
} }
if (dsp) if (dsp) {
ast_dsp_free(dsp); ast_dsp_free(dsp);
}
return res; return res;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment