Create a centralized configuration option for silencethreshold
authorTilghman Lesher <tilghman@meg.abyt.es>
Wed, 5 Mar 2008 16:23:44 +0000 (16:23 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Wed, 5 Mar 2008 16:23:44 +0000 (16:23 +0000)
(closes issue #11236)
 Reported by: philipps
 Patches:
       20080218__bug11236.diff.txt uploaded by Corydon76 (license 14)
 Tested by: philipps

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@106072 65c4cc65-6c06-0410-ace0-fbb531ad65f3

17 files changed:
CHANGES
UPGRADE.txt
apps/app_amd.c
apps/app_dial.c
apps/app_followme.c
apps/app_meetme.c
apps/app_minivm.c
apps/app_record.c
apps/app_voicemail.c
apps/app_waitforsilence.c
configs/dsp.conf.sample [new file with mode: 0644]
include/asterisk/dsp.h
main/app.c
main/asterisk.c
main/dsp.c
main/loader.c
res/res_agi.c

diff --git a/CHANGES b/CHANGES
index cf30113..5616708 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -175,7 +175,7 @@ Skinny changes
   * Proper codec support in chan_skinny.
   * Added settings for IP and Ethernet QoS requests
 
-
+MGCP changes
 ------------
   * Added separate settings for media QoS in mgcp.conf
 
@@ -387,6 +387,8 @@ Other Dialplan Application Changes
   * The ChannelRedirect application no longer exits the dialplan if the given channel
      does not exist. It will now set the CHANNELREDIRECT_STATUS variable to SUCCESS upon success
      or NOCHANNEL if the given channel was not found.
+  * The silencethreshold setting that was previously configurable in multiple
+     applications is now settable globally via dsp.conf.
 
 Music On Hold Changes
 ---------------------
index c860f4b..6fb2142 100644 (file)
@@ -56,6 +56,9 @@ Core:
 * The concise versions of various CLI commands are now deprecated. We recommend
   using the manager interface (AMI) for application integration with Asterisk.
 
+* The silencethreshold used for various applications is now settable via a
+  centralized config option in dsp.conf.
+
 Voicemail:
 
 * The voicemail configuration values 'maxmessage' and 'minmessage' have
index cb867ba..131cd01 100644 (file)
@@ -371,6 +371,8 @@ static int load_config(int reload)
        struct ast_variable *var = NULL;
        struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 
+       dfltSilenceThreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
+
        if (!(cfg = ast_config_load("amd.conf", config_flags))) {
                ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
                return -1;
index f93ba0d..5698c19 100644 (file)
@@ -60,6 +60,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/privacy.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/global_datastores.h"
+#include "asterisk/dsp.h"
 
 static char *app = "Dial";
 
@@ -1115,6 +1116,7 @@ static int setup_privacy_args(struct privacy_args *pa,
        char callerid[60];
        int res;
        char *l;
+       int silencethreshold;
 
        if (!ast_strlen_zero(chan->cid.cid_num)) {
                l = ast_strdupa(chan->cid.cid_num);
@@ -1188,8 +1190,9 @@ static int setup_privacy_args(struct privacy_args *pa,
                           "At the tone, please say your name:"
 
                        */
+                       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
                        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 c3c0d88..9dd130b 100644 (file)
@@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/causes.h"
 #include "asterisk/astdb.h"
+#include "asterisk/dsp.h"
 #include "asterisk/app.h"
 
 static char *app = "FollowMe";
@@ -130,7 +131,7 @@ struct findme_user {
        int ynidx; 
        long digts;
        int cleared;
-       AST_LIST_ENTRY(findme_user) entry;      
+       AST_LIST_ENTRY(findme_user) entry;
 };
 
 enum {
@@ -183,7 +184,6 @@ static void free_numbers(struct call_followme *f)
                /* Free the whitelisted number */
                ast_free(prev);
        AST_LIST_HEAD_INIT_NOLOCK(&f->wlnumbers);
-       
 }
 
 
@@ -258,7 +258,6 @@ static struct number *create_followme_number(char *number, int timeout, int numo
 {
        struct number *cur;
        char *tmp;
-       
 
        if (!(cur = ast_calloc(1, sizeof(*cur))))
                return NULL;
@@ -284,7 +283,7 @@ static int reload_followme(int reload)
        char numberstr[90];
        int timeout;
        char *timeoutstr;
-       int numorder;   
+       int numorder;
        const char *takecallstr;
        const char *declinecallstr;
        const char *tmpstr;
@@ -307,7 +306,7 @@ static int reload_followme(int reload)
        }
 
        featuredigittostr = ast_variable_retrieve(cfg, "general", "featuredigittimeout");
-       
+
        if (!ast_strlen_zero(featuredigittostr)) {
                if (!sscanf(featuredigittostr, "%d", &featuredigittimeout))
                        featuredigittimeout = 5000;
@@ -316,7 +315,7 @@ static int reload_followme(int reload)
        takecallstr = ast_variable_retrieve(cfg, "general", "takecall");
        if (!ast_strlen_zero(takecallstr))
                ast_copy_string(takecall, takecallstr, sizeof(takecall));
-       
+
        declinecallstr = ast_variable_retrieve(cfg, "general", "declinecall");
        if (!ast_strlen_zero(declinecallstr))
                ast_copy_string(nextindp, declinecallstr, sizeof(nextindp));
@@ -369,7 +368,7 @@ static int reload_followme(int reload)
                /* Totally fail if we fail to find/create an entry */
                if (!f)
                        continue;
-               
+
                if (!new)
                        ast_mutex_lock(&f->lock);
                /* Re-initialize the profile */
@@ -399,8 +398,8 @@ static int reload_followme(int reload)
                                        timeout = 25;
                                        numorder = 0;
                                }
-                               
-                               if (!numorder) {        
+
+                               if (!numorder) {
                                        idx = 1;
                                        AST_LIST_TRAVERSE(&f->numbers, nm, entry) 
                                                idx++;
@@ -414,7 +413,7 @@ static int reload_followme(int reload)
                        }
                        var = var->next;
                } /* End while(var) loop */
-               
+
                if (!new) 
                        ast_mutex_unlock(&f->lock);
                else
@@ -431,7 +430,7 @@ static int reload_followme(int reload)
 static void clear_caller(struct findme_user *tmpuser)
 {
        struct ast_channel *outbound;
-       
+
        if (tmpuser && tmpuser->ochan && tmpuser->state >= 0) {
                outbound = tmpuser->ochan;
                if (!outbound->cdr) {
@@ -460,12 +459,11 @@ static void clear_caller(struct findme_user *tmpuser)
 static void clear_calling_tree(struct findme_user_listptr *findme_user_list) 
 {
        struct findme_user *tmpuser;
-       
+
        AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
                clear_caller(tmpuser);
                tmpuser->cleared = 1;
        }
-       
 }
 
 
@@ -489,29 +487,29 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
        /* ------------ wait_for_winner_channel start --------------- */ 
 
        callfromname = ast_strdupa(tpargs->callfromprompt);
-       pressbuttonname = ast_strdupa(tpargs->optionsprompt);   
+       pressbuttonname = ast_strdupa(tpargs->optionsprompt);
 
        if (AST_LIST_EMPTY(findme_user_list)) {
                ast_verb(3, "couldn't reach at this number.\n");
                return NULL;
        }
-       
+
        if (!caller) {
                ast_verb(3, "Original caller hungup. Cleanup.\n");
                clear_calling_tree(findme_user_list);
                return NULL;
        }
-       
+
        totalwait = nm->timeout * 1000;
-       
+
        while (!ctstatus) {
                to = 1000;
                pos = 1; 
                livechannels = 0;
                watchers[0] = caller;
-               
-               dg = 0; 
-               winner = NULL;  
+
+               dg = 0;
+               winner = NULL;
                AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
                        if (tmpuser->state >= 0 && tmpuser->ochan) {
                                if (tmpuser->state == 3) 
@@ -526,7 +524,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                } else {
                                                        ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
                                                        return NULL;
-                                               }                                                       
+                                               }
                                        } else {
                                                tmpuser->state = 2;
                                                tmpuser->digts = 0;
@@ -566,7 +564,6 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                        tmpuser->ynidx = 0;
                                                        if (!ast_streamfile(tmpuser->ochan, pressbuttonname, tmpuser->ochan->language)) {
                                                                tmpuser->state = 3;
-                                                               
                                                        } else {
                                                                return NULL;
                                                        } 
@@ -580,7 +577,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                livechannels++;
                        }
                }
-               
+
                tmpto = to;
                if (to < 0) {
                        to = 1000;
@@ -590,7 +587,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                winner = ast_waitfor_n(watchers, pos, &to);
                tmpto -= to;
                totalwait -= tmpto;
-               wtd = to;       
+               wtd = to;
                if (totalwait <= 0) {
                        ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait);
                        clear_calling_tree(findme_user_list);
@@ -631,8 +628,8 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                                        ast_log(LOG_WARNING, "Unable to playback %s.\n", callfromname);
                                                                        ast_frfree(f);
                                                                        return NULL;
-                                                               }                               
-                                                       } else {                        
+                                                               }
+                                                       } else {
                                                                tmpuser->state = 2;
                                                                if (!ast_streamfile(tmpuser->ochan, tpargs->norecordingprompt, tmpuser->ochan->language))
                                                                        ast_sched_runq(tmpuser->ochan->sched);
@@ -693,18 +690,18 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                if (!strcmp(tmpuser->yn, tpargs->takecall)) {
                                                        ast_debug(1, "Match to take the call!\n");
                                                        ast_frfree(f);
-                                                       return tmpuser->ochan;  
+                                                       return tmpuser->ochan;
                                                }
                                                if (!strcmp(tmpuser->yn, tpargs->nextindp)) {
                                                        ast_debug(1, "Next in dial plan step requested.\n");
                                                        *status = 1;
                                                        ast_frfree(f);
                                                        return NULL;
-                                               }       
-                                               
+                                               }
+
                                        }
                                }
-                               
+
                                ast_frfree(f);
                        } else {
                                if (winner) {
@@ -723,12 +720,12 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
                                                }
                                        }
                                }
-                       }                                       
-                       
+                       }
+
                } else
                        ast_debug(1, "timed out waiting for action\n");
        }
