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 Friendly Automation
parent 7a00db673a
commit ef4255f6ed
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

@ -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");
}

View File

@ -594,6 +594,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)

View 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

View File

@ -43,6 +43,8 @@
#include "asterisk/dsp.h"
#include "asterisk/file.h"
#include <math.h>
#if !defined(LOW_MEMORY)
static void frame_cache_cleanup(void *data);
@ -703,6 +705,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;