Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions
plc.h File Reference

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

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  plc_state_t
 

Macros

#define CORRELATION_SPAN   160
 
#define PLC_HISTORY_LEN   (CORRELATION_SPAN + PLC_PITCH_MIN)
 
#define PLC_PITCH_MAX   40
 
#define PLC_PITCH_MIN   120
 
#define PLC_PITCH_OVERLAP_MAX   (PLC_PITCH_MIN >> 2)
 

Functions

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...
 

Detailed Description

SpanDSP - a series of DSP components for telephony.

plc.h

Author
Steve Underwood steve[email protected][email protected][email protected]ppice[email protected].org

Copyright (C) 2004 Steve Underwood

All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

This version may be optionally licenced under the GNU LGPL licence.

A license has been granted to Digium (via disclaimer) for the use of this code.

Definition in file plc.h.

Macro Definition Documentation

◆ CORRELATION_SPAN

#define CORRELATION_SPAN   160

The length over which the AMDF function looks for similarity (20 ms)

Definition at line 99 of file plc.h.

Referenced by plc_fillin().

◆ PLC_HISTORY_LEN

#define PLC_HISTORY_LEN   (CORRELATION_SPAN + PLC_PITCH_MIN)

History buffer length. The buffer much also be at leat 1.25 times PLC_PITCH_MIN, but that is much smaller than the buffer needs to be for the pitch assessment.

Definition at line 103 of file plc.h.

Referenced by normalise_history(), plc_fillin(), and save_history().

◆ PLC_PITCH_MAX

#define PLC_PITCH_MAX   40

Maximum allowed pitch (200 Hz)

Definition at line 95 of file plc.h.

Referenced by plc_fillin().

◆ PLC_PITCH_MIN

#define PLC_PITCH_MIN   120

Minimum allowed pitch (66 Hz)

Definition at line 93 of file plc.h.

Referenced by plc_fillin().

◆ PLC_PITCH_OVERLAP_MAX

#define PLC_PITCH_OVERLAP_MAX   (PLC_PITCH_MIN >> 2)

Maximum pitch OLA window

Definition at line 97 of file plc.h.

Function Documentation

◆ 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