mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
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:
committed by
George Joseph
parent
ce1213e72f
commit
947a6e8674
3
doc/CHANGES-staging/func_volume.txt
Normal file
3
doc/CHANGES-staging/func_volume.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Subject: func_volume
|
||||||
|
|
||||||
|
Accept decimal number as argument.
|
@@ -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");
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
27
main/frame.c
27
main/frame.c
@@ -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;
|
||||||
|
Reference in New Issue
Block a user