-       
+
        /* --- WAIT FOR WINNER NUMBER END! -----------*/
        return NULL;
 }
@@ -748,7 +745,7 @@ static void findmeexec(struct fm_args *tpargs)
        struct findme_user_listptr *findme_user_list;
        int status;
 
-       findme_user_list = ast_calloc(1, sizeof(*findme_user_list));            
+       findme_user_list = ast_calloc(1, sizeof(*findme_user_list));
        AST_LIST_HEAD_INIT_NOLOCK(findme_user_list);
 
        /* We're going to figure out what the longest possible string of digits to collect is */
@@ -782,14 +779,14 @@ static void findmeexec(struct fm_args *tpargs)
                                sprintf(dialarg, "%s", number);
                        else
                                sprintf(dialarg, "%s@%s", number, tpargs->context);
-                                       
+
                        tmpuser = ast_calloc(1, sizeof(*tmpuser));
                        if (!tmpuser) {
                                ast_log(LOG_WARNING, "Out of memory!\n");
                                ast_free(findme_user_list);
                                return;
                        }
-                                       
+
                        outbound = ast_request("Local", ast_best_codec(caller->nativeformats), dialarg, &dg);
                        if (outbound) {
                                ast_set_callerid(outbound, caller->cid.cid_num, caller->cid.cid_name, caller->cid.cid_num);
@@ -824,19 +821,17 @@ static void findmeexec(struct fm_args *tpargs)
                                                        outbound = NULL;
                                                }
                                        }
