dect
/
asterisk
Archived
13
0
Fork 0

Some changes to app_amd.

The channel name is printed in verbose messages
maximumWordLength option added.
Duration of words that do not meet the minimum word duration will be logged
The duration of pre-greeting silence will be logged
Only consider us in the greeting if we actually detected a valid word duration.

(closes issue #11650, reported and patched by davevg)



git-svn-id: http://svn.digium.com/svn/asterisk/trunk@95167 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
mmichelson 2007-12-28 16:12:06 +00:00
parent 02ba367421
commit a0cbc07523
2 changed files with 45 additions and 16 deletions

View File

@ -312,6 +312,8 @@ Other Dialplan Application Changes
of asking for verification of each name, one at a time.
* Privacy() no longer uses privacy.conf, as all options are specifyable as
direct options to the app.
* AMD() has a new "maximum word length" option. "show application AMD" from the CLI
for more details
Music On Hold Changes
---------------------

View File

@ -45,7 +45,7 @@ static char *synopsis = "Attempts to detect answering machines";
static char *descrip =
" AMD([initialSilence],[greeting],[afterGreetingSilence],[totalAnalysisTime]\n"
" ,[minimumWordLength],[betweenWordsSilence],[maximumNumberOfWords]\n"
" ,[silenceThreshold])\n"
" ,[silenceThreshold],[|maximumWordLength])\n"
" This application attempts to detect answering machines at the beginning\n"
" of outbound calls. Simply call this application after the call\n"
" has been answered (outbound only, of course).\n"
@ -65,6 +65,7 @@ static char *descrip =
"- 'maximumNumberOfWords'is the maximum number of words in the greeting. \n"
" If exceeded then MACHINE.\n"
"- 'silenceThreshold' is the silence threshold.\n"
"- 'maximumWordLength' is the maximum duration of a word to accept. If exceeded then MACHINE\n"
"This application sets the following channel variables upon completion:\n"
" AMDSTATUS - This is the status of the answering machine detection.\n"
" Possible values are:\n"
@ -75,7 +76,8 @@ static char *descrip =
" INITIALSILENCE-<%d silenceDuration>-<%d initialSilence>\n"
" HUMAN-<%d silenceDuration>-<%d afterGreetingSilence>\n"
" MAXWORDS-<%d wordsCount>-<%d maximumNumberOfWords>\n"
" LONGGREETING-<%d voiceDuration>-<%d greeting>\n";
" LONGGREETING-<%d voiceDuration>-<%d greeting>\n"
" MAXWORDLENGTH-<%d consecutiveVoiceDuration>\n";
#define STATE_IN_WORD 1
#define STATE_IN_SILENCE 2
@ -89,6 +91,7 @@ static int dfltMinimumWordLength = 100;
static int dfltBetweenWordsSilence = 50;
static int dfltMaximumNumberOfWords = 3;
static int dfltSilenceThreshold = 256;
static int dfltMaximumWordLength = 5000; /* Setting this to a large default so it is not used unless specify it in the configs or command line */
static void isAnsweringMachine(struct ast_channel *chan, void *data)
{
@ -120,6 +123,7 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
int betweenWordsSilence = dfltBetweenWordsSilence;
int maximumNumberOfWords = dfltMaximumNumberOfWords;
int silenceThreshold = dfltSilenceThreshold;
int maximumWordLength = dfltMaximumWordLength;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(argInitialSilence);
@ -130,6 +134,7 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
AST_APP_ARG(argBetweenWordsSilence);
AST_APP_ARG(argMaximumNumberOfWords);
AST_APP_ARG(argSilenceThreshold);
AST_APP_ARG(argMaximumWordLength);
);
ast_verb(3, "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat);
@ -154,15 +159,17 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
if (!ast_strlen_zero(args.argSilenceThreshold))
silenceThreshold = atoi(args.argSilenceThreshold);
if (!ast_strlen_zero(args.argMaximumWordLength))
maximumWordLength = atoi(args.argMaximumWordLength);
} else {
ast_debug(1, "AMD using the default parameters.\n");
}
/* Now we're ready to roll! */
ast_verb(3, "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d] \n",
initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold );
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength);
/* Set read format to signed linear so we get signed linear frames in */
readFormat = chan->readformat;
@ -188,7 +195,7 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
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))) {
ast_verb(3, "AMD: HANGUP\n");
ast_verb(3, "AMD: Channel [%s]. HANGUP\n", chan->name);
ast_debug(1, "Got hangup\n");
strcpy(amdStatus, "HANGUP");
break;
@ -215,15 +222,19 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
if (silenceDuration >= betweenWordsSilence) {
if (currentState != STATE_IN_SILENCE ) {
previousState = currentState;
ast_verb(3, "AMD: Changed state to STATE_IN_SILENCE\n");
ast_verb(3, "AMD: Channel [%s]. Changed state to STATE_IN_SILENCE\n", chan->name);
}
/* Find words less than word duration */
if (consecutiveVoiceDuration < minimumWordLength && consecutiveVoiceDuration > 0){
ast_verb(3, "AMD: Channel [%s]. Short Word Duration: %d\n", chan->name, consecutiveVoiceDuration);
}
currentState = STATE_IN_SILENCE;
consecutiveVoiceDuration = 0;
}
if (inInitialSilence == 1 && silenceDuration >= initialSilence) {
ast_verb(3, "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
silenceDuration, initialSilence);
ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
chan->name, silenceDuration, initialSilence);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence);
@ -231,8 +242,8 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
}
if (silenceDuration >= afterGreetingSilence && inGreeting == 1) {
ast_verb(3, "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
silenceDuration, afterGreetingSilence);
ast_verb(3, "AMD: Channel [%s]. HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
chan->name, silenceDuration, afterGreetingSilence);
ast_frfree(f);
strcpy(amdStatus , "HUMAN");
sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence);
@ -247,13 +258,19 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
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++;
ast_verb(3, "AMD: Word detected. iWordsCount:%d\n", iWordsCount);
ast_verb(3, "AMD: Channel [%s]. Word detected. iWordsCount:%d\n", chan->name, iWordsCount);
previousState = currentState;
currentState = STATE_IN_WORD;
}
if (consecutiveVoiceDuration >= maximumWordLength){
ast_verb(3, "AMD: Channel [%s]. Maximum Word Length detected. [%d]\n", chan->name, consecutiveVoiceDuration);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "MAXWORDLENGTH-%d", consecutiveVoiceDuration);
break;
}
if (iWordsCount >= maximumNumberOfWords) {
ast_verb(3, "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount);
ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: iWordsCount:%d\n", chan->name, iWordsCount);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords);
@ -261,7 +278,7 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
}
if (inGreeting == 1 && voiceDuration >= greeting) {
ast_verb(3, "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting);
ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", chan->name, voiceDuration, greeting);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting);
@ -269,7 +286,14 @@ static void isAnsweringMachine(struct ast_channel *chan, void *data)
}
if (voiceDuration >= minimumWordLength ) {
if (silenceDuration > 0)
ast_verb(3, "AMD: Channel [%s]. Detected Talk, previous silence duration: %d\n", chan->name, silenceDuration);
silenceDuration = 0;
}
if (consecutiveVoiceDuration >= minimumWordLength && inGreeting == 0){
/* Only go in here once to change the greeting flag when we detect the 1st word */
if (silenceDuration > 0)
ast_verb(3, "AMD: Channel [%s]. Before Greeting Time: silenceDuration: %d voiceDuration: %d\n", chan->name, silenceDuration, voiceDuration);
inInitialSilence = 0;
inGreeting = 1;
}
@ -343,6 +367,9 @@ static int load_config(int reload)
dfltBetweenWordsSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_number_of_words")) {
dfltMaximumNumberOfWords = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_word_length")) {
dfltMaximumWordLength = atoi(var->value);
} else {
ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
app, cat, var->name, var->lineno);
@ -356,9 +383,9 @@ static int load_config(int reload)
ast_config_destroy(cfg);
ast_verb(3, "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d]\n",
dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime,
dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold );
dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold, dfltMaximumWordLength);
return 0;
}