Playback a file with audio detect. More...
#include "asterisk.h"#include "asterisk/lock.h"#include "asterisk/file.h"#include "asterisk/channel.h"#include "asterisk/pbx.h"#include "asterisk/module.h"#include "asterisk/translate.h"#include "asterisk/utils.h"#include "asterisk/dsp.h"#include "asterisk/app.h"
Go to the source code of this file.
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | background_detect_exec (struct ast_channel *chan, void *data) |
| static int | load_module (void) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Playback with Talk Detection" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } |
| static char * | app = "BackgroundDetect" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
Playback a file with audio detect.
Definition in file app_talkdetect.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 251 of file app_talkdetect.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 251 of file app_talkdetect.c.
| static int background_detect_exec | ( | struct ast_channel * | chan, |
| void * | data | ||
| ) | [static] |
Definition at line 76 of file app_talkdetect.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_canmatch_extension(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), ast_goto_if_exists(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_waitfor(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_frame::frametype, ast_channel::language, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), ast_channel::readformat, ast_channel::sched, ast_channel::stream, ast_frame::subclass, ast_channel::timingfunc, and ast_dsp::totalsilence.
Referenced by load_module().
{
int res = 0;
char *tmp;
struct ast_frame *fr;
int notsilent = 0;
struct timeval start = { 0, 0 };
struct timeval detection_start = { 0, 0 };
int sil = 1000;
int min = 100;
int max = -1;
int analysistime = -1;
int continue_analysis = 1;
int x;
int origrformat = 0;
struct ast_dsp *dsp = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
AST_APP_ARG(silence);
AST_APP_ARG(min);
AST_APP_ARG(max);
AST_APP_ARG(analysistime);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
return -1;
}
tmp = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, tmp);
if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%30d", &x) == 1) && (x > 0)) {
sil = x;
}
if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%30d", &x) == 1) && (x > 0)) {
min = x;
}
if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%30d", &x) == 1) && (x > 0)) {
max = x;
}
if (!ast_strlen_zero(args.analysistime) && (sscanf(args.analysistime, "%30d", &x) == 1) && (x > 0)) {
analysistime = x;
}
ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d, analysistime=%d\n", args.filename, sil, min, max, analysistime);
do {
if (chan->_state != AST_STATE_UP) {
if ((res = ast_answer(chan))) {
break;
}
}
origrformat = chan->readformat;
if ((ast_set_read_format(chan, AST_FORMAT_SLINEAR))) {
ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
res = -1;
break;
}
if (!(dsp = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
res = -1;
break;
}
ast_stopstream(chan);
if (ast_streamfile(chan, tmp, chan->language)) {
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
break;
}
detection_start = ast_tvnow();
while (chan->stream) {
res = ast_sched_wait(chan->sched);
if ((res < 0) && !chan->timingfunc) {
res = 0;
break;
}
if (res < 0) {
res = 1000;
}
res = ast_waitfor(chan, res);
if (res < 0) {
ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
break;
} else if (res > 0) {
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) {
res = -1;
break;
} else if (fr->frametype == AST_FRAME_DTMF) {
char t[2];
t[0] = fr->subclass;
t[1] = '\0';
if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
/* They entered a valid extension, or might be anyhow */
res = fr->subclass;
ast_frfree(fr);
break;
}
} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && continue_analysis) {
int totalsilence;
int ms;
res = ast_dsp_silence(dsp, fr, &totalsilence);
if (res && (totalsilence > sil)) {
/* We've been quiet a little while */
if (notsilent) {
/* We had heard some talking */
ms = ast_tvdiff_ms(ast_tvnow(), start);
ms -= sil;
if (ms < 0)
ms = 0;
if ((ms > min) && ((max < 0) || (ms < max))) {
char ms_str[12];
ast_debug(1, "Found qualified token of %d ms\n", ms);
/* Save detected talk time (in milliseconds) */
snprintf(ms_str, sizeof(ms_str), "%d", ms);
pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
ast_goto_if_exists(chan, chan->context, "talk", 1);
res = 0;
ast_frfree(fr);
break;
} else {
ast_debug(1, "Found unqualified token of %d ms\n", ms);
}
notsilent = 0;
}
} else {
if (!notsilent) {
/* Heard some audio, mark the begining of the token */
start = ast_tvnow();
ast_debug(1, "Start of voice token!\n");
notsilent = 1;
}
}
}
ast_frfree(fr);
}
ast_sched_runq(chan->sched);
}
ast_stopstream(chan);
} while (0);
if (res > -1) {
if (origrformat && ast_set_read_format(chan, origrformat)) {
ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
chan->name, ast_getformatname(origrformat));
}
}
if (dsp) {
ast_dsp_free(dsp);
}
return res;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 246 of file app_talkdetect.c.
References ast_register_application_xml, and background_detect_exec().
{
return ast_register_application_xml(app, background_detect_exec);
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 241 of file app_talkdetect.c.
References ast_unregister_application().
{
return ast_unregister_application(app);
}
struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Playback with Talk Detection" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static] |
Definition at line 251 of file app_talkdetect.c.
char* app = "BackgroundDetect" [static] |
Definition at line 74 of file app_talkdetect.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 251 of file app_talkdetect.c.