-                                               
                                }
                        } else 
                                ast_log(LOG_WARNING, "Unable to allocate a channel for Local/%s cause: %s\n", dialarg, ast_cause2str(dg));
-                                       
+
                        number = rest;
                } while (number);
-                               
-               status = 0;     
+
+               status = 0;
                if (!AST_LIST_EMPTY(findme_user_list))
                        winner = wait_for_winner(findme_user_list, nm, caller, tpargs->namerecloc, &status, tpargs);
-               
-                                       
+
                while ((fmuser = AST_LIST_REMOVE_HEAD(findme_user_list, entry))) {
                        if (!fmuser->cleared && fmuser->ochan != winner)
                                clear_caller(fmuser);
@@ -845,21 +840,21 @@ static void findmeexec(struct fm_args *tpargs)
 
                fmuser = NULL;
                tmpuser = NULL;
-               headuser = NULL;        
+               headuser = NULL;
                if (winner)
                        break;
 
                if (!caller) {
                        tpargs->status = 1;
                        ast_free(findme_user_list);
-                       return; 
+                       return;
                }
 
                idx++;
-               AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry)
+               AST_LIST_TRAVERSE(&tpargs->cnumbers, nm, entry) {
                        if (nm->order == idx)
                                break;
-
+               }
        }
        ast_free(findme_user_list);
        if (!winner) 
