RTS API Documentation  1.10.11
Data Structures | Macros | Functions
switch_resample.h File Reference

Audio Resample Code. More...

#include <switch.h>
+ Include dependency graph for switch_resample.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  switch_audio_resampler_t
 An audio resampling handle. More...
 

Macros

#define switch_normalize_volume(x)   if (x > 4) x = 4; if (x < -4) x = -4;
 
#define SWITCH_GRANULAR_VOLUME_MAX   50
 
#define switch_normalize_volume_granular(x)   if (x > SWITCH_GRANULAR_VOLUME_MAX) x = SWITCH_GRANULAR_VOLUME_MAX; if (x < -SWITCH_GRANULAR_VOLUME_MAX) x = -SWITCH_GRANULAR_VOLUME_MAX;
 
#define SWITCH_RESAMPLE_QUALITY   2
 
#define switch_resample_create(_n, _fr, _tr, _ts, _q, _c)   switch_resample_perform_create(_n, _fr, _tr, _ts, _q, _c, __FILE__, __SWITCH_FUNC__, __LINE__)
 
#define switch_resample_calc_buffer_size(_to, _from, _srclen)   ((uint32_t)(((float)_to / (float)_from) * (float)_srclen) * 2)
 

Functions

switch_status_t switch_resample_perform_create (switch_audio_resampler_t **new_resampler, uint32_t from_rate, uint32_t to_rate, uint32_t to_size, int quality, uint32_t channels, const char *file, const char *func, int line)
 Prepare a new resampler handle. More...
 
void switch_resample_destroy (switch_audio_resampler_t **resampler)
 Destroy an existing resampler handle. More...
 
uint32_t switch_resample_process (switch_audio_resampler_t *resampler, int16_t *src, uint32_t srclen)
 Resample one float buffer into another using specifications of a given handle. More...
 
switch_size_t switch_float_to_short (float *f, short *s, switch_size_t len)
 Convert an array of floats to an array of shorts. More...
 
int switch_char_to_float (char *c, float *f, int len)
 Convert an array of chars to an array of floats. More...
 
int switch_float_to_char (float *f, char *c, int len)
 Convert an array of floats to an array of chars. More...
 
int switch_short_to_float (short *s, float *f, int len)
 Convert an array of shorts to an array of floats. More...
 
void switch_swap_linear (int16_t *buf, int len)
 Perform a byteswap on a buffer of 16 bit samples. More...
 
void switch_generate_sln_silence (int16_t *data, uint32_t samples, uint32_t channels, uint32_t divisor)
 Generate static noise. More...
 
void switch_change_sln_volume (int16_t *data, uint32_t samples, int32_t vol)
 Change the volume of a signed linear audio frame. More...
 
void switch_change_sln_volume_granular (int16_t *data, uint32_t samples, int32_t vol)
 Change the volume of a signed linear audio frame with more granularity. More...
 
uint32_t switch_merge_sln (int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels)
 
uint32_t switch_unmerge_sln (int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples, int channels)
 
void switch_mux_channels (int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels)
 
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)
 
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)
 
void switch_agc_destroy (switch_agc_t **agcP)
 
switch_status_t switch_agc_feed (switch_agc_t *agc, int16_t *data, uint32_t samples, uint32_t channels)
 
void switch_agc_set_energy_avg (switch_agc_t *agc, uint32_t energy_avg)
 
void switch_agc_set_energy_low (switch_agc_t *agc, uint32_t low_energy_point)
 
void switch_agc_set_token (switch_agc_t *agc, const char *token)
 

Detailed Description

Audio Resample Code.

This module implements a generic interface for doing audio resampling it currently uses libresample but can be ported to any resample library with a little effort. I decided against making this interface pluggable because there are not many options in terms of resample libraries so it seemed like a waste but I did opt to frontend the interface in case a better way comes along some day. =D

Definition in file switch_resample.h.

Macro Definition Documentation

◆ SWITCH_GRANULAR_VOLUME_MAX

#define SWITCH_GRANULAR_VOLUME_MAX   50

Definition at line 42 of file switch_resample.h.

Referenced by switch_change_sln_volume_granular().

◆ switch_normalize_volume

#define switch_normalize_volume (   x)    if (x > 4) x = 4; if (x < -4) x = -4;

Definition at line 41 of file switch_resample.h.

