func_volume: Accept decimal number as argument
authorJean Aunis <jean.aunis@prescom.fr>
Tue, 7 Apr 2020 12:05:22 +0000 (14:05 +0200)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Tue, 14 Apr 2020 14:28:05 +0000 (09:28 -0500)
Allow voice volume to be multiplied or divided by a floating point number.

ASTERISK-28813

Change-Id: I5b42b890ec4e1f6b0b3400cb44ff16522b021c8c

doc/CHANGES-staging/func_volume.txt [new file with mode: 0644]
funcs/func_volume.c
include/asterisk/frame.h
include/asterisk/utils.h
main/frame.c

diff --git a/doc/CHANGES-staging/func_volume.txt b/doc/CHANGES-staging/func_volume.txt
new file mode 100644 (file)
index 0000000..e73295b
--- /dev/null
@@ -0,0 +1,3 @@
+Subject: func_volume
+
+Accept decimal number as argument.
index 533eb55..8587479 100644 (file)
@@ -70,8 +70,8 @@
 
 struct volume_information {
        struct ast_audiohook audiohook;
-       int tx_gain;
-       int rx_gain;
+       float tx_gain;
+       float rx_gain;
        unsigned int flags;
 };
 
@@ -107,7 +107,7 @@ static int volume_callback(struct ast_audiohook *audiohook, struct ast_channel *
 {
        struct ast_datastore *datastore = NULL;
        struct volume_information *vi = NULL;
-       int *gain = NULL;
+       float *gain = NULL;
 
        /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
        if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
@@ -141,7 +141,7 @@ static int volume_callback(struct ast_audiohook *audiohook, struct ast_channel *
                if (!(gain = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? &vi->rx_gain : &vi->tx_gain) || !*gain)
                        return 0;
                /* Apply gain to frame... easy as pi */
-               ast_frame_adjust_volume(frame, *gain);
+               ast_frame_adjust_volume_float(frame, *gain);
        }
 
        return 0;
@@ -193,9 +193,9 @@ static int volume_write(struct ast_channel *chan, const char *cmd, char *data, c
        }
 
        if (!strcasecmp(args.direction, "tx")) {
-               vi->tx_gain = atoi(value);
+               vi->tx_gain = atof(value);
        } else if (!strcasecmp(args.direction, "rx")) {
-               vi->rx_gain = atoi(value);
+               vi->rx_gain = atof(value);
        } else {
                ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
        }
index 780cba3..0ead3b8 100644 (file)
@@ -597,6 +597,14 @@ struct ast_frame *ast_frame_enqueue(struct ast_frame *head, struct ast_frame *f,
 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment);
 
 /*!
+  \brief Adjusts the volume of the audio samples contained in a frame.
+  \param f The frame containing the samples (must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR)
+  \param adjustment The number of dB to adjust up or down.
+  \return 0 for success, non-zero for an error
+ */
+int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment);
+
+/*!
   \brief Sums two frames of audio samples.
   \param f1 The first frame (which will contain the result)
   \param f2 The second frame
index 2b332a5..10dfe83 100644 (file)
@@ -375,11 +375,35 @@ static force_inline void ast_slinear_saturated_multiply(short *input, short *val
                *input = (short) res;
 }
 
+static force_inline void ast_slinear_saturated_multiply_float(short *input, float *value)
+{
+       float res;
+
+       res = (float) *input * *value;
+       if (res > 32767)
+               *input = 32767;
+       else if (res < -32768)
+               *input = -32768;
+       else
+               *input = (short) res;
+}
+
 static force_inline void ast_slinear_saturated_divide(short *input, short *value)
 {
        *input /= *value;
 }
 
+static force_inline void ast_slinear_saturated_divide_float(short *input, float *value)
+{
+       float res = (float) *input / *value;
+       if (res > 32767)
+               *input = 32767;
+       else if (res < -32768)
+               *input = -32768;
+       else
+               *input = (short) res;
+}
+
 #ifdef localtime_r
 #undef localtime_r
 #endif
index f7a5222..4ae732b 100644 (file)
@@ -43,6 +43,8 @@
 #include "asterisk/dsp.h"
 #include "asterisk/file.h"
 
+#include <math.h>
+
 #if (defined(LOW_MEMORY) || defined(MALLOC_DEBUG)) && !defined(NO_FRAME_CACHE)
 #define NO_FRAME_CACHE
 #endif
@@ -706,6 +708,31 @@ int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
        return 0;
 }
 
+int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment)
+{
+       int count;
+       short *fdata = f->data.ptr;
+       float adjust_value = fabs(adjustment);
+
+       if ((f->frametype != AST_FRAME_VOICE) || !(ast_format_cache_is_slinear(f->subclass.format))) {
+               return -1;
+       }
+
+       if (!adjustment) {
+               return 0;
+       }
+
+       for (count = 0; count < f->samples; count++) {
+               if (adjustment > 0) {
+                       ast_slinear_saturated_multiply_float(&fdata[count], &adjust_value);
+               } else if (adjustment < 0) {
+                       ast_slinear_saturated_divide_float(&fdata[count], &adjust_value);
+               }
+       }
+
+       return 0;
+}
+
 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
 {
        int count;