@@ -869,9 +864,7 @@ static void findmeexec(struct fm_args *tpargs)
                tpargs->outbound = winner;
        }
 
-       
        return;
-               
 }
 
 static int app_exec(struct ast_channel *chan, void *data)
@@ -887,7 +880,6 @@ static int app_exec(struct ast_channel *chan, void *data)
        struct ast_channel *caller;
        struct ast_channel *outbound;
        static char toast[80];
-       
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(followmeid);
                AST_APP_ARG(options);
@@ -897,7 +889,7 @@ static int app_exec(struct ast_channel *chan, void *data)
                ast_log(LOG_WARNING, "%s requires an argument (followmeid)\n", app);
                return -1;
        }
-       
+
        if (!(argstr = ast_strdupa((char *)data))) {
                ast_log(LOG_ERROR, "Out of memory!\n");
                return -1;
@@ -916,7 +908,7 @@ static int app_exec(struct ast_channel *chan, void *data)
                        break;
        }
        AST_RWLIST_UNLOCK(&followmes);
-       
+
        ast_debug(1, "New profile %s.\n", args.followmeid);
 
        if (!f) {
@@ -927,7 +919,7 @@ static int app_exec(struct ast_channel *chan, void *data)
        /* XXX TODO: Reinsert the db check value to see whether or not follow-me is on or off */
        if (args.options) 
                ast_app_parse_options(followme_opts, &targs.followmeflags, NULL, args.options);
-       
+
        /* Lock the profile lock and copy out everything we need to run with before unlocking it again */
        ast_mutex_lock(&f->lock);
        targs.mohclass = ast_strdupa(f->moh);
@@ -948,38 +940,38 @@ static int app_exec(struct ast_channel *chan, void *data)
                AST_LIST_INSERT_TAIL(&targs.cnumbers, newnm, entry);
        }
        ast_mutex_unlock(&f->lock);
-       
+
        if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_STATUSMSG)) 
                ast_stream_and_wait(chan, targs.statusprompt, "");
-       
+
        snprintf(namerecloc,sizeof(namerecloc),"%s/followme.%s",ast_config_AST_SPOOL_DIR,chan->uniqueid);
        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, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL) < 0)
                        goto outrun;
-       
+
        if (!ast_fileexists(namerecloc, NULL, chan->language))
-               ast_copy_string(namerecloc, "", sizeof(namerecloc));                                    
-       
+               ast_copy_string(namerecloc, "", sizeof(namerecloc));
+
        if (ast_streamfile(chan, targs.plsholdprompt, chan->language))
                goto outrun;
        if (ast_waitstream(chan, "") < 0)
                goto outrun;
        ast_moh_start(chan, S_OR(targs.mohclass, NULL), NULL);