Referenced by switch_change_sln_volume(), and switch_ivr_process_fh().

◆ switch_normalize_volume_granular

#define switch_normalize_volume_granular (   x)    if (x > SWITCH_GRANULAR_VOLUME_MAX) x = SWITCH_GRANULAR_VOLUME_MAX; if (x < -SWITCH_GRANULAR_VOLUME_MAX) x = -SWITCH_GRANULAR_VOLUME_MAX;

◆ switch_resample_calc_buffer_size

#define switch_resample_calc_buffer_size (   _to,
  _from,
  _srclen 
)    ((uint32_t)(((float)_to / (float)_from) * (float)_srclen) * 2)

◆ SWITCH_RESAMPLE_QUALITY

#define SWITCH_RESAMPLE_QUALITY   2

Function Documentation

◆ switch_agc_create()

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 
)

Definition at line 470 of file switch_resample.c.

References switch_agc_s::pool, switch_agc_set(), switch_agc_set_token(), switch_assert, switch_core_alloc, switch_core_new_memory_pool, switch_snprintf(), and SWITCH_STATUS_SUCCESS.

472 {
473  switch_agc_t *agc;
475  char id[80] = "";
476 
477  switch_assert(agcP);
478 
480 
481  agc = switch_core_alloc(pool, sizeof(*agc));
482  agc->pool = pool;
483 
484  switch_agc_set(agc, energy_avg, low_energy_point, margin, change_factor, period_len);
485 
486 
487  switch_snprintf(id, sizeof(id), "%p", (void *)agc);
488  switch_agc_set_token(agc, id);
489 
490  *agcP = agc;
491 
492  return SWITCH_STATUS_SUCCESS;
493 }
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
switch_memory_pool_t * pool
void switch_agc_set_token(switch_agc_t *agc, const char *token)
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
switch_memory_pool_t * pool
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
struct fspr_pool_t switch_memory_pool_t
#define switch_assert(expr)
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)

◆ switch_agc_destroy()

void switch_agc_destroy ( switch_agc_t **  agcP)

Definition at line 495 of file switch_resample.c.

References switch_agc_s::pool, switch_assert, and switch_core_destroy_memory_pool.

496 {
497  switch_agc_t *agc;
498 
499  switch_assert(agcP);
500 
501  agc = *agcP;
502  *agcP = NULL;
503 
504  if (agc) {
507  }
508 }
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
switch_memory_pool_t * pool
struct fspr_pool_t switch_memory_pool_t
#define switch_assert(expr)

◆ switch_agc_feed()

switch_status_t switch_agc_feed ( switch_agc_t agc,
int16_t *  data,
uint32_t  samples,
uint32_t  channels 
)

Definition at line 529 of file switch_resample.c.

References switch_agc_s::change_factor, switch_agc_s::energy_avg, switch_agc_s::low_energy_point, switch_agc_s::margin, switch_agc_s::period_len, switch_agc_s::score, switch_agc_s::score_avg, switch_agc_s::score_count, switch_agc_s::score_over, switch_agc_s::score_sum, switch_agc_s::score_under, switch_change_sln_volume_granular(), SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, switch_log_printf(), switch_normalize_volume_granular, SWITCH_STATUS_SUCCESS, switch_agc_s::token, and switch_agc_s::vol.

