[asterisk-commits] file: trunk r42109 - /trunk/apps/app_amd.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Sep 6 10:05:49 MST 2006


Author: file
Date: Wed Sep  6 12:05:48 2006
New Revision: 42109

URL: http://svn.digium.com/view/asterisk?rev=42109&view=rev
Log:
Make this module fit the guidelines better

Modified:
    trunk/apps/app_amd.c

Modified: trunk/apps/app_amd.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_amd.c?rev=42109&r1=42108&r2=42109&view=diff
==============================================================================
--- trunk/apps/app_amd.c (original)
+++ trunk/apps/app_amd.c Wed Sep  6 12:05:48 2006
@@ -88,26 +88,21 @@
 
 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 @@
 	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 @@
 			     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)) {
+	if (!ast_strlen_zero(parse)) {
+		/* Some arguments have been passed. Lets parse them and overwrite the defaults. */
+		AST_STANDARD_APP_ARGS(args, parse);
+		if (!ast_strlen_zero(args.argInitialSilence))
+			initialSilence = atoi(args.argInitialSilence);
+		if (!ast_strlen_zero(args.argGreeting))
+			greeting = atoi(args.argGreeting);
+		if (!ast_strlen_zero(args.argAfterGreetingSilence))
+			afterGreetingSilence = atoi(args.argAfterGreetingSilence);
+		if (!ast_strlen_zero(args.argTotalAnalysisTime))
+			totalAnalysisTime = atoi(args.argTotalAnalysisTime);
+		if (!ast_strlen_zero(args.argMinimumWordLength))
+			minimumWordLength = atoi(args.argMinimumWordLength);
+		if (!ast_strlen_zero(args.argBetweenWordsSilence))
+			betweenWordsSilence = atoi(args.argBetweenWordsSilence);
+		if (!ast_strlen_zero(args.argMaximumNumberOfWords))
+			maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
+		if (!ast_strlen_zero(args.argSilenceThreshold))
+			silenceThreshold = atoi(args.argSilenceThreshold);
+	} else
 		ast_log(LOG_NOTICE, "AMD using the default parameters.\n");
-	} else {
-		/* 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)) {
-			initialSilence = atoi(args.argInitialSilence);
-		}
-		if (!ast_strlen_zero(args.argGreeting)) {
-			greeting = atoi(args.argGreeting);
-		}
-		if (!ast_strlen_zero(args.argAfterGreetingSilence)) {
-			afterGreetingSilence = atoi(args.argAfterGreetingSilence);
-		}
-		if (!ast_strlen_zero(args.argTotalAnalysisTime)) {
-			totalAnalysisTime = atoi(args.argTotalAnalysisTime);
-		}
-		if (!ast_strlen_zero(args.argMinimumWordLength)) {
-			minimumWordLength = atoi(args.argMinimumWordLength);
-		}
-		if (!ast_strlen_zero(args.argBetweenWordsSilence)) {
-			betweenWordsSilence = atoi(args.argBetweenWordsSilence);
-		}
-		if (!ast_strlen_zero(args.argMaximumNumberOfWords)) {
-			maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
-		}
-		if (!ast_strlen_zero(args.argSilenceThreshold)) {
-			silenceThreshold = atoi(args.argSilenceThreshold);
-		}
-	}
 
 	/* 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 @@
 					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;
-					}
-				}
-
-				if (iWordsCount >= maximumNumberOfWords ) {
-					if (option_verbose > 2)
-						ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount );
+				   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 (option_verbose > 2)
+						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 (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 );
+				
+				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);
 					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 );
-	}
-
-	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);
-	}
-
-	/* Free The Silence Detector DSP */
-	ast_dsp_free(silenceDetector );
+			ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name);
+		strcpy(amdStatus , "NOTSURE");
+		sprintf(amdCause , "TOOLONG-%d", iTotalTime);
+	}
+
+	/* Set the status and cause on the channel */
+	pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus);
+	pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
+
+	/* 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 DSP used to detect silence */
+	ast_dsp_free(silenceDetector);
 
 	return;
 }
@@ -321,7 +310,7 @@
 
 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 void load_config(void)
 {
-	struct ast_config *cfg;
-	char *cat;
-	struct ast_variable *var;
-
-	cfg = ast_config_load("amd.conf");
-
-	if (!cfg) {
+	struct ast_config *cfg = NULL;
+	char *cat = NULL;
+	struct ast_variable *var = NULL;
+
+	if (!(cfg = ast_config_load("amd.conf"))) {
 		ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
 		return;
 	}
@@ -374,6 +361,7 @@
 		}
 		cat = ast_category_browse(cfg, cat);
 	}
+
 	ast_config_destroy(cfg);
 
 	if (option_verbose > 2)



More information about the asterisk-commits mailing list