-       
+
        targs.status = 0;
        targs.chan = chan;
        ast_copy_string(targs.namerecloc, namerecloc, sizeof(targs.namerecloc));
-       
-       findmeexec(&targs);             
-       
+
+       findmeexec(&targs);
+
        while ((nm = AST_LIST_REMOVE_HEAD(&targs.cnumbers, entry)))
                ast_free(nm);
-               
+
        if (!ast_strlen_zero(namerecloc))
-               unlink(namerecloc);     
-       
+               unlink(namerecloc);
+
        if (targs.status != 100) {
                ast_moh_stop(chan);
                if (ast_test_flag(&targs.followmeflags, FOLLOWMEFLAG_UNREACHABLEMSG)) 
@@ -989,12 +981,12 @@ static int app_exec(struct ast_channel *chan, void *data)
                caller = chan;
                outbound = targs.outbound;
                /* Bridge the two channels. */
-               
-               memset(&config,0,sizeof(struct ast_bridge_config));
+
+               memset(&config, 0, sizeof(config));
                ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
                ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
                ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
-               
+
                ast_moh_stop(caller);
                /* Be sure no generators are left on it */
                ast_deactivate_generator(caller);
@@ -1006,7 +998,7 @@ static int app_exec(struct ast_channel *chan, void *data)
                        goto outrun;
                }
                time(&answer_time);
-               res = ast_bridge_call(caller,outbound,&config);
+               res = ast_bridge_call(caller, outbound, &config);
                time(&end_time);
                snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
                pbx_builtin_setvar_helper(caller, "DIALEDTIME", toast);
@@ -1017,7 +1009,7 @@ static int app_exec(struct ast_channel *chan, void *data)
        }
 
        outrun:
-       
+
        return res;
 }
 
@@ -1051,7 +1043,7 @@ static int reload(void)
 {
        reload_followme(1);
 
-       return 0;       
+       return 0;
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Find-Me/Follow-Me Application",
index 41c9950..471477a 100644 (file)
@@ -1699,7 +1699,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                         "%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, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 0, NULL);
                else
                        res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL);
                if (res == -1)
index ae76f9e..f11537e 100644 (file)
@@ -2360,7 +2360,6 @@ static int load_config(int reload)
        /* 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;
@@ -2375,6 +2374,8 @@ static int load_config(int reload)
        memset(&global_stats, 0, sizeof(global_stats));
        global_stats.reset = ast_tvnow();
 
+       global_silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
+
        /* Make sure we could load configuration file */
        if (!cfg) {
                ast_log(LOG_WARNING, "Failed to load configuration file. Module activated with default settings.\n");
@@ -2640,7 +2641,7 @@ static char *handle_minivm_show_settings(struct ast_cli_entry *e, int cmd, struc
        ast_cli(a->fd, "\n");
        ast_cli(a->fd, "  Mail command (shell):               %s\n", global_mailcmd);
        ast_cli(a->fd, "  Max silence:                        %d\n", global_maxsilence);
-       ast_cli(a->fd, "  Silence treshold:                   %d\n", global_silencethreshold);
+       ast_cli(a->fd, "  Silence threshold:                  %d\n", global_silencethreshold);
        ast_cli(a->fd, "  Max message length (secs):          %d\n", global_vmmaxmessage);
        ast_cli(a->fd, "  Min message length (secs):          %d\n", global_vmminmessage);
        ast_cli(a->fd, "  Default format:                     %s\n", default_vmformat);
index 7214e1f..b062011 100644 (file)
@@ -243,7 +243,7 @@ static int record_exec(struct ast_channel *chan, void *data)
                        ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
                        return -1;
                }
-               ast_dsp_set_threshold(sildet, 256);
+               ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
        } 
 
        /* Create the directory if it does not exist. */