530 {
531 
532  if (!channels) channels = 1;
533 
534  if (agc->vol) {
535  switch_change_sln_volume_granular(data, samples * channels, agc->vol);
536  }
537 
538  if (agc->energy_avg) {
539  uint32_t energy = 0;
540  int i;
541 
542  for (i = 0; i < samples * channels; i++) {
543  energy += abs(data[i]);
544  }
545 
546  if (samples) {
547  agc->score = energy / samples * channels;
548  }
549  agc->score_sum += agc->score;
550  agc->score_count++;
551 
552  if (agc->score_count > agc->period_len) {
553 
554  agc->score_avg = (int)((double)agc->score_sum / agc->score_count);
555  agc->score_count = 0;
556  agc->score_sum = 0;
557 
558  if (agc->score_avg > agc->energy_avg) {
559  if (agc->score_avg - agc->energy_avg > agc->margin) {
560  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "[%s] OVER++ SCORE AVG: %d ENERGY AVG: %d MARGIN: %d\n",
561  agc->token, agc->score_avg, agc->energy_avg, agc->margin);
562  agc->score_over++;
563  } else {
564  agc->score_over = 0;
565  }
566  } else {
567  agc->score_over = 0;
568  }
569 
570  if (agc->score_avg < agc->low_energy_point) {
571  agc->score_under = agc->change_factor + 1;
572  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "[%s] BELOW LOW POINT, SCORE AVG: %d ENERGY AVG: %d MARGIN: %d\n",
573  agc->token, agc->score_avg, agc->energy_avg, agc->margin);
574  } else if (((agc->score_avg < agc->energy_avg) && (agc->energy_avg - agc->score_avg > agc->margin))) {
575  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "[%s] UNDER++ SCORE AVG: %d ENERGY AVG: %d MARGIN: %d\n",
576  agc->token, agc->score_avg, agc->energy_avg, agc->margin);
577  agc->score_under++;
578  } else {
579  agc->score_under = 0;
580  }
581 
582  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "[%s] AVG %d over: %d under: %d\n",
583  agc->token, agc->score_avg, agc->score_over, agc->score_under);
584 
585  if (agc->score_over > agc->change_factor) {
586  agc->vol--;
588  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "[%s] VOL DOWN %d\n", agc->token, agc->vol);
589  //agc->score_over = 0;
590  } else if (agc->score_under > agc->change_factor) {
591  agc->vol++;
593  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "[%s] VOL UP %d\n", agc->token, agc->vol);
594  //agc->score_under = 0;
595  }
596 
597  }
598 
599  }
600 
601  return SWITCH_STATUS_SUCCESS;
602 }
uint32_t period_len
#define SWITCH_CHANNEL_LOG
uint32_t score_sum
#define switch_normalize_volume_granular(x)
uint32_t score_count
uint32_t change_factor
uint32_t energy_avg
uint32_t low_energy_point
void switch_change_sln_volume_granular(int16_t *data, uint32_t samples, int32_t vol)
Change the volume of a signed linear audio frame with more granularity.
uint32_t score_avg
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
uint32_t score_over
uint32_t score_under

◆ switch_agc_set()

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 
)

Definition at line 453 of file switch_resample.c.

References switch_agc_s::change_factor, switch_agc_s::energy_avg, switch_agc_s::low_energy_point, switch_agc_s::margin, switch_agc_s::period_len, switch_agc_s::score, switch_agc_s::score_avg, switch_agc_s::score_count, switch_agc_s::score_over, switch_agc_s::score_sum, and switch_agc_s::score_under.

Referenced by switch_agc_create().

455 {
456  agc->energy_avg = energy_avg;
457  agc->margin = margin;
458  agc->change_factor = change_factor;
459  agc->period_len = period_len;
460  agc->low_energy_point = low_energy_point;
461 
462  agc->score = 0;
463  agc->score_count = 0;
464  agc->score_sum = 0;
465  agc->score_avg = 0;
466  agc->score_over = 0;
467  agc->score_under = 0;
468 }
uint32_t period_len
uint32_t score_sum
uint32_t score_count
uint32_t change_factor
uint32_t energy_avg
uint32_t low_energy_point
uint32_t score_avg
uint32_t score_over
uint32_t score_under

◆ switch_agc_set_energy_avg()

void switch_agc_set_energy_avg ( switch_agc_t agc,
uint32_t  energy_avg 
)

Definition at line 510 of file switch_resample.c.

References switch_agc_s::energy_avg, and switch_assert.

511 {
512  switch_assert(agc);
513 
514  agc->energy_avg = energy_avg;
515 }
uint32_t energy_avg
#define switch_assert(expr)

◆ switch_agc_set_energy_low()

void switch_agc_set_energy_low ( switch_agc_t agc,
uint32_t  low_energy_point 
)

Definition at line 517 of file switch_resample.c.

References switch_agc_s::low_energy_point, and switch_assert.

518 {
519  switch_assert(agc);
520 
521  agc->low_energy_point = low_energy_point;
522 }
uint32_t low_energy_point
#define switch_assert(expr)

◆ switch_agc_set_token()

void switch_agc_set_token ( switch_agc_t agc,
const char *  token 
)

Definition at line 524 of file switch_resample.c.

References switch_agc_s::pool, switch_core_strdup, and switch_agc_s::token.

Referenced by switch_agc_create().

525 {
526  agc->token = switch_core_strdup(agc->pool, token);
527 }
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
switch_memory_pool_t * pool

