Asterisk - The Open Source Telephony Project  21.4.1
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"

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 = "da6642af068ee5e6490c5b1d2cc1d238" , .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.

Function Documentation

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 CORRELATION_SPAN, plc_state_t::history, plc_state_t::missing_samples, plc_state_t::pitch, plc_state_t::pitch_offset, plc_state_t::pitchbuf, PLC_HISTORY_LEN, PLC_PITCH_MAX, and PLC_PITCH_MIN.

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 */
190  normalise_history(s);
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 }
int pitch
Definition: plc.h:112
#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
int missing_samples
Definition: plc.h:108
#define PLC_PITCH_MIN
Definition: plc.h:93
#define CORRELATION_SPAN
Definition: plc.h:99
int pitch_offset
Definition: plc.h:110
float pitchbuf[PLC_PITCH_MIN]
Definition: plc.h:114
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 }
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 plc_state_t::missing_samples, plc_state_t::pitch, plc_state_t::pitch_offset, and plc_state_t::pitchbuf.

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 }
int pitch
Definition: plc.h:112
int missing_samples
Definition: plc.h:108
int pitch_offset
Definition: plc.h:110
float pitchbuf[PLC_PITCH_MIN]
Definition: plc.h:114