Asterisk - The Open Source Telephony Project  18.5.0
Macros | Functions | Variables
plc.c File Reference

SpanDSP - a series of DSP components for telephony. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/plc.h"
Include dependency graph for plc.c:

Go to the source code of this file.

Macros

#define ATTENUATION_INCREMENT   0.0025 /* Attenuation per sample */
 
#define FALSE   0
 
#define INT16_MAX   (32767)
 
#define INT16_MIN   (-32767-1)
 
#define ms_to_samples(t)   (((t)*DEFAULT_SAMPLE_RATE)/1000)
 
#define TRUE   (!FALSE)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int __inline__ amdf_pitch (int min_pitch, int max_pitch, int16_t amp[], int len)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int16_t fsaturate (double damp)
 
static int load_module (void)
 
static void normalise_history (plc_state_t *s)
 
int plc_fillin (plc_state_t *s, int16_t amp[], int len)
 Fill-in a block of missing audio samples. More...
 
plc_state_tplc_init (plc_state_t *s)
 Process a block of received V.29 modem audio samples. More...
 
int plc_rx (plc_state_t *s, int16_t amp[], int len)
 Process a block of received audio samples. More...
 
static int reload_module (void)
 
static void save_history (plc_state_t *s, int16_t *buf, int len)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PLC" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

SpanDSP - a series of DSP components for telephony.

Author
Steve Underwood steve.nosp@m.u@co.nosp@m.ppice.nosp@m..org

Definition in file plc.c.

Macro Definition Documentation

◆ ATTENUATION_INCREMENT

#define ATTENUATION_INCREMENT   0.0025 /* Attenuation per sample */

Definition at line 58 of file plc.c.

Referenced by plc_fillin(), and plc_rx().

◆ FALSE

#define FALSE   0

Definition at line 46 of file plc.c.

◆ INT16_MAX

#define INT16_MAX   (32767)

Definition at line 53 of file plc.c.

Referenced by fsaturate().

◆ INT16_MIN

#define INT16_MIN   (-32767-1)

Definition at line 54 of file plc.c.

Referenced by fsaturate().

◆ ms_to_samples

#define ms_to_samples (   t)    (((t)*DEFAULT_SAMPLE_RATE)/1000)

Definition at line 60 of file plc.c.

◆ TRUE

#define TRUE   (!FALSE)

Definition at line 49 of file plc.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 300 of file plc.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 300 of file plc.c.

◆ amdf_pitch()

static int __inline__ amdf_pitch ( int  min_pitch,
int  max_pitch,
int16_t  amp[],
int  len 
)
static

Definition at line 108 of file plc.c.

References abs, and len().

Referenced by plc_fillin().

