Mon Oct 8 12:39:07 2012

Asterisk developer's documentation


app_amd.c File Reference

Answering machine detection. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/app.h"

Go to the source code of this file.

Defines

#define STATE_IN_SILENCE   2
#define STATE_IN_WORD   1

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int amd_exec (struct ast_channel *chan, const char *data)
static void isAnsweringMachine (struct ast_channel *chan, const char *data)
static int load_config (int reload)
static int load_module (void)
static int reload (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Answering Machine Detection Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, }
static const char app [] = "AMD"
static struct ast_module_infoast_module_info = &__mod_info
static int dfltAfterGreetingSilence = 800
static int dfltBetweenWordsSilence = 50
static int dfltGreeting = 1500
static int dfltInitialSilence = 2500
static int dfltMaximumNumberOfWords = 3
static int dfltMaximumWordLength = 5000
static int dfltMaxWaitTimeForFrame = 50
static int dfltMinimumWordLength = 100
static int dfltSilenceThreshold = 256
static int dfltTotalAnalysisTime = 5000


Detailed Description

Answering machine detection.

Author:
Claude Klimos (claude.klimos@aheeva.com)

Definition in file app_amd.c.


Define Documentation

#define STATE_IN_SILENCE   2

Definition at line 133 of file app_amd.c.

Referenced by isAnsweringMachine().

#define STATE_IN_WORD   1

Definition at line 132 of file app_amd.c.

Referenced by isAnsweringMachine().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 508 of file app_amd.c.

static void __unreg_module ( void   )  [static]

Definition at line 508 of file app_amd.c.

static int amd_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 412 of file app_amd.c.

References isAnsweringMachine().

Referenced by load_module().

00413 {
00414    isAnsweringMachine(chan, data);
00415 
00416    return 0;
00417 }

static void isAnsweringMachine ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 149 of file app_amd.c.

