Thu Apr 28 2011 17:13:39

Asterisk developer's documentation


app_talkdetect.c File Reference

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"
Include dependency graph for app_talkdetect.c:

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_infoast_module_info = &__mod_info

Detailed Description

Playback a file with audio detect.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_talkdetect.c.


Function Documentation

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]
static int unload_module ( void  ) [static]

Definition at line 241 of file app_talkdetect.c.

References ast_unregister_application().


Variable Documentation

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.

Definition at line 251 of file app_talkdetect.c.