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
1.6.1
Tilghman Lesher 17 years ago
parent b0b8bcd3b2
commit 9d403c379f

@ -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)
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)
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)
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)
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)
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)
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;
} }

Loading…
Cancel
Save