References ast_party_caller::ani, args, AST_APP_ARG, ast_codec_get_samples(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_CNG, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), ast_log(), ast_read(), ast_set_read_format(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_verb, ast_waitfor(), ast_channel::caller, DEFAULT_SAMPLES_PER_MS, f, ast_party_redirecting::from, LOG_WARNING, ast_channel::name, ast_party_id::number, parse(), pbx_builtin_setvar_helper(), ast_channel::readformat, ast_channel::redirecting, S_COR, STATE_IN_SILENCE, STATE_IN_WORD, ast_party_number::str, and ast_party_number::valid.

Referenced by amd_exec().

00150 {
00151    int res = 0;
00152    struct ast_frame *f = NULL;
00153    struct ast_dsp *silenceDetector = NULL;
00154    int dspsilence = 0, readFormat, framelength = 0;
00155    int inInitialSilence = 1;
00156    int inGreeting = 0;
00157    int voiceDuration = 0;
00158    int silenceDuration = 0;
00159    int iTotalTime = 0;
00160    int iWordsCount = 0;
00161    int currentState = STATE_IN_WORD;
00162    int consecutiveVoiceDuration = 0;
00163    char amdCause[256] = "", amdStatus[256] = "";
00164    char *parse = ast_strdupa(data);
00165 
00166    /* Lets set the initial values of the variables that will control the algorithm.
00167       The initial values are the default ones. If they are passed as arguments
00168       when invoking the application, then the default values will be overwritten
00169       by the ones passed as parameters. */
00170    int initialSilence       = dfltInitialSilence;
00171    int greeting             = dfltGreeting;
00172    int afterGreetingSilence = dfltAfterGreetingSilence;
00173    int totalAnalysisTime    = dfltTotalAnalysisTime;
00174    int minimumWordLength    = dfltMinimumWordLength;
00175    int betweenWordsSilence  = dfltBetweenWordsSilence;
00176    int maximumNumberOfWords = dfltMaximumNumberOfWords;
00177    int silenceThreshold     = dfltSilenceThreshold;
00178    int maximumWordLength    = dfltMaximumWordLength;
00179    int maxWaitTimeForFrame  = dfltMaxWaitTimeForFrame;
00180 
00181    AST_DECLARE_APP_ARGS(args,
00182       AST_APP_ARG(argInitialSilence);
00183       AST_APP_ARG(argGreeting);
00184       AST_APP_ARG(argAfterGreetingSilence);
00185       AST_APP_ARG(argTotalAnalysisTime);
00186       AST_APP_ARG(argMinimumWordLength);
00187       AST_APP_ARG(argBetweenWordsSilence);
00188       AST_APP_ARG(argMaximumNumberOfWords);
00189       AST_APP_ARG(argSilenceThreshold);
00190       AST_APP_ARG(argMaximumWordLength);
00191    );
00192 
00193    ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", chan->name,
00194       S_COR(chan->caller.ani.number.valid, chan->caller.ani.number.str, "(N/A)"),
00195       S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "(N/A)"),
00196       ast_getformatname(chan->readformat));
00197 
00198    /* Lets parse the arguments. */
00199    if (!ast_strlen_zero(parse)) {
00200       /* Some arguments have been passed. Lets parse them and overwrite the defaults. */
00201       AST_STANDARD_APP_ARGS(args, parse);
00202       if (!ast_strlen_zero(args.argInitialSilence))
00203          initialSilence = atoi(args.argInitialSilence);
00204       if (!ast_strlen_zero(args.argGreeting))
00205          greeting = atoi(args.argGreeting);
00206       if (!ast_strlen_zero(args.argAfterGreetingSilence))
00207          afterGreetingSilence = atoi(args.argAfterGreetingSilence);
00208       if (!ast_strlen_zero(args.argTotalAnalysisTime))
00209          totalAnalysisTime = atoi(args.argTotalAnalysisTime);
00210       if (!ast_strlen_zero(args.argMinimumWordLength))
00211          minimumWordLength = atoi(args.argMinimumWordLength);
00212       if (!ast_strlen_zero(args.argBetweenWordsSilence))
00213          betweenWordsSilence = atoi(args.argBetweenWordsSilence);
00214       if (!ast_strlen_zero(args.argMaximumNumberOfWords))
00215          maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
00216       if (!ast_strlen_zero(args.argSilenceThreshold))
00217          silenceThreshold = atoi(args.argSilenceThreshold);
00218       if (!ast_strlen_zero(args.argMaximumWordLength))
00219          maximumWordLength = atoi(args.argMaximumWordLength);
00220    } else {
00221       ast_debug(1, "AMD using the default parameters.\n");
00222    }
00223 
00224    /* Find lowest ms value, that will be max wait time for a frame */
00225    if (maxWaitTimeForFrame > initialSilence)
00226       maxWaitTimeForFrame = initialSilence;
00227    if (maxWaitTimeForFrame > greeting)
00228       maxWaitTimeForFrame = greeting;
00229    if (maxWaitTimeForFrame > afterGreetingSilence)
00230       maxWaitTimeForFrame = afterGreetingSilence;
00231    if (maxWaitTimeForFrame > totalAnalysisTime)
00232       maxWaitTimeForFrame = totalAnalysisTime;
00233    if (maxWaitTimeForFrame > minimumWordLength)
00234       maxWaitTimeForFrame = minimumWordLength;
00235    if (maxWaitTimeForFrame > betweenWordsSilence)
00236       maxWaitTimeForFrame = betweenWordsSilence;
00237 
00238    /* Now we're ready to roll! */
00239    ast_verb(3, "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
00240       "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d] \n",
00241             initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
00242             minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength);
00243 
00244    /* Set read format to signed linear so we get signed linear frames in */
00245    readFormat = chan->readformat;
00246    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0 ) {
00247       ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", chan->name );
00248       pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
00249       pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
00250       return;
00251    }
00252 
00253    /* Create a new DSP that will detect the silence */
00254    if (!(silenceDetector = ast_dsp_new())) {
00255       ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to create silence detector :(\n", chan->name );
00256       pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
00257       pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
00258       return;
00259    }
00260 
00261    /* Set silence threshold to specified value */
00262    ast_dsp_set_threshold(silenceDetector, silenceThreshold);
00263 
00264    /* Now we go into a loop waiting for frames from the channel */
00265    while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
00266 
00267       /* If we fail to read in a frame, that means they hung up */
00268       if (!(f = ast_read(chan))) {
00269          ast_verb(3, "AMD: Channel [%s]. HANGUP\n", chan->name);
00270          ast_debug(1, "Got hangup\n");
00271          strcpy(amdStatus, "HANGUP");
00272          res = 1;
00273          break;
00274       }
00275 
00276       if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
00277          /* If the total time exceeds the analysis time then give up as we are not too sure */
00278          if (f->frametype == AST_FRAME_VOICE) {
00279             framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
00280          } else {
00281             framelength = 2 * maxWaitTimeForFrame;
00282          }
00283 
00284          iTotalTime += framelength;
00285          if (iTotalTime >= totalAnalysisTime) {
00286             ast_verb(3, "AMD: Channel [%s]. Too long...\n", chan->name );
00287             ast_frfree(f);
00288             strcpy(amdStatus , "NOTSURE");
00289             sprintf(amdCause , "TOOLONG-%d", iTotalTime);
00290             break;
00291          }
00292 
00293          /* Feed the frame of audio into the silence detector and see if we get a result */
00294          if (f->frametype != AST_FRAME_VOICE)
00295             dspsilence += 2 * maxWaitTimeForFrame;
00296          else {
00297             dspsilence = 0;
00298             ast_dsp_silence(silenceDetector, f, &dspsilence);
00299          }
00300 
00301          if (dspsilence > 0) {
00302             silenceDuration = dspsilence;
00303             
00304             if (silenceDuration >= betweenWordsSilence) {
00305                if (currentState != STATE_IN_SILENCE ) {
00306                   ast_verb(3, "AMD: Channel [%s]. Changed state to STATE_IN_SILENCE\n", chan->name);
00307                }
00308                /* Find words less than word duration */
00309                if (consecutiveVoiceDuration < minimumWordLength && consecutiveVoiceDuration > 0){
00310                   ast_verb(3, "AMD: Channel [%s]. Short Word Duration: %d\n", chan->name, consecutiveVoiceDuration);
00311                }
00312                currentState  = STATE_IN_SILENCE;
00313                consecutiveVoiceDuration = 0;
00314             }
00315 
00316             if (inInitialSilence == 1  && silenceDuration >= initialSilence) {
00317                ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
00318                   chan->name, silenceDuration, initialSilence);
00319                ast_frfree(f);
00320                strcpy(amdStatus , "MACHINE");
00321                sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence);
00322                res = 1;
00323                break;
00324             }
00325             
00326             if (silenceDuration >= afterGreetingSilence  &&  inGreeting == 1) {
00327                ast_verb(3, "AMD: Channel [%s]. HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
00328                   chan->name, silenceDuration, afterGreetingSilence);
00329                ast_frfree(f);
00330                strcpy(amdStatus , "HUMAN");
00331                sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence);
00332                res = 1;
00333                break;
00334             }
00335             
00336          } else {
00337             consecutiveVoiceDuration += framelength;
00338             voiceDuration += framelength;
00339 
00340             /* If I have enough consecutive voice to say that I am in a Word, I can only increment the
00341                number of words if my previous state was Silence, which means that I moved into a word. */
00342             if (consecutiveVoiceDuration >= minimumWordLength && currentState == STATE_IN_SILENCE) {
00343                iWordsCount++;
00344                ast_verb(3, "AMD: Channel [%s]. Word detected. iWordsCount:%d\n", chan->name, iWordsCount);
00345                currentState = STATE_IN_WORD;
00346             }
00347             if (consecutiveVoiceDuration >= maximumWordLength){
00348                ast_verb(3, "AMD: Channel [%s]. Maximum Word Length detected. [%d]\n", chan->name, consecutiveVoiceDuration);
00349                ast_frfree(f);
00350                strcpy(amdStatus , "MACHINE");
00351                sprintf(amdCause , "MAXWORDLENGTH-%d", consecutiveVoiceDuration);
00352                break;
00353             }
00354             if (iWordsCount >= maximumNumberOfWords) {
00355                ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: iWordsCount:%d\n", chan->name, iWordsCount);
00356                ast_frfree(f);
00357                strcpy(amdStatus , "MACHINE");
00358                sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords);
00359                res = 1;
00360                break;
00361             }
00362 
00363             if (inGreeting == 1 && voiceDuration >= greeting) {
00364                ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", chan->name, voiceDuration, greeting);
00365                ast_frfree(f);
00366                strcpy(amdStatus , "MACHINE");
00367                sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting);
00368                res = 1;
00369                break;
00370             }
00371 
00372             if (voiceDuration >= minimumWordLength ) {
00373                if (silenceDuration > 0)
00374                   ast_verb(3, "AMD: Channel [%s]. Detected Talk, previous silence duration: %d\n", chan->name, silenceDuration);
00375                silenceDuration = 0;
00376             }
00377             if (consecutiveVoiceDuration >= minimumWordLength && inGreeting == 0) {
00378                /* Only go in here once to change the greeting flag when we detect the 1st word */
00379                if (silenceDuration > 0)
00380                   ast_verb(3, "AMD: Channel [%s]. Before Greeting Time:  silenceDuration: %d voiceDuration: %d\n", chan->name, silenceDuration, voiceDuration);
00381                inInitialSilence = 0;
00382                inGreeting = 1;
00383             }
00384             
00385          }
00386       }
00387       ast_frfree(f);
00388    }
00389    
00390    if (!res) {
00391       /* It took too long to get a frame back. Giving up. */
00392       ast_verb(3, "AMD: Channel [%s]. Too long...\n", chan->name);
00393       strcpy(amdStatus , "NOTSURE");
00394       sprintf(amdCause , "TOOLONG-%d", iTotalTime);
00395    }
00396 
00397    /* Set the status and cause on the channel */
00398    pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus);
00399    pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
00400 
00401    /* Restore channel read format */
00402    if (readFormat && ast_set_read_format(chan, readFormat))
00403       ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name);
00404 
00405    /* Free the DSP used to detect silence */
00406    ast_dsp_free(silenceDetector);
00407 
00408    return;
00409 }