index 92e3859..e250c1f 100644 (file)
@@ -8399,7 +8399,7 @@ static int load_config(int reload)
                }
 
                /* Silence treshold */
-               silencethreshold = 256;
+               silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
                if ((val = ast_variable_retrieve(cfg, "general", "silencethreshold")))
                        silencethreshold = atoi(val);
                
index e45f243..c0fc47a 100644 (file)
  *
  * \author David C. Troy <dave@popvox.com>
  *
+ * \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 <skadorov@yahoo.com>
+ *
  * \ingroup applications
  */
 
@@ -42,9 +48,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #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,24 @@ static char *descrip =
 "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;
 
+       /*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 +104,15 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
                ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
                return -1;
        }
-       ast_dsp_set_threshold(sildet, silencethreshold);
+       ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
 
        /* 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,30 +122,36 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
                
                /* 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 (wait_for_silence)
+                       ast_verb(6, "Got %dms silence < %dms required\n", dsptime, timereqd);
+               else
+                       ast_verb(6, "Got %dms noise < %dms required\n", dsptime, timereqd);
 
-               if (dspsilence >= silencereqd) {
-                       ast_verb(3, "Exiting with %dms silence >= %dms required\n", dspsilence, silencereqd);
+               if (dsptime >= timereqd) {
+                       if (wait_for_silence)
+                               ast_verb(3, "Exiting with %dms silence >= %dms required\n", dsptime, timereqd);
+                       else
+                               ast_verb(3, "Exiting with %dms noise >= %dms required\n", 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");
+                       ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE");
                        break;
                }
 
-               if ( timeout && (difftime(time(&now),waitstart) >= timeout) ) {
+               if (timeout && (difftime(time(&now), waitstart) >= timeout)) {
                        pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
                        ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
                        res = 0;
@@ -146,43 +167,60 @@ static int do_waiting(struct ast_channel *chan, int silencereqd, time_t waitstar
        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);
+       ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout);
 
        time(&waitstart);
        res = 1;
        for (i=0; (i<iterations) && (res == 1); i++) {
-               res = do_waiting(chan, silencereqd, waitstart, timeout);
+               res = do_waiting(chan, timereqd, waitstart, timeout, wait_for_silence);
        }
        if (res > 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");
diff --git a/configs/dsp.conf.sample b/configs/dsp.conf.sample
new file mode 100644 (file)
index 0000000..788b78c
--- /dev/null
@@ -0,0 +1,7 @@
+[default]
+;
+; Length of sound (in milliseconds) before a period of silence is considered
+; to be a change from talking to silence or a period of noise converts silence
+; to talking.  [default=256]
+;
+;silencethreshold=256
index 10ed53d..1235c3a 100644 (file)
 
 struct ast_dsp;
 
+enum threshold {
+       /* Array offsets */
+       THRESHOLD_SILENCE = 0,
+       /* Always the last */
+       THRESHOLD_MAX = 1,
+};
+
 struct ast_dsp *ast_dsp_new(void);
 void ast_dsp_free(struct ast_dsp *dsp);
 
@@ -84,6 +91,10 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
    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);
@@ -115,4 +126,12 @@ int ast_dsp_get_tstate(struct ast_dsp *dsp);
 /*! \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(enum threshold which);
+
+/* \brief Reloads dsp settings from dsp.conf*/
+int ast_dsp_reload(void);
+
+int ast_dsp_init(void);
+
 #endif /* _ASTERISK_DSP_H */
