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.