static int load_config ( int  reload  )  [static]

Definition at line 419 of file app_amd.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_dsp_get_threshold_from_settings(), ast_log(), ast_variable_browse(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, LOG_WARNING, THRESHOLD_SILENCE, and var.

00420 {
00421    struct ast_config *cfg = NULL;
00422    char *cat = NULL;
00423    struct ast_variable *var = NULL;
00424    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00425 
00426    dfltSilenceThreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
00427 
00428    if (!(cfg = ast_config_load("amd.conf", config_flags))) {
00429       ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
00430       return -1;
00431    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00432       return 0;
00433    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
00434       ast_log(LOG_ERROR, "Config file amd.conf is in an invalid format.  Aborting.\n");
00435       return -1;
00436    }
00437 
00438    cat = ast_category_browse(cfg, NULL);
00439 
00440    while (cat) {
00441       if (!strcasecmp(cat, "general") ) {
00442          var = ast_variable_browse(cfg, cat);
00443          while (var) {
00444             if (!strcasecmp(var->name, "initial_silence")) {
00445                dfltInitialSilence = atoi(var->value);
00446             } else if (!strcasecmp(var->name, "greeting")) {
00447                dfltGreeting = atoi(var->value);
00448             } else if (!strcasecmp(var->name, "after_greeting_silence")) {
00449                dfltAfterGreetingSilence = atoi(var->value);
00450             } else if (!strcasecmp(var->name, "silence_threshold")) {
00451                dfltSilenceThreshold = atoi(var->value);
00452             } else if (!strcasecmp(var->name, "total_analysis_time")) {
00453                dfltTotalAnalysisTime = atoi(var->value);
00454             } else if (!strcasecmp(var->name, "min_word_length")) {
00455                dfltMinimumWordLength = atoi(var->value);
00456             } else if (!strcasecmp(var->name, "between_words_silence")) {
00457                dfltBetweenWordsSilence = atoi(var->value);
00458             } else if (!strcasecmp(var->name, "maximum_number_of_words")) {
00459                dfltMaximumNumberOfWords = atoi(var->value);
00460             } else if (!strcasecmp(var->name, "maximum_word_length")) {
00461                dfltMaximumWordLength = atoi(var->value);
00462 
00463             } else {
00464                ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
00465                   app, cat, var->name, var->lineno);
00466             }
00467             var = var->next;
00468          }
00469       }
00470       cat = ast_category_browse(cfg, cat);
00471    }
00472 
00473    ast_config_destroy(cfg);
00474 
00475    ast_verb(3, "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
00476       "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d]\n",
00477       dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime,
00478       dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold, dfltMaximumWordLength);
00479 
00480    return 0;
00481 }