109 {
110  int i;
111  int j;
112  int acc;
113  int min_acc;
114  int pitch;
115 
116  pitch = min_pitch;
117  min_acc = INT_MAX;
118  for (i = max_pitch; i <= min_pitch; i++) {
119  acc = 0;
120  for (j = 0; j < len; j++)
121  acc += abs(amp[i + j] - amp[j]);
122  if (acc < min_acc) {
123  min_acc = acc;
124  pitch = i;
125  }
126  }
127  return pitch;
128 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define abs(x)
Definition: f2c.h:195

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 300 of file plc.c.

◆ fsaturate()

static int16_t fsaturate ( double  damp)
inlinestatic

Definition at line 62 of file plc.c.

References INT16_MAX, and INT16_MIN.

Referenced by plc_fillin(), and plc_rx().

63 {
64  if (damp > 32767.0)
65  return INT16_MAX;
66  if (damp < -32768.0)
67  return INT16_MIN;
68  return (int16_t) rint(damp);
69 }
short int16_t
Definition: db.h:59
#define INT16_MIN
Definition: plc.c:54
#define INT16_MAX
Definition: plc.c:53

◆ load_module()

static int load_module ( void  )
static

Definition at line 281 of file plc.c.

References AST_MODULE_LOAD_SUCCESS, and reload_module().

Referenced by unload_module().

282 {
283  reload_module();
284 
286 }
static int reload_module(void)
Definition: plc.c:252

◆ normalise_history()

static void normalise_history ( plc_state_t s)
static

Definition at line 94 of file plc.c.

References plc_state_t::buf_ptr, plc_state_t::history, PLC_HISTORY_LEN, and tmp().

Referenced by plc_fillin().

95 {
97 
98  if (s->buf_ptr == 0)
99  return;
100  memcpy(tmp, s->history, sizeof(int16_t)*s->buf_ptr);
101  memmove(s->history, s->history + s->buf_ptr, sizeof(int16_t) * (PLC_HISTORY_LEN - s->buf_ptr));
102  memcpy(s->history + PLC_HISTORY_LEN - s->buf_ptr, tmp, sizeof(int16_t) * s->buf_ptr);
103  s->buf_ptr = 0;
104 }
short int16_t
Definition: db.h:59
int16_t history[PLC_HISTORY_LEN]
Definition: plc.h:116
static int tmp()
Definition: bt_open.c:389
int buf_ptr
Definition: plc.h:118
#define PLC_HISTORY_LEN
Definition: plc.h:103

◆ plc_fillin()

int plc_fillin ( plc_state_t s,
int16_t  amp[],
int  len 
)

Fill-in a block of missing audio samples.

Fill-in a block of missing audio samples.

Parameters
sThe packet loss concealer context.
ampThe audio sample buffer.
lenThe number of samples to be synthesised.
Returns
The number of samples synthesized.

Definition at line 175 of file plc.c.

References amdf_pitch(), ATTENUATION_INCREMENT, CORRELATION_SPAN, fsaturate(), plc_state_t::history, len(), plc_state_t::missing_samples, normalise_history(), plc_state_t::pitch, plc_state_t::pitch_offset, plc_state_t::pitchbuf, PLC_HISTORY_LEN, PLC_PITCH_MAX, PLC_PITCH_MIN, and save_history().

Referenced by adjust_frame_for_plc().

176 {
177  int i;
178  int pitch_overlap;
179  float old_step;
180  float new_step;
181  float old_weight;
182  float new_weight;
183  float gain;
184  int orig_len;
185 
186  orig_len = len;
187  if (s->missing_samples == 0) {
188  /* As the gap in real speech starts we need to assess the last known pitch,
189  and prepare the synthetic data we will use for fill-in */
192  /* We overlap a 1/4 wavelength */
193  pitch_overlap = s->pitch >> 2;
194  /* Cook up a single cycle of pitch, using a single of the real signal with 1/4
195  cycle OLA'ed to make the ends join up nicely */
196  /* The first 3/4 of the cycle is a simple copy */
197  for (i = 0; i < s->pitch - pitch_overlap; i++)
198  s->pitchbuf[i] = s->history[PLC_HISTORY_LEN - s->pitch + i];
199  /* The last 1/4 of the cycle is overlapped with the end of the previous cycle */
200  new_step = 1.0/pitch_overlap;
201  new_weight = new_step;
202  for ( ; i < s->pitch; i++) {
203  s->pitchbuf[i] = s->history[PLC_HISTORY_LEN - s->pitch + i] * (1.0 - new_weight) + s->history[PLC_HISTORY_LEN - 2 * s->pitch + i]*new_weight;
204  new_weight += new_step;
205  }
206  /* We should now be ready to fill in the gap with repeated, decaying cycles
207  of what is in pitchbuf */
208 
209  /* We need to OLA the first 1/4 wavelength of the synthetic data, to smooth
210  it into the previous real data. To avoid the need to introduce a delay
211  in the stream, reverse the last 1/4 wavelength, and OLA with that. */
212  gain = 1.0;
213  new_step = 1.0 / pitch_overlap;
214  old_step = new_step;
215  new_weight = new_step;
216  old_weight = 1.0 - new_step;
217  for (i = 0; i < pitch_overlap; i++) {
218  amp[i] = fsaturate(old_weight * s->history[PLC_HISTORY_LEN - 1 - i] + new_weight * s->pitchbuf[i]);
219  new_weight += new_step;
220  old_weight -= old_step;
221  if (old_weight < 0.0)
222  old_weight = 0.0;
223  }
224  s->pitch_offset = i;
225  } else {
226  gain = 1.0 - s->missing_samples*ATTENUATION_INCREMENT;
227  i = 0;
228  }
229  for ( ; gain > 0.0 && i < len; i++) {
230  amp[i] = s->pitchbuf[s->pitch_offset] * gain;
231  gain -= ATTENUATION_INCREMENT;
232  if (++s->pitch_offset >= s->pitch)
233  s->pitch_offset = 0;
234  }
235  for ( ; i < len; i++)
236  amp[i] = 0;
237  s->missing_samples += orig_len;
238  save_history(s, amp, len);
239  return len;
240 }
#define ATTENUATION_INCREMENT
Definition: plc.c:58
int pitch
Definition: plc.h:112
static void normalise_history(plc_state_t *s)
Definition: plc.c:94
#define PLC_PITCH_MAX
Definition: plc.h:95
int16_t history[PLC_HISTORY_LEN]
Definition: plc.h:116
#define PLC_HISTORY_LEN
Definition: plc.h:103
static int16_t fsaturate(double damp)
Definition: plc.c:62
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int missing_samples
Definition: plc.h:108
static void save_history(plc_state_t *s, int16_t *buf, int len)
Definition: plc.c:71
#define PLC_PITCH_MIN
Definition: plc.h:93
#define CORRELATION_SPAN
Definition: plc.h:99
int pitch_offset
Definition: plc.h:110
static int __inline__ amdf_pitch(int min_pitch, int max_pitch, int16_t amp[], int len)
Definition: plc.c:108
float pitchbuf[PLC_PITCH_MIN]
Definition: plc.h:114

◆ plc_init()

plc_state_t* plc_init ( plc_state_t s)

Process a block of received V.29 modem audio samples.

Process a block of received V.29 modem audio samples.

Parameters
sThe packet loss concealer context.
Returns
A pointer to the he packet loss concealer context.

Definition at line 244 of file plc.c.

245 {
246  memset(s, 0, sizeof(*s));
247  return s;
248 }

◆ plc_rx()

int plc_rx ( plc_state_t s,
int16_t  amp[],
int  len 
)

Process a block of received audio samples.

Process a block of received audio samples.

Parameters
sThe packet loss concealer context.
ampThe audio sample buffer.
lenThe number of samples in the buffer.
Returns
The number of samples in the buffer.

Definition at line 132 of file plc.c.

References ATTENUATION_INCREMENT, fsaturate(), len(), plc_state_t::missing_samples, plc_state_t::pitch, plc_state_t::pitch_offset, plc_state_t::pitchbuf, and save_history().

Referenced by adjust_frame_for_plc().

133 {
134  int i;
135  int pitch_overlap;
136  float old_step;
137  float new_step;
138  float old_weight;
139  float new_weight;
140  float gain;
141 
142  if (s->missing_samples) {
143  /* Although we have a real signal, we need to smooth it to fit well
144  with the synthetic signal we used for the previous block */
145 
146  /* The start of the real data is overlapped with the next 1/4 cycle
147  of the synthetic data. */
148  pitch_overlap = s->pitch >> 2;
149  if (pitch_overlap > len)
150  pitch_overlap = len;
151  gain = 1.0 - s->missing_samples*ATTENUATION_INCREMENT;
152  if (gain < 0.0)
153  gain = 0.0;
154  new_step = 1.0/pitch_overlap;
155  old_step = new_step*gain;
156  new_weight = new_step;
157  old_weight = (1.0 - new_step)*gain;
158  for (i = 0; i < pitch_overlap; i++) {
159  amp[i] = fsaturate(old_weight * s->pitchbuf[s->pitch_offset] + new_weight * amp[i]);
160  if (++s->pitch_offset >= s->pitch)
161  s->pitch_offset = 0;
162  new_weight += new_step;
163  old_weight -= old_step;
164  if (old_weight < 0.0)
165  old_weight = 0.0;
166  }
167  s->missing_samples = 0;
168  }
169  save_history(s, amp, len);
170  return len;
171 }
#define ATTENUATION_INCREMENT
Definition: plc.c:58
int pitch
Definition: plc.h:112
static int16_t fsaturate(double damp)
Definition: plc.c:62
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int missing_samples
Definition: plc.h:108
static void save_history(plc_state_t *s, int16_t *buf, int len)
Definition: plc.c:71
int pitch_offset
Definition: plc.h:110
float pitchbuf[PLC_PITCH_MIN]
Definition: plc.h:114

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 252 of file plc.c.

References ast_config_destroy(), ast_config_load, AST_OPT_FLAG_GENERIC_PLC, AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS, ast_opt_generic_plc, ast_options, ast_set2_flag, ast_true(), ast_variable_browse(), CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by load_module(), and unload_module().

253 {
254  struct ast_variable *var;
255  struct ast_flags config_flags = { 0 };
256  struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
257 
259  return 0;
260  }
261 
262  for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
263  if (!strcasecmp(var->name, "genericplc")) {
265  } else if (!strcasecmp(var->name, "genericplc_on_equal_codecs")) {
267  }
268  }
269  ast_config_destroy(cfg);
270 
271  /*
272  * Force on_equal_codecs to false if generic_plc is false.
273  */
274  if (!ast_opt_generic_plc) {
276  }
277 
278  return 0;
279 }
struct ast_variable * next
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define CONFIG_STATUS_FILEINVALID
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_opt_generic_plc
Definition: options.h:134
#define CONFIG_STATUS_FILEUNCHANGED
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
Structure used to handle boolean flags.
Definition: utils.h:199
#define CONFIG_STATUS_FILEMISSING
struct ast_flags ast_options
Definition: options.c:61

