func_volume: Accept decimal number as argument

Allow voice volume to be multiplied or divided by a floating point number.

ASTERISK-28813

Change-Id: I5b42b890ec4e1f6b0b3400cb44ff16522b021c8c
This commit is contained in:
Jean Aunis
2020-04-07 14:05:22 +02:00
committed by George Joseph
parent ce1213e72f
commit 947a6e8674
5 changed files with 68 additions and 6 deletions

View File

@@ -0,0 +1,3 @@
Subject: func_volume
Accept decimal number as argument.

View File

@@ -72,8 +72,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
struct volume_information { struct volume_information {
struct ast_audiohook audiohook; struct ast_audiohook audiohook;
int tx_gain; float tx_gain;
int rx_gain; float rx_gain;
unsigned int flags; unsigned int flags;
}; };
@@ -109,7 +109,7 @@ static int volume_callback(struct ast_audiohook *audiohook, struct ast_channel *
{ {
struct ast_datastore *datastore = NULL; struct ast_datastore *datastore = NULL;
struct volume_information *vi = 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 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) 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) if (!(gain = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? &vi->rx_gain : &vi->tx_gain) || !*gain)
return 0; return 0;
/* Apply gain to frame... easy as pi */ /* Apply gain to frame... easy as pi */
ast_frame_adjust_volume(frame, *gain); ast_frame_adjust_volume_float(frame, *gain);
} }
return 0; 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")) { if (!strcasecmp(args.direction, "tx")) {
vi->tx_gain = atoi(value); vi->tx_gain = atof(value);
} else if (!strcasecmp(args.direction, "rx")) { } else if (!strcasecmp(args.direction, "rx")) {
vi->rx_gain = atoi(value); vi->rx_gain = atof(value);
} else { } else {
ast_log(LOG_ERROR, "Direction must be either RX or TX\n"); ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
} }

View 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); 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. \brief Sums two frames of audio samples.
\param f1 The first frame (which will contain the result) \param f1 The first frame (which will contain the result)

View File

@@ -375,11 +375,35 @@ static force_inline void ast_slinear_saturated_multiply(short *input, short *val
*input = (short) res; *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) static force_inline void ast_slinear_saturated_divide(short *input, short *value)
{ {
*input /= *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 #ifdef localtime_r
#undef localtime_r #undef localtime_r
#endif #endif

View File

@@ -45,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dsp.h" #include "asterisk/dsp.h"
#include "asterisk/file.h" #include "asterisk/file.h"
#include <math.h>
#if !defined(LOW_MEMORY) #if !defined(LOW_MEMORY)
static void frame_cache_cleanup(void *data); static void frame_cache_cleanup(void *data);
@@ -695,6 +697,31 @@ int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
return 0; 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 ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
{ {
int count; int count;