2017-01-06 02:10:15 -05:00
/*
2006-01-02 17:28:59 +00:00
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2014-02-05 15:02:28 -06:00
* Copyright ( C ) 2005 - 2014 , Anthony Minessale II < anthm @ freeswitch . org >
2006-01-02 17:28:59 +00:00
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2006-01-02 17:28:59 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
2017-01-06 02:10:15 -05:00
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2006-01-02 17:28:59 +00:00
*
*
2010-09-02 08:22:22 -05:00
* switch_resample . c - - Resampler
2006-01-02 17:28:59 +00:00
*
*/
2008-01-27 17:42:51 +00:00
2006-04-29 01:00:52 +00:00
# include <switch.h>
2006-04-29 06:05:03 +00:00
# include <switch_resample.h>
2007-03-28 18:21:00 +00:00
# ifndef WIN32
# include <switch_private.h>
# endif
2009-02-13 23:35:17 +00:00
# include <speex/speex_resampler.h>
2006-01-02 17:28:59 +00:00
# define NORMFACT (float)0x8000
# define MAXSAMPLE (float)0x7FFF
# define MAXSAMPLEC (char)0x7F
2006-11-09 05:36:03 +00:00
# define QUALITY 0
2006-01-02 17:28:59 +00:00
# ifndef MIN
# define MIN(a,b) ((a) < (b) ? (a) : (b))
# endif
# ifndef MAX
# define MAX(a,b) ((a) > (b) ? (a) : (b))
# endif
2008-01-30 15:45:52 +00:00
# define resample_buffer(a, b, c) a > b ? ((a / 1000) / 2) * c : ((b / 1000) / 2) * c
2009-02-10 00:58:54 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_resample_perform_create ( switch_audio_resampler_t * * new_resampler ,
2010-02-06 03:38:24 +00:00
uint32_t from_rate , uint32_t to_rate ,
2009-02-13 23:35:17 +00:00
uint32_t to_size ,
2010-02-06 03:38:24 +00:00
int quality , uint32_t channels , const char * file , const char * func , int line )
2006-01-02 17:28:59 +00:00
{
2009-02-13 23:35:17 +00:00
int err = 0 ;
2006-04-29 01:00:52 +00:00
switch_audio_resampler_t * resampler ;
2006-03-30 23:02:50 +00:00
double lto_rate , lfrom_rate ;
2006-01-03 01:17:59 +00:00
2009-02-13 23:35:17 +00:00
switch_zmalloc ( resampler , sizeof ( * resampler ) ) ;
2010-02-06 03:38:24 +00:00
2015-06-05 23:46:56 -05:00
if ( ! channels ) channels = 1 ;
2017-01-06 02:10:15 -05:00
2015-06-05 23:46:56 -05:00
resampler - > resampler = speex_resampler_init ( channels , from_rate , to_rate , quality , & err ) ;
2009-02-13 23:35:17 +00:00
if ( ! resampler - > resampler ) {
free ( resampler ) ;
return SWITCH_STATUS_GENERR ;
2006-01-02 17:28:59 +00:00
}
2009-02-13 23:35:17 +00:00
* new_resampler = resampler ;
2006-03-30 23:02:50 +00:00
lto_rate = ( double ) resampler - > to_rate ;
2010-02-06 03:38:24 +00:00
lfrom_rate = ( double ) resampler - > from_rate ;
2009-02-13 23:35:17 +00:00
resampler - > from_rate = from_rate ;
2010-02-06 03:38:24 +00:00
resampler - > to_rate = to_rate ;
resampler - > factor = ( lto_rate / lfrom_rate ) ;
resampler - > rfactor = ( lfrom_rate / lto_rate ) ;
2014-06-12 22:06:33 +05:00
resampler - > channels = channels ;
2017-01-06 02:10:15 -05:00
2015-06-05 23:46:56 -05:00
//resampler->to_size = resample_buffer(to_rate, from_rate, (uint32_t) to_size);
resampler - > to_size = switch_resample_calc_buffer_size ( resampler - > to_rate , resampler - > from_rate , to_size ) / 2 ;
resampler - > to = malloc ( resampler - > to_size * sizeof ( int16_t ) * resampler - > channels ) ;
switch_assert ( resampler - > to ) ;
2006-01-02 17:28:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2009-02-13 23:35:17 +00:00
SWITCH_DECLARE ( uint32_t ) switch_resample_process ( switch_audio_resampler_t * resampler , int16_t * src , uint32_t srclen )
2006-01-02 17:28:59 +00:00
{
2015-06-05 23:46:56 -05:00
int to_size = switch_resample_calc_buffer_size ( resampler - > to_rate , resampler - > from_rate , srclen ) / 2 ;
if ( to_size > resampler - > to_size ) {
resampler - > to_size = to_size ;
resampler - > to = realloc ( resampler - > to , resampler - > to_size * sizeof ( int16_t ) * resampler - > channels ) ;
switch_assert ( resampler - > to ) ;
2015-06-04 13:13:25 -05:00
}
2017-01-06 02:10:15 -05:00
2009-02-13 23:35:17 +00:00
resampler - > to_len = resampler - > to_size ;
2009-07-23 15:55:13 +00:00
speex_resampler_process_interleaved_int ( resampler - > resampler , src , & srclen , resampler - > to , & resampler - > to_len ) ;
2009-02-13 23:35:17 +00:00
return resampler - > to_len ;
2006-01-02 17:28:59 +00:00
}
2007-12-12 21:30:55 +00:00
SWITCH_DECLARE ( void ) switch_resample_destroy ( switch_audio_resampler_t * * resampler )
2006-01-02 17:28:59 +00:00
{
2007-12-12 21:30:55 +00:00
if ( resampler & & * resampler ) {
if ( ( * resampler ) - > resampler ) {
2009-02-13 23:35:17 +00:00
speex_resampler_destroy ( ( * resampler ) - > resampler ) ;
2007-12-12 21:30:55 +00:00
}
2009-02-13 23:35:17 +00:00
free ( ( * resampler ) - > to ) ;
free ( * resampler ) ;
2007-12-12 21:30:55 +00:00
* resampler = NULL ;
}
2006-01-02 17:28:59 +00:00
}
2006-03-30 23:02:50 +00:00
SWITCH_DECLARE ( switch_size_t ) switch_float_to_short ( float * f , short * s , switch_size_t len )
2006-01-02 17:28:59 +00:00
{
2006-03-30 23:02:50 +00:00
switch_size_t i ;
2006-01-02 17:28:59 +00:00
float ft ;
2006-01-20 15:05:05 +00:00
for ( i = 0 ; i < len ; i + + ) {
2006-01-02 17:28:59 +00:00
ft = f [ i ] * NORMFACT ;
2006-01-20 15:05:05 +00:00
if ( ft > = 0 ) {
s [ i ] = ( short ) ( ft + 0.5 ) ;
2006-01-02 17:28:59 +00:00
} else {
2006-01-20 15:05:05 +00:00
s [ i ] = ( short ) ( ft - 0.5 ) ;
2006-01-02 17:28:59 +00:00
}
2006-01-20 15:05:05 +00:00
if ( ( float ) s [ i ] > MAXSAMPLE )
2009-01-25 01:40:50 +00:00
s [ i ] = ( short ) MAXSAMPLE / 2 ;
2006-01-20 15:05:05 +00:00
if ( s [ i ] < ( short ) - MAXSAMPLE )
2009-01-25 01:40:50 +00:00
s [ i ] = ( short ) - MAXSAMPLE / 2 ;
2006-01-02 17:28:59 +00:00
}
return len ;
}
SWITCH_DECLARE ( int ) switch_char_to_float ( char * c , float * f , int len )
{
int i ;
if ( len % 2 ) {
2006-01-20 15:05:05 +00:00
return ( - 1 ) ;
2006-01-02 17:28:59 +00:00
}
2006-01-20 15:05:05 +00:00
for ( i = 1 ; i < len ; i + = 2 ) {
f [ ( int ) ( i / 2 ) ] = ( float ) ( ( ( c [ i ] ) * 0x100 ) + c [ i - 1 ] ) ;
f [ ( int ) ( i / 2 ) ] / = NORMFACT ;
if ( f [ ( int ) ( i / 2 ) ] > MAXSAMPLE )
f [ ( int ) ( i / 2 ) ] = MAXSAMPLE ;
if ( f [ ( int ) ( i / 2 ) ] < - MAXSAMPLE )
f [ ( int ) ( i / 2 ) ] = - MAXSAMPLE ;
2006-01-02 17:28:59 +00:00
}
2006-01-20 15:05:05 +00:00
return len / 2 ;
2006-01-02 17:28:59 +00:00
}
SWITCH_DECLARE ( int ) switch_float_to_char ( float * f , char * c , int len )
{
int i ;
float ft ;
long l ;
2006-01-20 15:05:05 +00:00
for ( i = 0 ; i < len ; i + + ) {
2006-01-02 17:28:59 +00:00
ft = f [ i ] * NORMFACT ;
if ( ft > = 0 ) {
2006-01-20 15:05:05 +00:00
l = ( long ) ( ft + 0.5 ) ;
2006-01-02 17:28:59 +00:00
} else {
2006-01-20 15:05:05 +00:00
l = ( long ) ( ft - 0.5 ) ;
2006-01-02 17:28:59 +00:00
}
2006-01-20 15:05:05 +00:00
c [ i * 2 ] = ( unsigned char ) ( ( l ) & 0xff ) ;
c [ i * 2 + 1 ] = ( unsigned char ) ( ( ( l ) > > 8 ) & 0xff ) ;
2006-01-02 17:28:59 +00:00
}
2006-01-20 15:05:05 +00:00
return len * 2 ;
2006-01-02 17:28:59 +00:00
}
SWITCH_DECLARE ( int ) switch_short_to_float ( short * s , float * f , int len )
{
int i ;
2006-01-20 15:05:05 +00:00
for ( i = 0 ; i < len ; i + + ) {
f [ i ] = ( float ) ( s [ i ] ) / NORMFACT ;
2007-03-04 01:52:52 +00:00
/* f[i] = (float) s[i]; */
2006-01-02 17:28:59 +00:00
}
return len ;
}
SWITCH_DECLARE ( void ) switch_swap_linear ( int16_t * buf , int len )
{
int i ;
for ( i = 0 ; i < len ; i + + ) {
2006-01-20 15:05:05 +00:00
buf [ i ] = ( ( buf [ i ] > > 8 ) & 0x00ff ) | ( ( buf [ i ] < < 8 ) & 0xff00 ) ;
2006-01-02 17:28:59 +00:00
}
2006-01-02 18:31:50 +00:00
}
2006-10-25 01:00:26 +00:00
2014-06-13 04:49:37 +05:00
SWITCH_DECLARE ( void ) switch_generate_sln_silence ( int16_t * data , uint32_t samples , uint32_t channels , uint32_t divisor )
2007-03-21 18:50:51 +00:00
{
2014-06-13 04:49:37 +05:00
int16_t s ;
uint32_t x , i , j ;
2007-03-23 21:54:16 +00:00
int sum_rnd = 0 ;
2009-03-23 01:59:35 +00:00
int16_t rnd2 = ( int16_t ) switch_micro_time_now ( ) + ( int16_t ) ( intptr_t ) data ;
2007-03-21 18:50:51 +00:00
2014-06-13 04:49:37 +05:00
if ( channels = = 0 ) channels = 1 ;
2007-03-21 18:50:51 +00:00
assert ( divisor ) ;
2007-03-29 22:31:56 +00:00
2011-05-25 23:16:24 -04:00
if ( divisor = = ( uint32_t ) - 1 ) {
2013-03-27 13:52:03 -05:00
memset ( data , 0 , samples * 2 ) ;
2011-05-25 23:16:24 -04:00
return ;
}
2007-03-29 22:31:56 +00:00
for ( i = 0 ; i < samples ; i + + , sum_rnd = 0 ) {
2008-12-09 00:32:51 +00:00
for ( x = 0 ; x < 6 ; x + + ) {
rnd2 = rnd2 * 31821U + 13849U ;
2010-02-06 03:38:24 +00:00
sum_rnd + = rnd2 ;
2007-03-21 18:50:51 +00:00
}
2009-01-30 23:43:12 +00:00
2017-01-06 02:10:15 -05:00
s = ( int16_t ) ( ( int16_t ) sum_rnd / ( int ) divisor ) ;
2009-01-30 23:43:12 +00:00
2014-06-13 04:49:37 +05:00
for ( j = 0 ; j < channels ; j + + ) {
* data = s ;
2017-01-06 02:10:15 -05:00
data + + ;
2009-01-30 23:43:12 +00:00
}
2014-06-13 04:49:37 +05:00
2009-01-30 23:43:12 +00:00
}
}
2015-06-12 23:55:24 -05:00
SWITCH_DECLARE ( uint32_t ) switch_merge_sln ( int16_t * data , uint32_t samples , int16_t * other_data , uint32_t other_samples , int channels )
2007-11-30 22:56:01 +00:00
{
int i ;
int32_t x , z ;
2015-06-12 23:55:24 -05:00
if ( channels = = 0 ) channels = 1 ;
2007-11-30 22:56:01 +00:00
if ( samples > other_samples ) {
x = other_samples ;
} else {
x = samples ;
}
2015-06-12 23:55:24 -05:00
for ( i = 0 ; i < x * channels ; i + + ) {
2007-11-30 22:56:01 +00:00
z = data [ i ] + other_data [ i ] ;
switch_normalize_to_16bit ( z ) ;
data [ i ] = ( int16_t ) z ;
}
return x ;
}
2012-05-07 13:44:10 -05:00
2015-06-12 23:55:24 -05:00
SWITCH_DECLARE ( uint32_t ) switch_unmerge_sln ( int16_t * data , uint32_t samples , int16_t * other_data , uint32_t other_samples , int channels )
2012-05-07 13:44:10 -05:00
{
int i ;
int32_t x ;
2015-06-12 23:55:24 -05:00
if ( channels = = 0 ) channels = 1 ;
2012-05-07 13:44:10 -05:00
if ( samples > other_samples ) {
x = other_samples ;
} else {
x = samples ;
}
2015-06-12 23:55:24 -05:00
for ( i = 0 ; i < x * channels ; i + + ) {
2012-05-07 13:44:10 -05:00
data [ i ] - = other_data [ i ] ;
}
return x ;
}
2014-06-12 22:06:33 +05:00
SWITCH_DECLARE ( void ) switch_mux_channels ( int16_t * data , switch_size_t samples , uint32_t orig_channels , uint32_t channels )
2009-01-15 17:47:21 +00:00
{
2009-02-13 19:03:34 +00:00
switch_size_t i = 0 ;
2013-04-17 15:17:51 -05:00
uint32_t j = 0 ;
2010-02-06 03:38:24 +00:00
2014-06-12 22:06:33 +05:00
switch_assert ( channels < 11 ) ;
2014-09-17 02:14:54 +05:00
2014-06-12 22:06:33 +05:00
if ( orig_channels > channels ) {
2019-03-14 14:27:06 +00:00
if ( channels = = 1 ) {
for ( i = 0 ; i < samples ; i + + ) {
2019-03-19 13:05:51 +00:00
int32_t z = 0 ;
2019-03-14 14:27:06 +00:00
for ( j = 0 ; j < orig_channels ; j + + ) {
2019-03-19 13:05:51 +00:00
z + = ( int16_t ) data [ i * orig_channels + j ] ;
2019-03-14 14:27:06 +00:00
}
2014-06-12 22:06:33 +05:00
switch_normalize_to_16bit ( z ) ;
data [ i ] = ( int16_t ) z ;
}
2019-03-14 14:27:06 +00:00
} else if ( channels = = 2 ) {
int mark_buf = 0 ;
for ( i = 0 ; i < samples ; i + + ) {
2019-03-19 13:05:51 +00:00
int32_t z_left = 0 , z_right = 0 ;
2019-03-14 14:27:06 +00:00
for ( j = 0 ; j < orig_channels ; j + + ) {
if ( j % 2 ) {
2019-03-19 13:05:51 +00:00
z_left + = ( int16_t ) data [ i * orig_channels + j ] ;
2019-03-14 14:27:06 +00:00
} else {
2019-03-19 13:05:51 +00:00
z_right + = ( int16_t ) data [ i * orig_channels + j ] ;
2019-03-14 14:27:06 +00:00
}
}
/* mark_buf will always be smaller than the size of data in bytes because orig_channels > channels */
switch_normalize_to_16bit ( z_left ) ;
data [ mark_buf + + ] = ( int16_t ) z_left ;
switch_normalize_to_16bit ( z_right ) ;
data [ mark_buf + + ] = ( int16_t ) z_right ;
}
}
2014-06-12 22:06:33 +05:00
} else if ( orig_channels < channels ) {
/* interesting problem... take a give buffer and double up every sample in the buffer without using any other buffer.....
This way beats the other i think bacause there is no malloc but I do have to copy the data twice */
# if 1
uint32_t k = 0 , len = samples * orig_channels ;
for ( i = 0 ; i < len ; i + + ) {
data [ i + len ] = data [ i ] ;
}
for ( i = 0 ; i < samples ; i + + ) {
2017-01-06 02:10:15 -05:00
for ( j = 0 ; j < channels ; j + + ) {
2014-06-12 22:06:33 +05:00
data [ k + + ] = data [ i + samples ] ;
}
2009-01-15 17:47:21 +00:00
}
2014-06-12 22:06:33 +05:00
2017-01-06 02:10:15 -05:00
# else
2014-06-12 22:06:33 +05:00
uint32_t k = 0 , len = samples * 2 * orig_channels ;
int16_t * orig = NULL ;
switch_zmalloc ( orig , len ) ;
memcpy ( orig , data , len ) ;
for ( i = 0 ; i < samples ; i + + ) {
2017-01-06 02:10:15 -05:00
for ( j = 0 ; j < channels ; j + + ) {
2014-06-12 22:06:33 +05:00
data [ k + + ] = orig [ i ] ;
}
}
2017-01-06 02:10:15 -05:00
2014-06-12 22:06:33 +05:00
free ( orig ) ;
# endif
2009-01-15 17:47:21 +00:00
}
}
2011-02-20 14:37:23 -06:00
SWITCH_DECLARE ( void ) switch_change_sln_volume_granular ( int16_t * data , uint32_t samples , int32_t vol )
{
double newrate = 0 ;
2021-04-02 12:18:16 -07:00
// change in dB mapped to ratio for output sample
// computed as (powf(10.0f, (float)(change_in_dB) / 20.0f))
static const double pos [ SWITCH_GRANULAR_VOLUME_MAX ] = {
1.122018 , 1.258925 , 1.412538 , 1.584893 , 1.778279 , 1.995262 , 2.238721 , 2.511887 , 2.818383 , 3.162278 ,
3.548134 , 3.981072 , 4.466835 , 5.011872 , 5.623413 , 6.309574 , 7.079458 , 7.943282 , 8.912509 , 10.000000 ,
11.220183 , 12.589254 , 14.125375 , 15.848933 , 17.782795 , 19.952621 , 22.387213 , 25.118862 , 28.183832 , 31.622776 ,
35.481335 , 39.810719 , 44.668358 , 50.118729 , 56.234131 , 63.095726 , 70.794586 , 79.432816 , 89.125107 , 100.000000 ,
112.201836 , 125.892517 , 141.253784 , 158.489334 , 177.827942 , 199.526215 , 223.872070 , 251.188705 , 281.838318 , 316.227753
} ;
static const double neg [ SWITCH_GRANULAR_VOLUME_MAX ] = {
0.891251 , 0.794328 , 0.707946 , 0.630957 , 0.562341 , 0.501187 , 0.446684 , 0.398107 , 0.354813 , 0.316228 ,
0.281838 , 0.251189 , 0.223872 , 0.199526 , 0.177828 , 0.158489 , 0.141254 , 0.125893 , 0.112202 , 0.100000 ,
0.089125 , 0.079433 , 0.070795 , 0.063096 , 0.056234 , 0.050119 , 0.044668 , 0.039811 , 0.035481 , 0.031623 ,
0.028184 , 0.025119 , 0.022387 , 0.019953 , 0.017783 , 0.015849 , 0.014125 , 0.012589 , 0.011220 , 0.010000 ,
0.008913 , 0.007943 , 0.007079 , 0.006310 , 0.005623 , 0.005012 , 0.004467 , 0.003981 , 0.003548 , 0.000000 // NOTE mapped -50 dB ratio to total silence instead of 0.003162
} ;
const double * chart ;
2011-02-20 14:37:23 -06:00
uint32_t i ;
if ( vol = = 0 ) return ;
switch_normalize_volume_granular ( vol ) ;
if ( vol > 0 ) {
chart = pos ;
} else {
chart = neg ;
}
2017-01-06 02:10:15 -05:00
2011-02-20 14:37:23 -06:00
i = abs ( vol ) - 1 ;
2017-01-06 02:10:15 -05:00
2021-04-02 12:18:16 -07:00
switch_assert ( i < SWITCH_GRANULAR_VOLUME_MAX ) ;
2011-02-20 14:37:23 -06:00
newrate = chart [ i ] ;
if ( newrate ) {
int32_t tmp ;
uint32_t x ;
int16_t * fp = data ;
for ( x = 0 ; x < samples ; x + + ) {
2011-02-20 14:50:20 -06:00
tmp = ( int32_t ) ( fp [ x ] * newrate ) ;
2011-02-20 14:37:23 -06:00
switch_normalize_to_16bit ( tmp ) ;
fp [ x ] = ( int16_t ) tmp ;
}
2013-12-18 00:55:29 +05:00
} else {
memset ( data , 0 , samples * 2 ) ;
2011-02-20 14:37:23 -06:00
}
}
2006-10-25 01:00:26 +00:00
SWITCH_DECLARE ( void ) switch_change_sln_volume ( int16_t * data , uint32_t samples , int32_t vol )
{
2007-03-29 22:31:56 +00:00
double newrate = 0 ;
2011-02-25 18:09:58 -06:00
double pos [ 4 ] = { 1.3 , 2.3 , 3.3 , 4.3 } ;
double neg [ 4 ] = { .80 , .60 , .40 , .20 } ;
double * chart ;
uint32_t i ;
if ( vol = = 0 ) return ;
2006-10-25 01:00:26 +00:00
switch_normalize_volume ( vol ) ;
if ( vol > 0 ) {
2011-02-25 18:09:58 -06:00
chart = pos ;
} else {
chart = neg ;
2006-10-25 01:00:26 +00:00
}
2017-01-06 02:10:15 -05:00
2011-02-25 18:09:58 -06:00
i = abs ( vol ) - 1 ;
2017-01-06 02:10:15 -05:00
2011-02-25 18:09:58 -06:00
switch_assert ( i < 4 ) ;
2006-10-25 01:00:26 +00:00
2011-02-25 18:09:58 -06:00
newrate = chart [ i ] ;
2006-10-25 01:00:26 +00:00
if ( newrate ) {
int32_t tmp ;
2006-10-25 04:47:08 +00:00
uint32_t x ;
2006-10-25 01:00:26 +00:00
int16_t * fp = data ;
for ( x = 0 ; x < samples ; x + + ) {
2011-02-25 18:09:58 -06:00
tmp = ( int32_t ) ( fp [ x ] * newrate ) ;
2006-10-25 01:00:26 +00:00
switch_normalize_to_16bit ( tmp ) ;
2007-03-29 22:31:56 +00:00
fp [ x ] = ( int16_t ) tmp ;
2006-10-25 01:00:26 +00:00
}
}
}
2017-01-18 13:19:41 -06:00
struct switch_agc_s {
switch_memory_pool_t * pool ;
uint32_t energy_avg ;
uint32_t margin ;
uint32_t change_factor ;
2017-04-27 15:28:59 -05:00
char * token ;
2017-01-18 13:19:41 -06:00
int vol ;
uint32_t score ;
uint32_t score_count ;
uint32_t score_sum ;
uint32_t score_avg ;
uint32_t score_over ;
uint32_t score_under ;
uint32_t period_len ;
2017-01-18 15:12:08 -06:00
uint32_t low_energy_point ;
2017-01-18 13:19:41 -06:00
} ;
2017-01-05 18:34:01 -06:00
SWITCH_DECLARE ( void ) switch_agc_set ( switch_agc_t * agc , uint32_t energy_avg ,
uint32_t low_energy_point , uint32_t margin , uint32_t change_factor , uint32_t period_len )
{
agc - > energy_avg = energy_avg ;
agc - > margin = margin ;
agc - > change_factor = change_factor ;
agc - > period_len = period_len ;
agc - > low_energy_point = low_energy_point ;
2021-04-02 12:18:16 -07:00
agc - > score = 0 ;
agc - > score_count = 0 ;
agc - > score_sum = 0 ;
agc - > score_avg = 0 ;
agc - > score_over = 0 ;
agc - > score_under = 0 ;
2017-01-05 18:34:01 -06:00
}
2017-01-18 13:19:41 -06:00
2017-01-18 15:12:08 -06:00
SWITCH_DECLARE ( switch_status_t ) switch_agc_create ( switch_agc_t * * agcP , uint32_t energy_avg ,
uint32_t low_energy_point , uint32_t margin , uint32_t change_factor , uint32_t period_len )
2017-01-18 13:19:41 -06:00
{
switch_agc_t * agc ;
switch_memory_pool_t * pool ;
2017-04-27 15:28:59 -05:00
char id [ 80 ] = " " ;
2017-01-18 13:19:41 -06:00
switch_assert ( agcP ) ;
switch_core_new_memory_pool ( & pool ) ;
agc = switch_core_alloc ( pool , sizeof ( * agc ) ) ;
agc - > pool = pool ;
2017-01-05 18:34:01 -06:00
switch_agc_set ( agc , energy_avg , low_energy_point , margin , change_factor , period_len ) ;
2017-01-18 13:19:41 -06:00
2017-04-27 15:28:59 -05:00
switch_snprintf ( id , sizeof ( id ) , " %p " , ( void * ) agc ) ;
switch_agc_set_token ( agc , id ) ;
2017-01-18 13:19:41 -06:00
* agcP = agc ;
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_DECLARE ( void ) switch_agc_destroy ( switch_agc_t * * agcP )
{
switch_agc_t * agc ;
switch_assert ( agcP ) ;
agc = * agcP ;
* agcP = NULL ;
if ( agc ) {
switch_memory_pool_t * pool = agc - > pool ;
switch_core_destroy_memory_pool ( & pool ) ;
}
}
SWITCH_DECLARE ( void ) switch_agc_set_energy_avg ( switch_agc_t * agc , uint32_t energy_avg )
{
switch_assert ( agc ) ;
agc - > energy_avg = energy_avg ;
}
2017-01-18 15:12:08 -06:00
SWITCH_DECLARE ( void ) switch_agc_set_energy_low ( switch_agc_t * agc , uint32_t low_energy_point )
{
switch_assert ( agc ) ;
agc - > low_energy_point = low_energy_point ;
}
2017-04-27 15:28:59 -05:00
SWITCH_DECLARE ( void ) switch_agc_set_token ( switch_agc_t * agc , const char * token )
{
agc - > token = switch_core_strdup ( agc - > pool , token ) ;
}
2017-01-18 13:19:41 -06:00
SWITCH_DECLARE ( switch_status_t ) switch_agc_feed ( switch_agc_t * agc , int16_t * data , uint32_t samples , uint32_t channels )
{
if ( ! channels ) channels = 1 ;
if ( agc - > vol ) {
switch_change_sln_volume_granular ( data , samples * channels , agc - > vol ) ;
}
if ( agc - > energy_avg ) {
uint32_t energy = 0 ;
int i ;
for ( i = 0 ; i < samples * channels ; i + + ) {
energy + = abs ( data [ i ] ) ;
}
2019-11-14 07:26:00 +00:00
if ( samples ) {
agc - > score = energy / samples * channels ;
}
2017-01-18 13:19:41 -06:00
agc - > score_sum + = agc - > score ;
agc - > score_count + + ;
if ( agc - > score_count > agc - > period_len ) {
agc - > score_avg = ( int ) ( ( double ) agc - > score_sum / agc - > score_count ) ;
agc - > score_count = 0 ;
agc - > score_sum = 0 ;
2017-05-03 15:25:04 -05:00
if ( agc - > score_avg > agc - > energy_avg ) {
if ( agc - > score_avg - agc - > energy_avg > agc - > margin ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " [%s] OVER++ SCORE AVG: %d ENERGY AVG: %d MARGIN: %d \n " ,
agc - > token , agc - > score_avg , agc - > energy_avg , agc - > margin ) ;
agc - > score_over + + ;
2021-04-02 12:18:16 -07:00
} else {
agc - > score_over = 0 ;
2017-05-03 15:25:04 -05:00
}
2017-01-18 13:19:41 -06:00
} else {
agc - > score_over = 0 ;
}
2017-05-03 15:25:04 -05:00
if ( agc - > score_avg < agc - > low_energy_point ) {
agc - > score_under = agc - > change_factor + 1 ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " [%s] BELOW LOW POINT, SCORE AVG: %d ENERGY AVG: %d MARGIN: %d \n " ,
agc - > token , agc - > score_avg , agc - > energy_avg , agc - > margin ) ;
} else if ( ( ( agc - > score_avg < agc - > energy_avg ) & & ( agc - > energy_avg - agc - > score_avg > agc - > margin ) ) ) {
2017-04-27 15:28:59 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " [%s] UNDER++ SCORE AVG: %d ENERGY AVG: %d MARGIN: %d \n " ,
agc - > token , agc - > score_avg , agc - > energy_avg , agc - > margin ) ;
2017-01-18 13:19:41 -06:00
agc - > score_under + + ;
} else {
agc - > score_under = 0 ;
}
2017-04-27 15:28:59 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " [%s] AVG %d over: %d under: %d \n " ,
agc - > token , agc - > score_avg , agc - > score_over , agc - > score_under ) ;
2017-01-18 13:19:41 -06:00
if ( agc - > score_over > agc - > change_factor ) {
agc - > vol - - ;
switch_normalize_volume_granular ( agc - > vol ) ;
2017-04-27 15:28:59 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " [%s] VOL DOWN %d \n " , agc - > token , agc - > vol ) ;
2017-05-03 15:25:04 -05:00
//agc->score_over = 0;
2017-01-18 13:19:41 -06:00
} else if ( agc - > score_under > agc - > change_factor ) {
agc - > vol + + ;
switch_normalize_volume_granular ( agc - > vol ) ;
2017-04-27 15:28:59 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG1 , " [%s] VOL UP %d \n " , agc - > token , agc - > vol ) ;
2017-05-03 15:25:04 -05:00
//agc->score_under = 0;
2017-01-18 13:19:41 -06:00
}
}
}
return SWITCH_STATUS_SUCCESS ;
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2013-06-25 11:50:17 -05:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet :
2006-11-27 22:30:48 +00:00
*/