◆ save_history()

static void save_history ( plc_state_t s,
int16_t buf,
int  len 
)
static

Definition at line 71 of file plc.c.

References plc_state_t::buf_ptr, plc_state_t::history, len(), and PLC_HISTORY_LEN.

Referenced by plc_fillin(), and plc_rx().

72 {
73  if (len >= PLC_HISTORY_LEN) {
74  /* Just keep the last part of the new data, starting at the beginning of the buffer */
75  memcpy(s->history, buf + len - PLC_HISTORY_LEN, sizeof(int16_t) * PLC_HISTORY_LEN);
76  s->buf_ptr = 0;
77  return;
78  }
79  if (s->buf_ptr + len > PLC_HISTORY_LEN) {
80  /* Wraps around - must break into two sections */
81  memcpy(s->history + s->buf_ptr, buf, sizeof(int16_t) * (PLC_HISTORY_LEN - s->buf_ptr));
82  len -= (PLC_HISTORY_LEN - s->buf_ptr);
83  memcpy(s->history, buf + (PLC_HISTORY_LEN - s->buf_ptr), sizeof(int16_t)*len);
84  s->buf_ptr = len;
85  return;
86  }
87  /* Can use just one section */
88  memcpy(s->history + s->buf_ptr, buf, sizeof(int16_t)*len);
89  s->buf_ptr += len;
90 }
short int16_t
Definition: db.h:59
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int16_t history[PLC_HISTORY_LEN]
Definition: plc.h:116
int buf_ptr
Definition: plc.h:118
#define PLC_HISTORY_LEN
Definition: plc.h:103
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ unload_module()

static int unload_module ( void  )
static

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PLC" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
static

Definition at line 300 of file plc.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 300 of file plc.c.