--- apps/app_amd.c.2007-03-08 2007-03-08 18:07:00.000000000 -0700 +++ apps/app_amd.c 2007-03-13 17:42:32.000000000 -0600 @@ -86,19 +86,22 @@ static int dfltMaximumNumberOfWords = 3; static int dfltSilenceThreshold = 256; +/* Set to the lowest ms value provided in amd.conf or application parameters */ +static int dfltMaxWaitTimeForFrame = 50; + static void isAnsweringMachine(struct ast_channel *chan, void *data) { int res = 0; struct ast_frame *f = NULL; struct ast_dsp *silenceDetector = NULL; - int dspsilence = 0, readFormat, framelength; + int dspsilence = 0, readFormat, framelength = 0; int inInitialSilence = 1; int inGreeting = 0; int voiceDuration = 0; int silenceDuration = 0; int iTotalTime = 0; int iWordsCount = 0; - int currentState = STATE_IN_SILENCE; + int currentState = STATE_IN_WORD; int previousState = STATE_IN_SILENCE; int consecutiveVoiceDuration = 0; char amdCause[256] = "", amdStatus[256] = ""; @@ -116,6 +119,7 @@ int betweenWordsSilence = dfltBetweenWordsSilence; int maximumNumberOfWords = dfltMaximumNumberOfWords; int silenceThreshold = dfltSilenceThreshold; + int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(argInitialSilence); @@ -154,6 +158,20 @@ } else if (option_debug) ast_log(LOG_DEBUG, "AMD using the default parameters.\n"); + /* Find lowest ms value, that will be max wait time for a frame */ + if (maxWaitTimeForFrame > initialSilence) + maxWaitTimeForFrame = initialSilence; + if (maxWaitTimeForFrame > greeting) + maxWaitTimeForFrame = greeting; + if (maxWaitTimeForFrame > afterGreetingSilence) + maxWaitTimeForFrame = afterGreetingSilence; + if (maxWaitTimeForFrame > totalAnalysisTime) + maxWaitTimeForFrame = totalAnalysisTime; + if (maxWaitTimeForFrame > minimumWordLength) + maxWaitTimeForFrame = minimumWordLength; + if (maxWaitTimeForFrame > betweenWordsSilence) + maxWaitTimeForFrame = betweenWordsSilence; + /* Now we're ready to roll! */ if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] " @@ -182,7 +200,8 @@ 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) { + while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) { + /* If we fail to read in a frame, that means they hung up */ if (!(f = ast_read(chan))) { if (option_verbose > 2) @@ -193,9 +212,13 @@ break; } - if (f->frametype == AST_FRAME_VOICE) { + if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) { /* 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); + if (f->frametype == AST_FRAME_VOICE) + framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS); + else + framelength += 2 * maxWaitTimeForFrame; + iTotalTime += framelength; if (iTotalTime >= totalAnalysisTime) { if (option_verbose > 2) @@ -207,9 +230,15 @@ } /* 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 (f->frametype != AST_FRAME_VOICE) + dspsilence += 2 * maxWaitTimeForFrame; + else + { + dspsilence = 0; + ast_dsp_silence(silenceDetector, f, &dspsilence); + } + + if (dspsilence > 0) { silenceDuration = dspsilence; if (silenceDuration >= betweenWordsSilence) { @@ -229,6 +258,7 @@ ast_frfree(f); strcpy(amdStatus , "MACHINE"); sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence); + res = 1; break; } @@ -239,6 +269,7 @@ ast_frfree(f); strcpy(amdStatus , "HUMAN"); sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence); + res = 1; break; } @@ -262,6 +293,7 @@ ast_frfree(f); strcpy(amdStatus , "MACHINE"); sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords); + res = 1; break; } @@ -271,6 +303,7 @@ ast_frfree(f); strcpy(amdStatus , "MACHINE"); sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting); + res = 1; break; }