Index: apps/app_meetme.c =================================================================== --- apps/app_meetme.c (revision 98514) +++ apps/app_meetme.c (working copy) @@ -1531,10 +1531,13 @@ struct timeval nexteventts = { 0, }; int to; int setusercount = 0; + int silencethreshold; if (!(user = ast_calloc(1, sizeof(*user)))) return ret; + silencethreshold = ast_dsp_get_threshold_from_settings(); + /* Possible timeout waiting for marked user */ if ((confflags & CONFFLAG_WAITMARKED) && !ast_strlen_zero(optargs[OPT_ARG_WAITMARKED]) && @@ -1699,7 +1702,7 @@ "%s/meetme/meetme-username-%s-%d", ast_config_AST_SPOOL_DIR, conf->confno, user->user_no); if (confflags & CONFFLAG_INTROUSERNOREVIEW) - res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, 128, 0, NULL); + res = ast_play_and_record(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, silencethreshold, 0, NULL); else res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); if (res == -1) Index: apps/app_minivm.c =================================================================== --- apps/app_minivm.c (revision 98514) +++ apps/app_minivm.c (working copy) @@ -2362,7 +2362,6 @@ /* First, set some default settings */ global_externnotify[0] = '\0'; global_logfile[0] = '\0'; - global_silencethreshold = 256; global_vmmaxmessage = 2000; global_maxgreet = 2000; global_vmminmessage = 0; @@ -2377,6 +2376,8 @@ memset(&global_stats, 0, sizeof(global_stats)); global_stats.reset = ast_tvnow(); + global_silencethreshold = ast_dsp_get_threshold_from_settings(); + /* Make sure we could load configuration file */ if (!cfg) { ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n"); Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 98514) +++ apps/app_voicemail.c (working copy) @@ -8296,7 +8296,7 @@ } /* Silence treshold */ - silencethreshold = 256; + silencethreshold = ast_dsp_get_threshold_from_settings(); if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold"))) silencethreshold = atoi(val); Index: apps/app_dial.c =================================================================== --- apps/app_dial.c (revision 98514) +++ apps/app_dial.c (working copy) @@ -55,6 +55,7 @@ #include "asterisk/privacy.h" #include "asterisk/stringfields.h" #include "asterisk/global_datastores.h" +#include "asterisk/dsp.h" static char *app = "Dial"; @@ -1116,6 +1117,7 @@ char callerid[60]; int res; char *l; + int silencethreshold; if (!ast_strlen_zero(chan->cid.cid_num)) { l = ast_strdupa(chan->cid.cid_num); @@ -1189,8 +1191,9 @@ "At the tone, please say your name:" */ + silencethreshold = ast_dsp_get_threshold_from_settings(); ast_answer(chan); - res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "gsm", &duration, 128, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */ + res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "gsm", &duration, silencethreshold, 2000, 0); /* NOTE: I've reduced the total time to 4 sec */ /* don't think we'll need a lock removed, we took care of conflicts by naming the pa.privintro file */ if (res == -1) { Index: apps/app_waitforsilence.c =================================================================== --- apps/app_waitforsilence.c (revision 98514) +++ apps/app_waitforsilence.c (working copy) @@ -29,6 +29,12 @@ * * \author David C. Troy * + * \brief Wait For Noise + * The same as Wait For Silence but listenes noise on the chennel that is above \n + * the pre-configured silence threshold from dsp.conf + * + * \author Philipp Skadorov + * * \ingroup applications */ @@ -42,9 +48,9 @@ #include "asterisk/dsp.h" #include "asterisk/module.h" -static char *app = "WaitForSilence"; -static char *synopsis = "Waits for a specified amount of silence"; -static char *descrip = +static char *app_silence = "WaitForSilence"; +static char *synopsis_silence = "Waits for a specified amount of silence"; +static char *descrip_silence = " WaitForSilence(silencerequired[,iterations][,timeout]):\n" "Wait for Silence: Waits for up to 'silencerequired' \n" "milliseconds of silence, 'iterations' times or once if omitted.\n" @@ -68,15 +74,27 @@ "SILENCE - if exited with silence detected\n" "TIMEOUT - if exited without silence detected after timeout\n"; -static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstart, int timeout) { +static char *app_noise = "WaitForNoise"; +static char *synopsis_noise = "Waits for a specified amount of noise"; +static char *descrip_noise = +"WaitForNoise(noiserequired[,iterations][,timeout]) \n" +"Wait for Noise: The same as Wait for Silance but waits for noise that is above the threshold specified\n"; + +static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) { struct ast_frame *f; - int dspsilence = 0; - static int silencethreshold = 128; + int dsptime = 0; int rfmt = 0; int res = 0; struct ast_dsp *sildet; /* silence detector dsp */ time_t now; + const char * format_string = ""; + int silencethreshold; + + /*Either silence or noise calc depending on wait_for_silence flag*/ + int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) = + wait_for_silence ? ast_dsp_silence : ast_dsp_noise; + rfmt = chan->readformat; /* Set to linear mode */ res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); if (res < 0) { @@ -89,15 +107,16 @@ ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } + silencethreshold = ast_dsp_get_threshold_from_settings(); ast_dsp_set_threshold(sildet, silencethreshold); /* Await silence... */ f = NULL; for(;;) { /* Start with no silence received */ - dspsilence = 0; + dsptime = 0; - res = ast_waitfor(chan, silencereqd); + res = ast_waitfor(chan, timereqd); /* Must have gotten a hangup; let's exit */ if (res <= 0) { @@ -107,32 +126,47 @@ /* We waited and got no frame; sounds like digital silence or a muted digital channel */ if (!res) { - dspsilence = silencereqd; + dsptime = timereqd; } else { /* Looks like we did get a frame, so let's check it out */ f = ast_read(chan); if (!f) break; if (f && f->frametype == AST_FRAME_VOICE) { - ast_dsp_silence(sildet, f, &dspsilence); + ast_dsp_func(sildet, f, &dsptime); ast_frfree(f); } } - ast_verb(3, "Got %dms silence< %dms required\n", dspsilence, silencereqd); + if (option_verbose > 6) { + format_string = wait_for_silence? + VERBOSE_PREFIX_3 "Got %dms silence silence < %dms required\n": + VERBOSE_PREFIX_3 "Got %dms silence noise < %dms required\n"; - if (dspsilence >= silencereqd) { - ast_verb(3, "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd); + ast_verbose(format_string, dsptime, timereqd); + } + if (dsptime >= timereqd) { + if (option_verbose > 2) { + format_string = wait_for_silence? + VERBOSE_PREFIX_3 "Exiting with %dms silence >= %dms required\n" : + VERBOSE_PREFIX_3 "Exiting with %dms silence >= %dms required\n"; + ast_verbose(format_string, dsptime, timereqd); + } /* Ended happily with silence */ res = 1; - pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE"); - ast_debug(1, "WAITSTATUS was set to SILENCE\n"); + pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE"); + if(wait_for_silence) { + ast_log(LOG_DEBUG, "WAITSTATUS was set to SILENCE\n"); + } + else { + ast_log(LOG_DEBUG, "WAITSTATUS was set to NOISE\n"); + } break; } if ( timeout && (difftime(time(&now),waitstart) >= timeout) ) { pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT"); - ast_debug(1, "WAITSTATUS was set to TIMEOUT\n"); + ast_log(LOG_DEBUG, "WAITSTATUS was set to TIMEOUT\n"); res = 0; break; } @@ -146,43 +180,61 @@ return res; } -static int waitforsilence_exec(struct ast_channel *chan, void *data) +static int waitfor_exec(struct ast_channel *chan, void *data, int wait_for_silence) { int res = 1; - int silencereqd = 1000; + int timereqd = 1000; int timeout = 0; int iterations = 1, i; time_t waitstart; res = ast_answer(chan); /* Answer the channel */ - if (!data || ( (sscanf(data, "%d,%d,%d", &silencereqd, &iterations, &timeout) != 3) && - (sscanf(data, "%d|%d", &silencereqd, &iterations) != 2) && - (sscanf(data, "%d", &silencereqd) != 1) ) ) { + if (!data || ( (sscanf(data, "%d,%d,%d", &timereqd, &iterations, &timeout) != 3) && + (sscanf(data, "%d,%d", &timereqd, &iterations) != 2) && + (sscanf(data, "%d", &timereqd) != 1) ) ) { ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n"); } - ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, silencereqd, timeout); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout); time(&waitstart); res = 1; for (i=0; (i 0) res = 0; return res; } +static int waitforsilence_exec(struct ast_channel *chan, void *data) +{ + return waitfor_exec(chan, data, 1); +} +static int waitfornoise_exec(struct ast_channel *chan, void *data) +{ + return waitfor_exec(chan, data, 0); +} + static int unload_module(void) { - return ast_unregister_application(app); + int res; + res = ast_unregister_application(app_silence); + res |= ast_unregister_application(app_noise); + + return res; } static int load_module(void) { - return ast_register_application(app, waitforsilence_exec, synopsis, descrip); + int res; + + res = ast_register_application(app_silence, waitforsilence_exec, synopsis_silence, descrip_silence); + res |= ast_register_application(app_noise, waitfornoise_exec, synopsis_noise, descrip_noise); + return res; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Wait For Silence"); Index: apps/app_amd.c =================================================================== --- apps/app_amd.c (revision 98514) +++ apps/app_amd.c (working copy) @@ -339,6 +339,8 @@ struct ast_variable *var = NULL; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + dfltSilenceThreshold = ast_dsp_get_threshold_from_settings(); + if (!(cfg = ast_config_load("amd.conf", config_flags))) { ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n"); return -1; Index: apps/app_record.c =================================================================== --- apps/app_record.c (revision 98514) +++ apps/app_record.c (working copy) @@ -107,6 +107,7 @@ int rfmt = 0; int ioflags; int waitres; + int silencethreshold; struct ast_silence_generator *silgen = NULL; struct ast_flags flags = { 0, }; AST_DECLARE_APP_ARGS(args, @@ -243,7 +244,8 @@ ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } - ast_dsp_set_threshold(sildet, 256); + silencethreshold = ast_dsp_get_threshold_from_settings(); + ast_dsp_set_threshold(sildet, silencethreshold); } /* Create the directory if it does not exist. */ Index: apps/app_followme.c =================================================================== --- apps/app_followme.c (revision 98514) +++ apps/app_followme.c (working copy) @@ -51,6 +51,7 @@ #include "asterisk/utils.h" #include "asterisk/causes.h" #include "asterisk/astdb.h" +#include "asterisk/dsp.h" #include "asterisk/app.h" static char *app = "FollowMe"; @@ -882,9 +883,12 @@ char *argstr; char namerecloc[255]; int duration = 0; + int silencethreshold; struct ast_channel *caller; struct ast_channel *outbound; static char toast[80]; + + silencethreshold = ast_dsp_get_threshold_from_settings(); AST_DECLARE_APP_ARGS(args, AST_APP_ARG(followmeid); @@ -954,7 +958,7 @@ duration = 5; if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_RECORDNAME)) - if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, 128, 0, NULL) < 0) + if (ast_play_and_record(chan, "vm-rec-name", namerecloc, 5, "sln", &duration, silencethreshold, 0, NULL) < 0) goto outrun; if (!ast_fileexists(namerecloc, NULL, chan->language)) Index: include/asterisk/dsp.h =================================================================== --- include/asterisk/dsp.h (revision 98514) +++ include/asterisk/dsp.h (working copy) @@ -80,6 +80,10 @@ number of seconds of silence */ int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence); +/*! \brief Return non-zero if this is noise. Updates "totalnoise" with the total + number of seconds of noise */ +int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise); + /*! \brief Return non-zero if historically this should be a busy, request that ast_dsp_silence has already been called */ int ast_dsp_busydetect(struct ast_dsp *dsp); @@ -108,4 +112,10 @@ /*! \brief Get tcount (Threshold counter) */ int ast_dsp_get_tcount(struct ast_dsp *dsp); +/*! \brief Get silence threshold from dsp.conf*/ +int ast_dsp_get_threshold_from_settings(void); + +/* \brief Reloads dsp settings from dsp.conf*/ +int ast_dsp_reload(void); + #endif /* _ASTERISK_DSP_H */ Index: main/loader.c =================================================================== --- main/loader.c (revision 98514) +++ main/loader.c (working copy) @@ -46,6 +46,7 @@ #include "asterisk/rtp.h" #include "asterisk/http.h" #include "asterisk/lock.h" +#include "asterisk/dsp.h" #ifdef DLFCNCOMPAT #include "asterisk/dlfcn-compat.h" @@ -247,6 +248,7 @@ { "rtp", ast_rtp_reload }, { "http", ast_http_reload }, { "logger", logger_reload }, + { "dsp", ast_dsp_reload}, { NULL, NULL } }; Index: main/app.c =================================================================== --- main/app.c (revision 98514) +++ main/app.c (working copy) @@ -1268,7 +1268,7 @@ int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path) { - int silencethreshold = 128; + int silencethreshold; int maxsilence = 0; int res = 0; int cmd = 0; @@ -1286,6 +1286,8 @@ cmd = '3'; /* Want to start by recording */ + silencethreshold = ast_dsp_get_threshold_from_settings(); + while ((cmd >= 0) && (cmd != 't')) { switch (cmd) { case '1': Index: main/dsp.c =================================================================== --- main/dsp.c (revision 98514) +++ main/dsp.c (working copy) @@ -52,6 +52,7 @@ #include "asterisk/ulaw.h" #include "asterisk/alaw.h" #include "asterisk/utils.h" +#include "asterisk/config.h" /*! Number of goertzels for progress detect */ enum gsamp_size { @@ -166,6 +167,8 @@ #define BUSYDETECT_MARTIN #endif +#define CONFIG_FILE_NAME "dsp.conf" + typedef struct { int v2; int v3; @@ -847,7 +850,7 @@ return __ast_dsp_call_progress(dsp, inf->data, inf->datalen / 2); } -static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totalsilence) +static int __ast_dsp_silence_noise(struct ast_dsp *dsp, short *s, int len, int *totalsilence, int *totalnoise) { int accum; int x; @@ -899,6 +902,8 @@ } if (totalsilence) *totalsilence = dsp->totalsilence; + if (totalnoise) + *totalnoise = dsp->totalnoise; return res; } @@ -1053,9 +1058,28 @@ } s = f->data; len = f->datalen/2; - return __ast_dsp_silence(dsp, s, len, totalsilence); + return __ast_dsp_silence_noise(dsp, s, len, totalsilence, NULL); } +int ast_dsp_noise(struct ast_dsp *dsp, struct ast_frame *f, int *totalnoise) +{ + short *s; + int len; + + if (f->frametype != AST_FRAME_VOICE) { + ast_log(LOG_WARNING, "Can't calculate noise on a non-voice frame\n"); + return 0; + } + if (f->subclass != AST_FORMAT_SLINEAR) { + ast_log(LOG_WARNING, "Can only calculate noise on signed-linear frames :(\n"); + return 0; + } + s = f->data; + len = f->datalen/2; + return __ast_dsp_silence_noise(dsp, s, len, NULL, totalnoise); +} + + struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *af) { int silence; @@ -1110,7 +1134,7 @@ ast_log(LOG_WARNING, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(af->subclass)); return af; } - silence = __ast_dsp_silence(dsp, shortdata, len, NULL); + res = __ast_dsp_silence_noise(dsp, shortdata, len, &silence, NULL); if ((dsp->features & DSP_FEATURE_SILENCE_SUPPRESS) && silence) { memset(&dsp->f, 0, sizeof(dsp->f)); dsp->f.frametype = AST_FRAME_NULL; @@ -1394,3 +1418,43 @@ { return dsp->tcount; } + +static int threshold = -1; + +int ast_dsp_get_threshold_from_settings() +{ + const int default_threshold = 256; + + struct ast_flags config_flags = { 0 }; + struct ast_config *cfg; + struct ast_variable *var; + + if(-1 == threshold) { + threshold = default_threshold; + cfg = ast_config_load(CONFIG_FILE_NAME, config_flags); + + if (!cfg) { + ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); + } + else { + for (var = ast_variable_browse(cfg, "default"); var; var = var->next) { + if (!strcasecmp(var->name, "silencethreshold")){ + if(sscanf(var->value, "%d", &threshold) != 1) { + ast_log(LOG_WARNING, "Error processing file %s :(\n", CONFIG_FILE_NAME); + threshold = default_threshold; + } + break; + } + } + } + } + return threshold; +} + +int ast_dsp_reload(void) +{ + threshold = -1; + ast_dsp_get_threshold_from_settings(); + + return 0; +} Index: res/res_agi.c =================================================================== --- res/res_agi.c (revision 98514) +++ res/res_agi.c (working copy) @@ -1255,7 +1255,9 @@ char *silencestr=NULL; int rfmt=0; + int silencethreshold; + /* XXX EAGI FIXME XXX */ if (argc < 6) @@ -1295,7 +1297,8 @@ ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } - ast_dsp_set_threshold(sildet, 256); + silencethreshold = ast_dsp_get_threshold_from_settings(); + ast_dsp_set_threshold(sildet, silencethreshold); } /* backward compatibility, if no offset given, arg[6] would have been