◆ switch_merge_sln()

uint32_t switch_merge_sln ( int16_t *  data,
uint32_t  samples,
int16_t *  other_data,
uint32_t  other_samples,
int  channels 
)

Definition at line 231 of file switch_resample.c.

References switch_normalize_to_16bit.

Referenced by eavesdrop_callback().

232 {
233  int i;
234  int32_t x, z;
235 
236  if (channels == 0) channels = 1;
237 
238  if (samples > other_samples) {
239  x = other_samples;
240  } else {
241  x = samples;
242  }
243 
244  for (i = 0; i < x * channels; i++) {
245  z = data[i] + other_data[i];
247  data[i] = (int16_t) z;
248  }
249 
250  return x;
251 }
#define switch_normalize_to_16bit(n)
Definition: switch_utils.h:292

◆ switch_mux_channels()

void switch_mux_channels ( int16_t *  data,
switch_size_t  samples,
uint32_t  orig_channels,
uint32_t  channels 
)

Definition at line 274 of file switch_resample.c.

References switch_assert, switch_normalize_to_16bit, and switch_zmalloc.

Referenced by switch_core_file_read(), switch_core_file_write(), switch_core_session_read_frame(), switch_core_session_write_frame(), switch_core_speech_read_tts(), switch_ivr_eavesdrop_session(), and teletone_handler().

275 {
276  switch_size_t i = 0;
277  uint32_t j = 0;
278 
279  switch_assert(channels < 11);
280 
281  if (orig_channels > channels) {
282  if (channels == 1) {
283  for (i = 0; i < samples; i++) {
284  int32_t z = 0;
285  for (j = 0; j < orig_channels; j++) {
286  z += (int16_t) data[i * orig_channels + j];
287  }
289  data[i] = (int16_t) z;
290  }
291  } else if (channels == 2) {
292  int mark_buf = 0;
293  for (i = 0; i < samples; i++) {
294  int32_t z_left = 0, z_right = 0;
295  for (j = 0; j < orig_channels; j++) {
296  if (j % 2) {
297  z_left += (int16_t) data[i * orig_channels + j];
298  } else {
299  z_right += (int16_t) data[i * orig_channels + j];
300  }
301  }
302  /* mark_buf will always be smaller than the size of data in bytes because orig_channels > channels */
304  data[mark_buf++] = (int16_t) z_left;
305  switch_normalize_to_16bit(z_right);
306  data[mark_buf++] = (int16_t) z_right;
307  }
308  }
309  } else if (orig_channels < channels) {
310 
311  /* interesting problem... take a give buffer and double up every sample in the buffer without using any other buffer.....
312  This way beats the other i think bacause there is no malloc but I do have to copy the data twice */
313 #if 1
314  uint32_t k = 0, len = samples * orig_channels;
315 
316  for (i = 0; i < len; i++) {
317  data[i+len] = data[i];
318  }
319 
320  for (i = 0; i < samples; i++) {
321  for (j = 0; j < channels; j++) {
322  data[k++] = data[i + samples];
323  }
324  }
325 
326 #else
327  uint32_t k = 0, len = samples * 2 * orig_channels;
328  int16_t *orig = NULL;
329 
330  switch_zmalloc(orig, len);
331  memcpy(orig, data, len);
332 
333  for (i = 0; i < samples; i++) {
334  for (j = 0; j < channels; j++) {
335  data[k++] = orig[i];
336  }
337  }
338 
339  free(orig);
340 #endif
341 
342  }
343 }
#define switch_zmalloc(ptr, len)
uintptr_t switch_size_t
#define switch_normalize_to_16bit(n)
Definition: switch_utils.h:292
#define switch_assert(expr)

◆ switch_unmerge_sln()

uint32_t switch_unmerge_sln ( int16_t *  data,
uint32_t  samples,
int16_t *  other_data,
uint32_t  other_samples,
int  channels 
)

Definition at line 254 of file switch_resample.c.

Referenced by switch_core_session_read_frame().

255 {
256  int i;
257  int32_t x;
258 
259  if (channels == 0) channels = 1;
260 
261  if (samples > other_samples) {
262  x = other_samples;
263  } else {
264  x = samples;
265  }
266 
267  for (i = 0; i < x * channels; i++) {
268  data[i] -= other_data[i];
269  }
270 
271  return x;
272 }