diff options
author | Joshua Colp <jcolp@digium.com> | 2006-09-06 17:05:48 +0000 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2006-09-06 17:05:48 +0000 |
commit | ca2b4d407a5fdbed1c17a02cdcfce38cdb52fd5b (patch) | |
tree | 9fbddf43f60f987864a88452a846a8dbbbe4d09f /apps/app_amd.c | |
parent | e77c51f5c69702df5a0dc3cc754f3debc28e5846 (diff) |
Make this module fit the guidelines better
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@42109 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_amd.c')
-rw-r--r-- | apps/app_amd.c | 218 |
1 files changed, 103 insertions, 115 deletions
diff --git a/apps/app_amd.c b/apps/app_amd.c index 2f7148b9c..21e9b90fa 100644 --- a/apps/app_amd.c +++ b/apps/app_amd.c @@ -88,26 +88,21 @@ static int dfltSilenceThreshold = 256; static void isAnsweringMachine(struct ast_channel *chan, void *data) { - int res = 0, ret = 0; - + int res = 0; struct ast_frame *f = NULL; - - struct ast_dsp *silenceDetector; /* silence detector dsp */ - int dspsilence = 0; - int readFormat; - int framelength; - - int inInitialSilence = 1; - int inGreeting = 0; - int voiceDuration = 0; - int silenceDuration = 0; - int iTotalTime = 0; - int iWordsCount = 0; - int currentState = STATE_IN_SILENCE; - int previousState = STATE_IN_SILENCE; + struct ast_dsp *silenceDetector = NULL; + int dspsilence = 0, readFormat, framelength; + int inInitialSilence = 1; + int inGreeting = 0; + int voiceDuration = 0; + int silenceDuration = 0; + int iTotalTime = 0; + int iWordsCount = 0; + int currentState = STATE_IN_SILENCE; + int previousState = STATE_IN_SILENCE; int consecutiveVoiceDuration = 0; - char amdCause[256] = ""; - char amdStatus[256] = ""; + char amdCause[256] = "", amdStatus[256] = ""; + char *parse = ast_strdupa(data); /* Lets set the initial values of the variables that will control the algorithm. The initial values are the default ones. If they are passed as arguments @@ -122,7 +117,6 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) int maximumNumberOfWords = dfltMaximumNumberOfWords; int silenceThreshold = dfltSilenceThreshold; - char *parse; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(argInitialSilence); AST_APP_ARG(argGreeting); @@ -133,98 +127,92 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) AST_APP_ARG(argMaximumNumberOfWords); AST_APP_ARG(argSilenceThreshold); ); + if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat); /* Lets parse the arguments. */ - if (ast_strlen_zero(data)) { - ast_log(LOG_NOTICE, "AMD using the default parameters.\n"); - } else { + if (!ast_strlen_zero(parse)) { /* Some arguments have been passed. Lets parse them and overwrite the defaults. */ - parse = ast_strdupa(data); - AST_STANDARD_APP_ARGS(args, parse); - - if (!ast_strlen_zero(args.argInitialSilence)) { + if (!ast_strlen_zero(args.argInitialSilence)) initialSilence = atoi(args.argInitialSilence); - } - if (!ast_strlen_zero(args.argGreeting)) { + if (!ast_strlen_zero(args.argGreeting)) greeting = atoi(args.argGreeting); - } - if (!ast_strlen_zero(args.argAfterGreetingSilence)) { + if (!ast_strlen_zero(args.argAfterGreetingSilence)) afterGreetingSilence = atoi(args.argAfterGreetingSilence); - } - if (!ast_strlen_zero(args.argTotalAnalysisTime)) { + if (!ast_strlen_zero(args.argTotalAnalysisTime)) totalAnalysisTime = atoi(args.argTotalAnalysisTime); - } - if (!ast_strlen_zero(args.argMinimumWordLength)) { + if (!ast_strlen_zero(args.argMinimumWordLength)) minimumWordLength = atoi(args.argMinimumWordLength); - } - if (!ast_strlen_zero(args.argBetweenWordsSilence)) { + if (!ast_strlen_zero(args.argBetweenWordsSilence)) betweenWordsSilence = atoi(args.argBetweenWordsSilence); - } - if (!ast_strlen_zero(args.argMaximumNumberOfWords)) { + if (!ast_strlen_zero(args.argMaximumNumberOfWords)) maximumNumberOfWords = atoi(args.argMaximumNumberOfWords); - } - if (!ast_strlen_zero(args.argSilenceThreshold)) { + if (!ast_strlen_zero(args.argSilenceThreshold)) silenceThreshold = atoi(args.argSilenceThreshold); - } - } + } else + ast_log(LOG_NOTICE, "AMD using the default parameters.\n"); /* Now we're ready to roll! */ - if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] " "totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n", initialSilence, greeting, afterGreetingSilence, totalAnalysisTime, minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold ); + /* Set read format to signed linear so we get signed linear frames in */ readFormat = chan->readformat; - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); - if (res < 0 ) { + if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0 ) { ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", chan->name ); - pbx_builtin_setvar_helper(chan , "AMDSTATUS" , "" ); - pbx_builtin_setvar_helper(chan , "AMDCAUSE" , "" ); + pbx_builtin_setvar_helper(chan , "AMDSTATUS", ""); + pbx_builtin_setvar_helper(chan , "AMDCAUSE", ""); return; } - silenceDetector = ast_dsp_new(); - if (!silenceDetector ) { + /* Create a new DSP that will detect the silence */ + if (!(silenceDetector = ast_dsp_new())) { ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to create silence detector :(\n", chan->name ); - pbx_builtin_setvar_helper(chan , "AMDSTATUS" , "" ); - pbx_builtin_setvar_helper(chan , "AMDCAUSE" , "" ); + pbx_builtin_setvar_helper(chan , "AMDSTATUS", ""); + pbx_builtin_setvar_helper(chan , "AMDCAUSE", ""); return; } - ast_dsp_set_threshold(silenceDetector, silenceThreshold ); - while ((ret = ast_waitfor(chan, totalAnalysisTime))) - { - if (ret < 0 || !(f = ast_read(chan))) { - /* No Frame OR Error on ast_waitfor : Called Party Must Have Dropped */ + /* Set silence threshold to specified value */ + ast_dsp_set_threshold(silenceDetector, silenceThreshold); + + /* Now we go into a loop waiting for frames from the channel */ + while ((res = ast_waitfor(chan, totalAnalysisTime)) > -1) { + /* If we fail to read in a frame, that means they hung up */ + if (!(f = ast_read(chan))) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n"); if (option_debug) ast_log(LOG_DEBUG, "Got hangup\n"); - strcpy(amdStatus , "HANGUP" ); - strcpy(amdCause , "" ); + strcpy(amdStatus, "HANGUP"); break; } - if (f->frametype == AST_FRAME_VOICE ) { + + if (f->frametype == AST_FRAME_VOICE) { + /* If the total time exceeds the analysis time then give up as we are not too sure */ framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS); iTotalTime += framelength; - if (iTotalTime >= totalAnalysisTime ) { + if (iTotalTime >= totalAnalysisTime) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name ); ast_frfree(f); - strcpy(amdStatus , "NOTSURE" ); - sprintf(amdCause , "TOOLONG-%d", iTotalTime ); + strcpy(amdStatus , "NOTSURE"); + sprintf(amdCause , "TOOLONG-%d", iTotalTime); break; } + + /* Feed the frame of audio into the silence detector and see if we get a result */ dspsilence = 0; ast_dsp_silence(silenceDetector, f, &dspsilence); - if (dspsilence ) { + if (dspsilence) { silenceDuration = dspsilence; - if (silenceDuration >= betweenWordsSilence ) { + + if (silenceDuration >= betweenWordsSilence) { if (currentState != STATE_IN_SILENCE ) { previousState = currentState; if (option_verbose > 2) @@ -233,87 +221,88 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) currentState = STATE_IN_SILENCE; consecutiveVoiceDuration = 0; } - if (inInitialSilence == 1 && silenceDuration >= initialSilence ) { + + if (inInitialSilence == 1 && silenceDuration >= initialSilence) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n", - silenceDuration, initialSilence ); + silenceDuration, initialSilence); ast_frfree(f); - strcpy(amdStatus , "MACHINE" ); - sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence ); + strcpy(amdStatus , "MACHINE"); + sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence); break; } - - if (silenceDuration >= afterGreetingSilence && inGreeting == 1 ) { + + if (silenceDuration >= afterGreetingSilence && inGreeting == 1) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n", - silenceDuration, afterGreetingSilence ); + silenceDuration, afterGreetingSilence); ast_frfree(f); - strcpy(amdStatus , "HUMAN" ); - sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence ); + strcpy(amdStatus , "HUMAN"); + sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence); break; } + } else { consecutiveVoiceDuration += framelength; voiceDuration += framelength; - + /* If I have enough consecutive voice to say that I am in a Word, I can only increment the - number of words if my previous state was Silence, which means that I moved into a word. */ - if (consecutiveVoiceDuration >= minimumWordLength ) { - if (currentState == STATE_IN_SILENCE ) { - iWordsCount++; - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount ); - previousState = currentState; - currentState = STATE_IN_WORD; - } + number of words if my previous state was Silence, which means that I moved into a word. */ + if (consecutiveVoiceDuration >= minimumWordLength && currentState == STATE_IN_SILENCE) { + iWordsCount++; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount); + previousState = currentState; + currentState = STATE_IN_WORD; } - - if (iWordsCount >= maximumNumberOfWords ) { + + if (iWordsCount >= maximumNumberOfWords) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount ); + ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount); ast_frfree(f); - strcpy(amdStatus , "MACHINE" ); - sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords ); + strcpy(amdStatus , "MACHINE"); + sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords); break; } - - if (inGreeting == 1 && voiceDuration >= greeting ) { + + if (inGreeting == 1 && voiceDuration >= greeting) { if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting); - ast_frfree(f); - strcpy(amdStatus , "MACHINE" ); - sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting ); + ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting); + ast_frfree(f); + strcpy(amdStatus , "MACHINE"); + sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting); break; } + if (voiceDuration >= minimumWordLength ) { silenceDuration = 0; inInitialSilence = 0; inGreeting = 1; } + } } ast_frfree(f); } - if (!ret) { + + if (!res) { /* It took too long to get a frame back. Giving up. */ if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name ); - strcpy(amdStatus , "NOTSURE" ); - sprintf(amdCause , "TOOLONG-%d", iTotalTime ); + ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name); + strcpy(amdStatus , "NOTSURE"); + sprintf(amdCause , "TOOLONG-%d", iTotalTime); } - pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus ); - pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause ); + /* Set the status and cause on the channel */ + pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus); + pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause); - /* If We Started With A Valid Read Format, Return To It... */ - if (readFormat && chan->_state == AST_STATE_UP) { - res = ast_set_read_format(chan, readFormat ); - if (res) - ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name); - } + /* Restore channel read format */ + if (readFormat && ast_set_read_format(chan, readFormat)) + ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name); - /* Free The Silence Detector DSP */ - ast_dsp_free(silenceDetector ); + /* Free the DSP used to detect silence */ + ast_dsp_free(silenceDetector); return; } @@ -321,7 +310,7 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data) static int amd_exec(struct ast_channel *chan, void *data) { - struct ast_module_user *u; + struct ast_module_user *u = NULL; u = ast_module_user_add(chan); isAnsweringMachine(chan, data); @@ -332,13 +321,11 @@ static int amd_exec(struct ast_channel *chan, void *data) static void load_config(void) { - struct ast_config *cfg; - char *cat; - struct ast_variable *var; + struct ast_config *cfg = NULL; + char *cat = NULL; + struct ast_variable *var = NULL; - cfg = ast_config_load("amd.conf"); - - if (!cfg) { + if (!(cfg = ast_config_load("amd.conf"))) { ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n"); return; } @@ -374,6 +361,7 @@ static void load_config(void) } cat = ast_category_browse(cfg, cat); } + ast_config_destroy(cfg); if (option_verbose > 2) |