[Asterisk-code-review] app_amd: Add option to play audio during AMD. (asterisk[master])
Friendly Automation
asteriskteam at digium.com
Mon Sep 26 09:30:45 CDT 2022
Friendly Automation has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/18974 )
Change subject: app_amd: Add option to play audio during AMD.
......................................................................
app_amd: Add option to play audio during AMD.
Adds an option that will play an audio file
to the party while AMD is running on the
channel, so the called party does not just
hear silence.
ASTERISK-30179 #close
Change-Id: I4af306274552b61b3d9f0883c33f698abd4699b6
---
M apps/app_amd.c
M configs/samples/amd.conf.sample
A doc/CHANGES-staging/app_amd.txt
3 files changed, 75 insertions(+), 4 deletions(-)
Approvals:
Joshua Colp: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Friendly Automation: Approved for Submit
diff --git a/apps/app_amd.c b/apps/app_amd.c
index 39d0b79..fb63c7d 100644
--- a/apps/app_amd.c
+++ b/apps/app_amd.c
@@ -92,6 +92,12 @@
<para>Is the maximum duration of a word to accept.</para>
<para>If exceeded, then the result is detection as a MACHINE</para>
</parameter>
+ <parameter name="audioFile" required="false">
+ <para>Is an audio file to play to the caller while AMD is in progress.</para>
+ <para>By default, no audio file is played.</para>
+ <para>If an audio file is configured in amd.conf, then that file will be used
+ if one is not specified here. That file may be overridden by this argument.</para>
+ </parameter>
</syntax>
<description>
<para>This application attempts to detect answering machines at the beginning
@@ -155,6 +161,9 @@
static int dfltMaximumNumberOfWords = 2;
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 char *dfltAudioFile = NULL;
+
+static ast_mutex_t config_lock;
/* Set to the lowest ms value provided in amd.conf or application parameters */
static int dfltMaxWaitTimeForFrame = 50;
@@ -179,7 +188,7 @@
char amdCause[256] = "", amdStatus[256] = "";
char *parse = ast_strdupa(data);
- /* Lets set the initial values of the variables that will control the algorithm.
+ /* Let's 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
when invoking the application, then the default values will be overwritten
by the ones passed as parameters. */
@@ -193,6 +202,7 @@
int silenceThreshold = dfltSilenceThreshold;
int maximumWordLength = dfltMaximumWordLength;
int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame;
+ const char *audioFile = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(argInitialSilence);
@@ -204,8 +214,15 @@
AST_APP_ARG(argMaximumNumberOfWords);
AST_APP_ARG(argSilenceThreshold);
AST_APP_ARG(argMaximumWordLength);
+ AST_APP_ARG(audioFile);
);
+ ast_mutex_lock(&config_lock);
+ if (!ast_strlen_zero(dfltAudioFile)) {
+ audioFile = ast_strdupa(dfltAudioFile);
+ }
+ ast_mutex_unlock(&config_lock);
+
ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", ast_channel_name(chan),
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, "(N/A)"),
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "(N/A)"),
@@ -233,6 +250,9 @@
silenceThreshold = atoi(args.argSilenceThreshold);
if (!ast_strlen_zero(args.argMaximumWordLength))
maximumWordLength = atoi(args.argMaximumWordLength);
+ if (!ast_strlen_zero(args.audioFile)) {
+ audioFile = args.audioFile;
+ }
} else {
ast_debug(1, "AMD using the default parameters.\n");
}
@@ -280,6 +300,11 @@
/* Set our start time so we can tie the loop to real world time and not RTP updates */
amd_tvstart = ast_tvnow();
+ /* Optional audio file to play to caller while AMD is doing its thing. */
+ if (!ast_strlen_zero(audioFile)) {
+ ast_streamfile(chan, audioFile, ast_channel_language(chan));
+ }
+
/* Now we go into a loop waiting for frames from the channel */
while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
int ms = 0;
@@ -462,10 +487,14 @@
/* Free the DSP used to detect silence */
ast_dsp_free(silenceDetector);
+ /* If we were playing something to pass the time, stop it now. */
+ if (!ast_strlen_zero(audioFile)) {
+ ast_stopstream(chan);
+ }
+
return;
}
-
static int amd_exec(struct ast_channel *chan, const char *data)
{
isAnsweringMachine(chan, data);
@@ -516,7 +545,16 @@
dfltMaximumNumberOfWords = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_word_length")) {
dfltMaximumWordLength = atoi(var->value);
-
+ } else if (!strcasecmp(var->name, "playback_file")) {
+ ast_mutex_lock(&config_lock);
+ if (dfltAudioFile) {
+ ast_free(dfltAudioFile);
+ dfltAudioFile = NULL;
+ }
+ if (!ast_strlen_zero(var->value)) {
+ dfltAudioFile = ast_strdup(var->value);
+ }
+ ast_mutex_unlock(&config_lock);
} else {
ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
app, cat, var->name, var->lineno);
@@ -539,6 +577,12 @@
static int unload_module(void)
{
+ ast_mutex_lock(&config_lock);
+ if (dfltAudioFile) {
+ ast_free(dfltAudioFile);
+ }
+ ast_mutex_unlock(&config_lock);
+ ast_mutex_destroy(&config_lock);
return ast_unregister_application(app);
}
@@ -554,6 +598,7 @@
*/
static int load_module(void)
{
+ ast_mutex_init(&config_lock);
if (load_config(0) || ast_register_application_xml(app, amd_exec)) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/configs/samples/amd.conf.sample b/configs/samples/amd.conf.sample
index d1764b5..b108298 100644
--- a/configs/samples/amd.conf.sample
+++ b/configs/samples/amd.conf.sample
@@ -8,6 +8,11 @@
silence_threshold = 256 ; If the average level of noise in a sample does not reach
; this value, from a scale of 0 to 32767, then we will consider
; it to be silence.
+;playback_file = ; Audio file to play while AMD is running, so the caller
+ ; does not just hear silence. Note that specifying this here
+ ; will apply to ALL AMD runs, so you may wish to set it
+ ; in the dialplan as an argument to AMD() instead.
+ ; Default is no audio file (not to play anything).
; Greeting ;
initial_silence = 2500 ; Maximum silence duration before the greeting.
@@ -19,7 +24,7 @@
; Word detection ;
min_word_length = 100 ; Minimum duration of Voice to considered as a word
-maximum_word_length = 5000 ; Maximum duration of a single Voice utterance allowed.
+maximum_word_length = 5000 ; Maximum duration of a single Voice utterance allowed.
between_words_silence = 50 ; Minimum duration of silence after a word to consider
; the audio what follows as a new word
diff --git a/doc/CHANGES-staging/app_amd.txt b/doc/CHANGES-staging/app_amd.txt
new file mode 100644
index 0000000..ffccd8c
--- /dev/null
+++ b/doc/CHANGES-staging/app_amd.txt
@@ -0,0 +1,5 @@
+Subject: app_amd
+
+An audio file to play during AMD processing can
+now be specified to the AMD application or configured
+in the amd.conf configuration file.
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/18974
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I4af306274552b61b3d9f0883c33f698abd4699b6
Gerrit-Change-Number: 18974
Gerrit-PatchSet: 8
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at sangoma.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220926/51a00545/attachment-0001.html>
More information about the asterisk-code-review
mailing list