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 | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Playback with Talk Detection") | |
static int | background_detect_exec (struct ast_channel *chan, const char *data) |
static int | load_module (void) |
static int | unload_module (void) |
Variables | |
static char * | app = "BackgroundDetect" |
Playback a file with audio detect.
Definition in file app_talkdetect.c.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Playback with Talk Detection" | ||||
) |
static int background_detect_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 80 of file app_talkdetect.c.
References ast_channel::_state, args, 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::caller, ast_frame_subclass::codec, ast_channel::context, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, LOG_WARNING, ast_party_id::number, pbx_builtin_setvar_helper(), ast_channel::readformat, S_COR, ast_channel::sched, ast_party_number::str, ast_channel::stream, ast_frame::subclass, ast_channel::timingfunc, ast_dsp::totalsilence, and ast_party_number::valid.
Referenced by load_module().
00081 { 00082 int res = 0; 00083 char *tmp; 00084 struct ast_frame *fr; 00085 int notsilent = 0; 00086 struct timeval start = { 0, 0 }; 00087 struct timeval detection_start = { 0, 0 }; 00088 int sil = 1000; 00089 int min = 100; 00090 int max = -1; 00091 int analysistime = -1; 00092 int continue_analysis = 1; 00093 int x; 00094 int origrformat = 0; 00095 struct ast_dsp *dsp = NULL; 00096 AST_DECLARE_APP_ARGS(args, 00097 AST_APP_ARG(filename); 00098 AST_APP_ARG(silence); 00099 AST_APP_ARG(min); 00100 AST_APP_ARG(max); 00101 AST_APP_ARG(analysistime); 00102 ); 00103 00104 if (ast_strlen_zero(data)) { 00105 ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n"); 00106 return -1; 00107 } 00108 00109 tmp = ast_strdupa(data); 00110 AST_STANDARD_APP_ARGS(args, tmp); 00111 00112 if (!ast_strlen_zero(args.silence) && (sscanf(args.silence, "%30d", &x) == 1) && (x > 0)) { 00113 sil = x; 00114 } 00115 if (!ast_strlen_zero(args.min) && (sscanf(args.min, "%30d", &x) == 1) && (x > 0)) { 00116 min = x; 00117 } 00118 if (!ast_strlen_zero(args.max) && (sscanf(args.max, "%30d", &x) == 1) && (x > 0)) { 00119 max = x; 00120 } 00121 if (!ast_strlen_zero(args.analysistime) && (sscanf(args.analysistime, "%30d", &x) == 1) && (x > 0)) { 00122 analysistime = x; 00123 } 00124 00125 ast_debug(1, "Preparing detect of '%s', sil=%d, min=%d, max=%d, analysistime=%d\n", args.filename, sil, min, max, analysistime); 00126 do { 00127 if (chan->_state != AST_STATE_UP) { 00128 if ((res = ast_answer(chan))) { 00129 break; 00130 } 00131 } 00132 00133 origrformat = chan->readformat; 00134 if ((ast_set_read_format(chan, AST_FORMAT_SLINEAR))) { 00135 ast_log(LOG_WARNING, "Unable to set read format to linear!\n"); 00136 res = -1; 00137 break; 00138 } 00139 00140 if (!(dsp = ast_dsp_new())) { 00141 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 00142 res = -1; 00143 break; 00144 } 00145 ast_stopstream(chan); 00146 if (ast_streamfile(chan, tmp, chan->language)) { 00147 ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data); 00148 break; 00149 } 00150 detection_start = ast_tvnow(); 00151 while (chan->stream) { 00152 res = ast_sched_wait(chan->sched); 00153 if ((res < 0) && !chan->timingfunc) { 00154 res = 0; 00155 break; 00156 } 00157 if (res < 0) { 00158 res = 1000; 00159 } 00160 res = ast_waitfor(chan, res); 00161 if (res < 0) { 00162 ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name); 00163 break; 00164 } else if (res > 0) { 00165 fr = ast_read(chan); 00166 if (continue_analysis && analysistime >= 0) { 00167 /* If we have a limit for the time to analyze voice 00168 * frames and the time has not expired */ 00169 if (ast_tvdiff_ms(ast_tvnow(), detection_start) >= analysistime) { 00170 continue_analysis = 0; 00171 ast_verb(3, "BackgroundDetect: Talk analysis time complete on %s.\n", chan->name); 00172 } 00173 } 00174 00175 if (!fr) { 00176 res = -1; 00177 break; 00178 } else if (fr->frametype == AST_FRAME_DTMF) { 00179 char t[2]; 00180 t[0] = fr->subclass.integer; 00181 t[1] = '\0'; 00182 if (ast_canmatch_extension(chan, chan->context, t, 1, 00183 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 00184 /* They entered a valid extension, or might be anyhow */ 00185 res = fr->subclass.integer; 00186 ast_frfree(fr); 00187 break; 00188 } 00189 } else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass.codec == AST_FORMAT_SLINEAR) && continue_analysis) { 00190 int totalsilence; 00191 int ms; 00192 res = ast_dsp_silence(dsp, fr, &totalsilence); 00193 if (res && (totalsilence > sil)) { 00194 /* We've been quiet a little while */ 00195 if (notsilent) { 00196 /* We had heard some talking */ 00197 ms = ast_tvdiff_ms(ast_tvnow(), start); 00198 ms -= sil; 00199 if (ms < 0) 00200 ms = 0; 00201 if ((ms > min) && ((max < 0) || (ms < max))) { 00202 char ms_str[12]; 00203 ast_debug(1, "Found qualified token of %d ms\n", ms); 00204 00205 /* Save detected talk time (in milliseconds) */ 00206 snprintf(ms_str, sizeof(ms_str), "%d", ms); 00207 pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str); 00208 00209 ast_goto_if_exists(chan, chan->context, "talk", 1); 00210 res = 0; 00211 ast_frfree(fr); 00212 break; 00213 } else { 00214 ast_debug(1, "Found unqualified token of %d ms\n", ms); 00215 } 00216 notsilent = 0; 00217 } 00218 } else { 00219 if (!notsilent) { 00220 /* Heard some audio, mark the begining of the token */ 00221 start = ast_tvnow(); 00222 ast_debug(1, "Start of voice token!\n"); 00223 notsilent = 1; 00224 } 00225 } 00226 } 00227 ast_frfree(fr); 00228 } 00229 ast_sched_runq(chan->sched); 00230 } 00231 ast_stopstream(chan); 00232 } while (0); 00233 00234 if (res > -1) { 00235 if (origrformat && ast_set_read_format(chan, origrformat)) { 00236 ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 00237 chan->name, ast_getformatname(origrformat)); 00238 } 00239 } 00240 if (dsp) { 00241 ast_dsp_free(dsp); 00242 } 00243 return res; 00244 }
static int load_module | ( | void | ) | [static] |
Definition at line 251 of file app_talkdetect.c.
References ast_register_application_xml, and background_detect_exec().
00252 { 00253 return ast_register_application_xml(app, background_detect_exec); 00254 }
static int unload_module | ( | void | ) | [static] |
Definition at line 246 of file app_talkdetect.c.
References ast_unregister_application().
00247 { 00248 return ast_unregister_application(app); 00249 }
char* app = "BackgroundDetect" [static] |
Definition at line 78 of file app_talkdetect.c.