static int load_module ( void   )  [static]

Definition at line 488 of file app_amd.c.

References amd_exec(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, and load_config().

00489 {
00490    if (load_config(0))
00491       return AST_MODULE_LOAD_DECLINE;
00492    if (ast_register_application_xml(app, amd_exec))
00493       return AST_MODULE_LOAD_FAILURE;
00494    return AST_MODULE_LOAD_SUCCESS;
00495 }

static int reload ( void   )  [static]

Definition at line 497 of file app_amd.c.

References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and load_config().

00498 {
00499    if (load_config(1))
00500       return AST_MODULE_LOAD_DECLINE;
00501    return AST_MODULE_LOAD_SUCCESS;
00502 }

static int unload_module ( void   )  [static]

Definition at line 483 of file app_amd.c.

References ast_unregister_application().

00484 {
00485    return ast_unregister_application(app);
00486 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Answering Machine Detection Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 508 of file app_amd.c.

const char app[] = "AMD" [static]

Definition at line 130 of file app_amd.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 508 of file app_amd.c.

int dfltAfterGreetingSilence = 800 [static]

Definition at line 138 of file app_amd.c.

int dfltBetweenWordsSilence = 50 [static]

Definition at line 141 of file app_amd.c.

int dfltGreeting = 1500 [static]

Definition at line 137 of file app_amd.c.

int dfltInitialSilence = 2500 [static]

Definition at line 136 of file app_amd.c.

int dfltMaximumNumberOfWords = 3 [static]

Definition at line 142 of file app_amd.c.

int dfltMaximumWordLength = 5000 [static]

Definition at line 144 of file app_amd.c.

int dfltMaxWaitTimeForFrame = 50 [static]

Definition at line 147 of file app_amd.c.

int dfltMinimumWordLength = 100 [static]

Definition at line 140 of file app_amd.c.

int dfltSilenceThreshold = 256 [static]

Definition at line 143 of file app_amd.c.

int dfltTotalAnalysisTime = 5000 [static]

Definition at line 139 of file app_amd.c.


Generated on Mon Oct 8 12:39:07 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7