index 5c3f8a4..7a2227f 100644 (file)
@@ -1268,7 +1268,7 @@ int ast_unlock_path(const char *path)
 
 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 @@ int ast_record_review(struct ast_channel *chan, const char *playfile, const char
 
        cmd = '3';       /* Want to start by recording */
 
+       silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
+
        while ((cmd >= 0) && (cmd != 't')) {
                switch (cmd) {
                case '1':
index 287b6cc..21aee3b 100644 (file)
@@ -121,6 +121,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 #include "asterisk/linkedlists.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/module.h"
+#include "asterisk/dsp.h"
 
 #include "asterisk/doxyref.h"          /* Doxygen documentation */
 
@@ -3218,7 +3219,7 @@ int main(int argc, char *argv[])
        }
 
        ast_rtp_init();
-
+       ast_dsp_init();
        ast_udptl_init();
 
        if (ast_image_init()) {
index 6945464..a9a7874 100644 (file)
@@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/alaw.h"
 #include "asterisk/utils.h"
 #include "asterisk/options.h"
+#include "asterisk/config.h"
 
 /*! Number of goertzels for progress detect */
 enum gsamp_size {
@@ -193,6 +194,8 @@ enum gsamp_thresh {
 #define SAMPLES_IN_FRAME       160
 
 
+#define CONFIG_FILE_NAME "dsp.conf"
+
 typedef struct {
        int v2;
        int v3;
@@ -272,6 +275,8 @@ static char dtmf_positions[] = "123A" "456B" "789C" "*0#D";
 
 static char bell_mf_positions[] = "1247C-358A--69*---0B----#";
 
+static int thresholds[THRESHOLD_MAX];
+
 static inline void goertzel_sample(goertzel_state_t *s, short sample)
 {
        int v1;
@@ -1021,7 +1026,7 @@ int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf)
        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;
@@ -1073,6 +1078,8 @@ static int __ast_dsp_silence(struct ast_dsp *dsp, short *s, int len, int *totals
        }
        if (totalsilence)
                *totalsilence = dsp->totalsilence;
+       if (totalnoise)
+               *totalnoise = dsp->totalnoise;
        return res;
 }
 
@@ -1179,9 +1186,28 @@ int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
        }
        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;
@@ -1236,7 +1262,7 @@ struct ast_frame *ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp,
                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;
@@ -1516,3 +1542,42 @@ int ast_dsp_get_tcount(struct ast_dsp *dsp)
 {
        return dsp->tcount;
 }
+
+static int _dsp_init(int reload)
+{
+       struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+       struct ast_config *cfg;
+       struct ast_variable *var;
+
+       cfg = ast_config_load(CONFIG_FILE_NAME, config_flags);
+
+       if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED) {
+               const char *value;
+
+               value = ast_variable_retrieve(cfg, "default", "silencethreshold");
+               if (value && sscanf(value, "%d", &thresholds[THRESHOLD_SILENCE]) != 1) {
+                       ast_log(LOG_WARNING, "%s: '%s' is not a valid silencethreshold value\n", CONFIG_FILE_NAME, var->value);
+                       thresholds[THRESHOLD_SILENCE] = 256;
+               } else if (!value)
+                       thresholds[THRESHOLD_SILENCE] = 256;
+
+               ast_config_destroy(cfg);
+       }
+       return 0;
+}
+
+int ast_dsp_get_threshold_from_settings(enum threshold which)
+{
+       return thresholds[which];
+}
+
+int ast_dsp_init(void)
+{
+       return _dsp_init(0);
+}
+
+int ast_dsp_reload(void)
+{
+       return _dsp_init(1);
+}
+
index 43d254c..d34da9f 100644 (file)
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/http.h"
 #include "asterisk/lock.h"
 #include "asterisk/features.h"
+#include "asterisk/dsp.h"
 
 #ifdef DLFCNCOMPAT
 #include "asterisk/dlfcn-compat.h"
@@ -249,6 +250,7 @@ static struct reload_classes {
        { "http",       ast_http_reload },
        { "logger",     logger_reload },
        { "features",   ast_features_reload },
+       { "dsp",        ast_dsp_reload},
        { NULL,         NULL }
 };
 
index 6e9b529..dcde563 100644 (file)
@@ -1296,7 +1296,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
                        ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
                        return -1;
                }
-               ast_dsp_set_threshold(sildet, 256);
+               ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
        }
 
        /* backward compatibility, if no offset given, arg[6] would have been