]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
func_volume: Accept decimal number as argument
authorJean Aunis <jean.aunis@prescom.fr>
Tue, 7 Apr 2020 12:05:22 +0000 (14:05 +0200)
committerGeorge Joseph <gjoseph@digium.com>
Tue, 14 Apr 2020 14:36:54 +0000 (09:36 -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 f381c413b2a8cf1269be65f6626e19cf3f5746da..438d9a2155e9af4c9cf410b8355aecb8f96bd648 100644 (file)
@@ -72,8 +72,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 struct volume_information {
        struct ast_audiohook audiohook;
-       int tx_gain;
-       int rx_gain;
+       float tx_gain;
+       float rx_gain;
        unsigned int flags;
 };
 
@@ -109,7 +109,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)
@@ -143,7 +143,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;
@@ -195,9 +195,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 9733600f004c9fa3911ef54643ecd3f900f79c60..4572b6e122113623a7afa806e58204d31b4774be 100644 (file)
@@ -587,6 +587,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)
index 2e652c35ee832e6f07795c276a8a2f8fa8dd3e28..082cec4ed7ae7127b2caa586b30294284c836d44 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 6dc28a70da02f7ababbe4fcf228577eb6011a789..28178a6309ae88f27c0ca6aa92b4b045b9de127b 100644 (file)
@@ -45,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/dsp.h"
 #include "asterisk/file.h"
 
+#include <math.h>
+
 #if !defined(LOW_MEMORY)
 static void frame_cache_cleanup(void *data);
 
@@ -695,6 +697,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;