- initial import

This commit is contained in:
2018-06-05 11:05:37 +03:00
commit e1a4931375
4673 changed files with 1383093 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
project (webrtc)
# Rely on C++ 11
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (WEBRTC_SOURCES
ilbcfix/xcorr_coef.c
ilbcfix/window32_w32.c
ilbcfix/vq4.c
ilbcfix/vq3.c
ilbcfix/unpack_bits.c
ilbcfix/swap_bytes.c
ilbcfix/state_search.c
ilbcfix/state_construct.c
ilbcfix/split_vq.c
ilbcfix/sort_sq.c
ilbcfix/smooth.c
ilbcfix/smooth_out_data.c
ilbcfix/simple_lsf_quant.c
ilbcfix/simple_lsf_dequant.c
ilbcfix/simple_lpc_analysis.c
ilbcfix/simple_interpolate_lsf.c
ilbcfix/refiner.c
ilbcfix/poly_to_lsp.c
ilbcfix/poly_to_lsf.c
ilbcfix/pack_bits.c
ilbcfix/nearest_neighbor.c
ilbcfix/my_corr.c
ilbcfix/lsp_to_lsf.c
ilbcfix/lsf_to_poly.c
ilbcfix/lsf_to_lsp.c
ilbcfix/lsf_interpolate_to_poly_enc.c
ilbcfix/lsf_interpolate_to_poly_dec.c
ilbcfix/lsf_check.c
ilbcfix/lpc_encode.c
ilbcfix/interpolate.c
ilbcfix/interpolate_samples.c
ilbcfix/init_encode.c
ilbcfix/init_decode.c
ilbcfix/index_conv_enc.c
ilbcfix/index_conv_dec.c
ilbcfix/ilbc.c
ilbcfix/ilbc_encode.c
ilbcfix/ilbc_decode.c
ilbcfix/ilbc_constants.c
ilbcfix/ilbc_cb_search.c
ilbcfix/hp_output.c
ilbcfix/hp_input.c
ilbcfix/get_sync_seq.c
ilbcfix/get_lsp_poly.c
ilbcfix/get_cd_vec.c
ilbcfix/gain_quant.c
ilbcfix/gain_dequant.c
ilbcfix/frame_classify.c
ilbcfix/filtered_cb_vecs.c
ilbcfix/enhancer.c
ilbcfix/enhancer_interface.c
ilbcfix/enh_upsample.c
ilbcfix/energy_inverse.c
ilbcfix/do_plc.c
ilbcfix/decoder_interpolate_lsf.c
ilbcfix/decode_residual.c
ilbcfix/create_augmented_vec.c
ilbcfix/comp_corr.c
ilbcfix/chebyshev.c
ilbcfix/cb_update_best_index.c
ilbcfix/cb_search_core.c
ilbcfix/cb_mem_energy.c
ilbcfix/cb_mem_energy_calc.c
ilbcfix/cb_mem_energy_augmentation.c
ilbcfix/cb_construct.c
ilbcfix/bw_expand.c
ilbcfix/augmented_cb_corr.c
ilbcfix/abs_quant.c
ilbcfix/abs_quant_loop.c
cng/webrtc_cng.c
cng/cng_helpfuns.c
aecm/echo_control_mobile.c
aecm/aecm_core.c
aec/resampler.c
aec/echo_cancellation.c
aec/aec_core.c
aec/aec_core_sse2.c
aec/aec_core_rdft.c
vad/webrtc_vad.c
vad/vad_sp.c
vad/vad_gmm.c
vad/vad_filterbank.c
vad/vad_core.c
vad/vad_const.c
isac/transform.c
isac/spectrum_ar_model_tables.c
isac/pitch_lag_tables.c
isac/pitch_gain_tables.c
isac/pitch_filter.c
isac/pitch_estimator.c
isac/lpc_tables.c
isac/lpc_masking_model.c
isac/lattice.c
isac/isacfix.c
isac/isac_filters.c
isac/isac_decode.c
isac/initialize.c
isac/filterbanks.c
isac/filterbank_tables.c
isac/fft.c
isac/entropy_coding.c
isac/encode.c
isac/decode_plc.c
isac/decode_bwe.c
isac/bandwidth_estimator.c
isac/arith_routines.c
isac/arith_routines_logist.c
isac/arith_routines_hist.c
g711/g711.c
g711/g711_interface.c
ns/nsx_core.c
ns/ns_core.c
ns/noise_suppression.c
ns/noise_suppression_x.c
signal_processing_library/energy.c
signal_processing_library/downsample_fast.c
signal_processing_library/dot_product_with_scale.c
signal_processing_library/division_operations.c
signal_processing_library/cross_correlation.c
signal_processing_library/cos_table.c
signal_processing_library/copy_set_operations.c
signal_processing_library/complex_ifft.c
signal_processing_library/complex_fft.c
signal_processing_library/complex_bit_reverse.c
signal_processing_library/auto_correlation.c
signal_processing_library/auto_corr_to_refl_coef.c
signal_processing_library/add_sat_w32.c
signal_processing_library/add_sat_w16.c
signal_processing_library/webrtc_fft_t_rad.c
signal_processing_library/webrtc_fft_t_1024_8.c
signal_processing_library/vector_scaling_operations.c
signal_processing_library/sub_sat_w32.c
signal_processing_library/sub_sat_w16.c
signal_processing_library/sqrt_of_one_minus_x_squared.c
signal_processing_library/splitting_filter.c
signal_processing_library/spl_version.c
signal_processing_library/spl_sqrt.c
signal_processing_library/sin_table.c
signal_processing_library/sin_table_1024.c
signal_processing_library/resample.c
signal_processing_library/resample_fractional.c
signal_processing_library/resample_by_2.c
signal_processing_library/resample_by_2_internal.c
signal_processing_library/resample_48khz.c
signal_processing_library/refl_coef_to_lpc.c
signal_processing_library/randomization_functions.c
signal_processing_library/randn_table.c
signal_processing_library/norm_w32.c
signal_processing_library/norm_w16.c
signal_processing_library/norm_u32.c
signal_processing_library/min_max_operations.c
signal_processing_library/lpc_to_refl_coef.c
signal_processing_library/levinson_durbin.c
signal_processing_library/ilbc_specific_functions.c
signal_processing_library/hanning_table.c
signal_processing_library/get_size_in_bits.c
signal_processing_library/get_scaling_square.c
signal_processing_library/get_hanning_window.c
signal_processing_library/filter_ma_fast_q12.c
signal_processing_library/filter_ar.c
signal_processing_library/filter_ar_fast_q12.c
utility/ring_buffer.c
utility/fft4g.c
)
add_library(webrtc ${WEBRTC_SOURCES})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* Specifies the interface for the AEC core.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_
#include <stdio.h>
#include "typedefs.h"
#include "signal_processing_library.h"
//#define G167 // for running G167 tests
//#define UNCONSTR // time-unconstrained filter
//#define AEC_DEBUG // for recording files
#define FRAME_LEN 80
#define PART_LEN 64 // Length of partition
#define PART_LEN1 (PART_LEN + 1) // Unique fft coefficients
#define PART_LEN2 (PART_LEN * 2) // Length of partition * 2
#define NR_PART 12 // Number of partitions
#define FILT_LEN (PART_LEN * NR_PART) // Filter length
#define FILT_LEN2 (FILT_LEN * 2) // Double filter length
#define FAR_BUF_LEN (FILT_LEN2 * 2)
#define PREF_BAND_SIZE 24
#define BLOCKL_MAX FRAME_LEN
typedef float complex_t[2];
// For performance reasons, some arrays of complex numbers are replaced by twice
// as long arrays of float, all the real parts followed by all the imaginary
// ones (complex_t[SIZE] -> float[2][SIZE]). This allows SIMD optimizations and
// is better than two arrays (one for the real parts and one for the imaginary
// parts) as this other way would require two pointers instead of one and cause
// extra register spilling. This also allows the offsets to be calculated at
// compile time.
// Metrics
enum {offsetLevel = -100};
typedef struct {
float sfrsum;
int sfrcounter;
float framelevel;
float frsum;
int frcounter;
float minlevel;
float averagelevel;
} power_level_t;
typedef struct {
float instant;
float average;
float min;
float max;
float sum;
float hisum;
float himean;
int counter;
int hicounter;
} stats_t;
typedef struct {
int farBufWritePos, farBufReadPos;
int knownDelay;
int inSamples, outSamples;
int delayEstCtr;
void *farFrBuf, *nearFrBuf, *outFrBuf;
void *nearFrBufH;
void *outFrBufH;
float xBuf[PART_LEN2]; // farend
float dBuf[PART_LEN2]; // nearend
float eBuf[PART_LEN2]; // error
float dBufH[PART_LEN2]; // nearend
float xPow[PART_LEN1];
float dPow[PART_LEN1];
float dMinPow[PART_LEN1];
float dInitMinPow[PART_LEN1];
float *noisePow;
#ifdef FFTW
float fftR[PART_LEN2];
fftw_complex fftC[PART_LEN2];
fftw_plan fftPlan, ifftPlan;
fftw_complex xfBuf[NR_PART * PART_LEN1];
fftw_complex wfBuf[NR_PART * PART_LEN1];
fftw_complex sde[PART_LEN1];
#else
float xfBuf[2][NR_PART * PART_LEN1]; // farend fft buffer
float wfBuf[2][NR_PART * PART_LEN1]; // filter fft
complex_t sde[PART_LEN1]; // cross-psd of nearend and error
complex_t sxd[PART_LEN1]; // cross-psd of farend and nearend
complex_t xfwBuf[NR_PART * PART_LEN1]; // farend windowed fft buffer
#endif
float sx[PART_LEN1], sd[PART_LEN1], se[PART_LEN1]; // far, near and error psd
float hNs[PART_LEN1];
float hNlFbMin, hNlFbLocalMin;
float hNlXdAvgMin;
int hNlNewMin, hNlMinCtr;
float overDrive, overDriveSm;
float targetSupp, minOverDrive;
float outBuf[PART_LEN];
int delayIdx;
short stNearState, echoState;
short divergeState;
int xfBufBlockPos;
short farBuf[FILT_LEN2 * 2];
short mult; // sampling frequency multiple
int sampFreq;
WebRtc_UWord32 seed;
float mu; // stepsize
float errThresh; // error threshold
int noiseEstCtr;
// Toggles for G.167 testing
#ifdef G167
short adaptToggle; // Filter adaptation
short nlpToggle; // Nonlinear processing
short cnToggle; // Comfort noise
#endif
power_level_t farlevel;
power_level_t nearlevel;
power_level_t linoutlevel;
power_level_t nlpoutlevel;
int metricsMode;
int stateCounter;
stats_t erl;
stats_t erle;
stats_t aNlp;
stats_t rerl;
// Quantities to control H band scaling for SWB input
int freq_avg_ic; //initial bin for averaging nlp gain
int flag_Hband_cn; //for comfort noise
float cn_scale_Hband; //scale for comfort noise in H band
#ifdef AEC_DEBUG
FILE *farFile;
FILE *nearFile;
FILE *outFile;
FILE *outLpFile;
#endif
} aec_t;
typedef void (*WebRtcAec_FilterFar_t)(aec_t *aec, float yf[2][PART_LEN1]);
extern WebRtcAec_FilterFar_t WebRtcAec_FilterFar;
typedef void (*WebRtcAec_ScaleErrorSignal_t)(aec_t *aec, float ef[2][PART_LEN1]);
extern WebRtcAec_ScaleErrorSignal_t WebRtcAec_ScaleErrorSignal;
#define IP_LEN PART_LEN // this must be at least ceil(2 + sqrt(PART_LEN))
#define W_LEN PART_LEN
typedef void (*WebRtcAec_FilterAdaptation_t)
(aec_t *aec, float *fft, float ef[2][PART_LEN1], int ip[IP_LEN],
float wfft[W_LEN]);
extern WebRtcAec_FilterAdaptation_t WebRtcAec_FilterAdaptation;
typedef void (*WebRtcAec_OverdriveAndSuppress_t)
(aec_t *aec, float hNl[PART_LEN1], const float hNlFb, float efw[2][PART_LEN1]);
extern WebRtcAec_OverdriveAndSuppress_t WebRtcAec_OverdriveAndSuppress;
int WebRtcAec_CreateAec(aec_t **aec);
int WebRtcAec_FreeAec(aec_t *aec);
int WebRtcAec_InitAec(aec_t *aec, int sampFreq);
void WebRtcAec_InitAec_SSE2(void);
void WebRtcAec_InitMetrics(aec_t *aec);
void WebRtcAec_ProcessFrame(aec_t *aec, const short *farend,
const short *nearend, const short *nearendH,
short *out, short *outH,
int knownDelay);
// aec_core_rdft.c
void aec_rdft_128(int, float *, int *, float *);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_

View File

@@ -0,0 +1,511 @@
/*
* http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
* Copyright Takuya OOURA, 1996-2001
*
* You may use, copy, modify and distribute this code for any purpose (include
* commercial use) and without fee. Please refer to this package when you modify
* this code.
*
* Changes by the WebRTC authors:
* - Trivial type modifications.
* - Minimal code subset to do rdft of length 128.
* - Optimizations because of known length.
*
* All changes are covered by the WebRTC license and IP grant:
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "aec_core.h"
static void bitrv2_32or128(int n, int *ip, float *a) {
// n is 32 or 128
int j, j1, k, k1, m, m2;
float xr, xi, yr, yi;
ip[0] = 0;
{
int l = n;
m = 1;
while ((m << 3) < l) {
l >>= 1;
for (j = 0; j < m; j++) {
ip[m + j] = ip[j] + l;
}
m <<= 1;
}
}
m2 = 2 * m;
for (k = 0; k < m; k++) {
for (j = 0; j < k; j++) {
j1 = 2 * j + ip[k];
k1 = 2 * k + ip[j];
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += m2;
k1 += 2 * m2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += m2;
k1 -= m2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
j1 += m2;
k1 += 2 * m2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
j1 = 2 * k + m2 + ip[k];
k1 = j1 + m2;
xr = a[j1];
xi = a[j1 + 1];
yr = a[k1];
yi = a[k1 + 1];
a[j1] = yr;
a[j1 + 1] = yi;
a[k1] = xr;
a[k1 + 1] = xi;
}
}
static void makewt(int *ip, float *w) {
const int nw = 32;
int j, nwh;
float delta, x, y;
ip[0] = nw;
ip[1] = 1;
nwh = nw >> 1;
delta = atanf(1.0f) / nwh;
w[0] = 1;
w[1] = 0;
w[nwh] = cosf(delta * nwh);
w[nwh + 1] = w[nwh];
for (j = 2; j < nwh; j += 2) {
x = cosf(delta * j);
y = sinf(delta * j);
w[j] = x;
w[j + 1] = y;
w[nw - j] = y;
w[nw - j + 1] = x;
}
bitrv2_32or128(nw, ip + 2, w);
}
static void makect_32(int *ip, float *c) {
const int nc = 32;
int j, nch;
float delta;
ip[1] = nc;
nch = nc >> 1;
delta = atanf(1.0f) / nch;
c[0] = cosf(delta * nch);
c[nch] = 0.5f * c[0];
for (j = 1; j < nch; j++) {
c[j] = 0.5f * cosf(delta * j);
c[nc - j] = 0.5f * sinf(delta * j);
}
}
static void cft1st_128(float *a, float *w) {
const int n = 128;
int j, k1, k2;
float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
x0r = a[0] + a[2];
x0i = a[1] + a[3];
x1r = a[0] - a[2];
x1i = a[1] - a[3];
x2r = a[4] + a[6];
x2i = a[5] + a[7];
x3r = a[4] - a[6];
x3i = a[5] - a[7];
a[0] = x0r + x2r;
a[1] = x0i + x2i;
a[4] = x0r - x2r;
a[5] = x0i - x2i;
a[2] = x1r - x3i;
a[3] = x1i + x3r;
a[6] = x1r + x3i;
a[7] = x1i - x3r;
wk1r = w[2];
x0r = a[8] + a[10];
x0i = a[9] + a[11];
x1r = a[8] - a[10];
x1i = a[9] - a[11];
x2r = a[12] + a[14];
x2i = a[13] + a[15];
x3r = a[12] - a[14];
x3i = a[13] - a[15];
a[8] = x0r + x2r;
a[9] = x0i + x2i;
a[12] = x2i - x0i;
a[13] = x0r - x2r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[10] = wk1r * (x0r - x0i);
a[11] = wk1r * (x0r + x0i);
x0r = x3i + x1r;
x0i = x3r - x1i;
a[14] = wk1r * (x0i - x0r);
a[15] = wk1r * (x0i + x0r);
k1 = 0;
for (j = 16; j < n; j += 16) {
k1 += 2;
k2 = 2 * k1;
wk2r = w[k1];
wk2i = w[k1 + 1];
wk1r = w[k2];
wk1i = w[k2 + 1];
wk3r = wk1r - 2 * wk2i * wk1i;
wk3i = 2 * wk2i * wk1r - wk1i;
x0r = a[j] + a[j + 2];
x0i = a[j + 1] + a[j + 3];
x1r = a[j] - a[j + 2];
x1i = a[j + 1] - a[j + 3];
x2r = a[j + 4] + a[j + 6];
x2i = a[j + 5] + a[j + 7];
x3r = a[j + 4] - a[j + 6];
x3i = a[j + 5] - a[j + 7];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j + 4] = wk2r * x0r - wk2i * x0i;
a[j + 5] = wk2r * x0i + wk2i * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j + 2] = wk1r * x0r - wk1i * x0i;
a[j + 3] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j + 6] = wk3r * x0r - wk3i * x0i;
a[j + 7] = wk3r * x0i + wk3i * x0r;
wk1r = w[k2 + 2];
wk1i = w[k2 + 3];
wk3r = wk1r - 2 * wk2r * wk1i;
wk3i = 2 * wk2r * wk1r - wk1i;
x0r = a[j + 8] + a[j + 10];
x0i = a[j + 9] + a[j + 11];
x1r = a[j + 8] - a[j + 10];
x1i = a[j + 9] - a[j + 11];
x2r = a[j + 12] + a[j + 14];
x2i = a[j + 13] + a[j + 15];
x3r = a[j + 12] - a[j + 14];
x3i = a[j + 13] - a[j + 15];
a[j + 8] = x0r + x2r;
a[j + 9] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j + 12] = -wk2i * x0r - wk2r * x0i;
a[j + 13] = -wk2i * x0i + wk2r * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j + 10] = wk1r * x0r - wk1i * x0i;
a[j + 11] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j + 14] = wk3r * x0r - wk3i * x0i;
a[j + 15] = wk3r * x0i + wk3i * x0r;
}
}
static void cftmdl_128(int l, float *a, float *w) {
const int n = 128;
int j, j1, j2, j3, k, k1, k2, m, m2;
float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
m = l << 2;
for (j = 0; j < l; j += 2) {
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j2] = x0r - x2r;
a[j2 + 1] = x0i - x2i;
a[j1] = x1r - x3i;
a[j1 + 1] = x1i + x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i - x3r;
}
wk1r = w[2];
for (j = m; j < l + m; j += 2) {
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j2] = x2i - x0i;
a[j2 + 1] = x0r - x2r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j1] = wk1r * (x0r - x0i);
a[j1 + 1] = wk1r * (x0r + x0i);
x0r = x3i + x1r;
x0i = x3r - x1i;
a[j3] = wk1r * (x0i - x0r);
a[j3 + 1] = wk1r * (x0i + x0r);
}
k1 = 0;
m2 = 2 * m;
for (k = m2; k < n; k += m2) {
k1 += 2;
k2 = 2 * k1;
wk2r = w[k1];
wk2i = w[k1 + 1];
wk1r = w[k2];
wk1i = w[k2 + 1];
wk3r = wk1r - 2 * wk2i * wk1i;
wk3i = 2 * wk2i * wk1r - wk1i;
for (j = k; j < l + k; j += 2) {
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j2] = wk2r * x0r - wk2i * x0i;
a[j2 + 1] = wk2r * x0i + wk2i * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j1] = wk1r * x0r - wk1i * x0i;
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r - wk3i * x0i;
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
}
wk1r = w[k2 + 2];
wk1i = w[k2 + 3];
wk3r = wk1r - 2 * wk2r * wk1i;
wk3i = 2 * wk2r * wk1r - wk1i;
for (j = k + m; j < l + (k + m); j += 2) {
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
x0r -= x2r;
x0i -= x2i;
a[j2] = -wk2i * x0r - wk2r * x0i;
a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
x0r = x1r - x3i;
x0i = x1i + x3r;
a[j1] = wk1r * x0r - wk1i * x0i;
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
x0r = x1r + x3i;
x0i = x1i - x3r;
a[j3] = wk3r * x0r - wk3i * x0i;
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
}
}
}
static void cftfsub_128(float *a, float *w) {
int j, j1, j2, j3, l;
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
cft1st_128(a, w);
cftmdl_128(8, a, w);
l = 32;
for (j = 0; j < l; j += 2) {
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = a[j + 1] + a[j1 + 1];
x1r = a[j] - a[j1];
x1i = a[j + 1] - a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i + x2i;
a[j2] = x0r - x2r;
a[j2 + 1] = x0i - x2i;
a[j1] = x1r - x3i;
a[j1 + 1] = x1i + x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i - x3r;
}
}
static void cftbsub_128(float *a, float *w) {
int j, j1, j2, j3, l;
float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
cft1st_128(a, w);
cftmdl_128(8, a, w);
l = 32;
for (j = 0; j < l; j += 2) {
j1 = j + l;
j2 = j1 + l;
j3 = j2 + l;
x0r = a[j] + a[j1];
x0i = -a[j + 1] - a[j1 + 1];
x1r = a[j] - a[j1];
x1i = -a[j + 1] + a[j1 + 1];
x2r = a[j2] + a[j3];
x2i = a[j2 + 1] + a[j3 + 1];
x3r = a[j2] - a[j3];
x3i = a[j2 + 1] - a[j3 + 1];
a[j] = x0r + x2r;
a[j + 1] = x0i - x2i;
a[j2] = x0r - x2r;
a[j2 + 1] = x0i + x2i;
a[j1] = x1r - x3i;
a[j1 + 1] = x1i - x3r;
a[j3] = x1r + x3i;
a[j3 + 1] = x1i + x3r;
}
}
static void rftfsub_128(float *a, int nc, float *c) {
const int n = 128;
int j, k, kk, ks, m;
float wkr, wki, xr, xi, yr, yi;
m = n >> 1;
ks = 2 * nc / m;
kk = 0;
for (j = 2; j < m; j += 2) {
k = n - j;
kk += ks;
wkr = 0.5f - c[nc - kk];
wki = c[kk];
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
yr = wkr * xr - wki * xi;
yi = wkr * xi + wki * xr;
a[j] -= yr;
a[j + 1] -= yi;
a[k] += yr;
a[k + 1] -= yi;
}
}
static void rftbsub_128(float *a, int nc, float *c) {
const int n = 128;
int j, k, kk, ks, m;
float wkr, wki, xr, xi, yr, yi;
a[1] = -a[1];
m = n >> 1;
ks = 2 * nc / m;
kk = 0;
for (j = 2; j < m; j += 2) {
k = n - j;
kk += ks;
wkr = 0.5f - c[nc - kk];
wki = c[kk];
xr = a[j] - a[k];
xi = a[j + 1] + a[k + 1];
yr = wkr * xr + wki * xi;
yi = wkr * xi - wki * xr;
a[j] -= yr;
a[j + 1] = yi - a[j + 1];
a[k] += yr;
a[k + 1] = yi - a[k + 1];
}
a[m + 1] = -a[m + 1];
}
void aec_rdft_128(int isgn, float *a, int *ip, float *w)
{
const int n = 128;
int nw, nc;
float xi;
nw = ip[0];
if (n > (nw << 2)) {
nw = n >> 2;
makewt(ip, w);
}
nc = ip[1];
if (n > (nc << 2)) {
nc = n >> 2;
makect_32(ip, w + nw);
}
if (isgn >= 0) {
bitrv2_32or128(n, ip + 2, a);
cftfsub_128(a, w);
rftfsub_128(a, nc, w + nw);
xi = a[0] - a[1];
a[0] += a[1];
a[1] = xi;
} else {
a[1] = 0.5f * (a[0] - a[1]);
a[0] -= a[1];
rftbsub_128(a, nc, w + nw);
bitrv2_32or128(n, ip + 2, a);
cftbsub_128(a, w);
}
}

View File

@@ -0,0 +1,435 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* The core AEC algorithm, SSE2 version of speed-critical functions.
*/
#if defined(__SSE2__)
#include <emmintrin.h>
#include <math.h>
#include "aec_core.h"
__inline static float MulRe(float aRe, float aIm, float bRe, float bIm)
{
return aRe * bRe - aIm * bIm;
}
__inline static float MulIm(float aRe, float aIm, float bRe, float bIm)
{
return aRe * bIm + aIm * bRe;
}
static void FilterFarSSE2(aec_t *aec, float yf[2][PART_LEN1])
{
int i;
for (i = 0; i < NR_PART; i++) {
int j;
int xPos = (i + aec->xfBufBlockPos) * PART_LEN1;
int pos = i * PART_LEN1;
// Check for wrap
if (i + aec->xfBufBlockPos >= NR_PART) {
xPos -= NR_PART*(PART_LEN1);
}
// vectorized code (four at once)
for (j = 0; j + 3 < PART_LEN1; j += 4) {
const __m128 xfBuf_re = _mm_loadu_ps(&aec->xfBuf[0][xPos + j]);
const __m128 xfBuf_im = _mm_loadu_ps(&aec->xfBuf[1][xPos + j]);
const __m128 wfBuf_re = _mm_loadu_ps(&aec->wfBuf[0][pos + j]);
const __m128 wfBuf_im = _mm_loadu_ps(&aec->wfBuf[1][pos + j]);
const __m128 yf_re = _mm_loadu_ps(&yf[0][j]);
const __m128 yf_im = _mm_loadu_ps(&yf[1][j]);
const __m128 a = _mm_mul_ps(xfBuf_re, wfBuf_re);
const __m128 b = _mm_mul_ps(xfBuf_im, wfBuf_im);
const __m128 c = _mm_mul_ps(xfBuf_re, wfBuf_im);
const __m128 d = _mm_mul_ps(xfBuf_im, wfBuf_re);
const __m128 e = _mm_sub_ps(a, b);
const __m128 f = _mm_add_ps(c, d);
const __m128 g = _mm_add_ps(yf_re, e);
const __m128 h = _mm_add_ps(yf_im, f);
_mm_storeu_ps(&yf[0][j], g);
_mm_storeu_ps(&yf[1][j], h);
}
// scalar code for the remaining items.
for (; j < PART_LEN1; j++) {
yf[0][j] += MulRe(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
yf[1][j] += MulIm(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
}
}
}
static void ScaleErrorSignalSSE2(aec_t *aec, float ef[2][PART_LEN1])
{
const __m128 k1e_10f = _mm_set1_ps(1e-10f);
const __m128 kThresh = _mm_set1_ps(aec->errThresh);
const __m128 kMu = _mm_set1_ps(aec->mu);
int i;
// vectorized code (four at once)
for (i = 0; i + 3 < PART_LEN1; i += 4) {
const __m128 xPow = _mm_loadu_ps(&aec->xPow[i]);
const __m128 ef_re_base = _mm_loadu_ps(&ef[0][i]);
const __m128 ef_im_base = _mm_loadu_ps(&ef[1][i]);
const __m128 xPowPlus = _mm_add_ps(xPow, k1e_10f);
__m128 ef_re = _mm_div_ps(ef_re_base, xPowPlus);
__m128 ef_im = _mm_div_ps(ef_im_base, xPowPlus);
const __m128 ef_re2 = _mm_mul_ps(ef_re, ef_re);
const __m128 ef_im2 = _mm_mul_ps(ef_im, ef_im);
const __m128 ef_sum2 = _mm_add_ps(ef_re2, ef_im2);
const __m128 absEf = _mm_sqrt_ps(ef_sum2);
const __m128 bigger = _mm_cmpgt_ps(absEf, kThresh);
__m128 absEfPlus = _mm_add_ps(absEf, k1e_10f);
const __m128 absEfInv = _mm_div_ps(kThresh, absEfPlus);
__m128 ef_re_if = _mm_mul_ps(ef_re, absEfInv);
__m128 ef_im_if = _mm_mul_ps(ef_im, absEfInv);
ef_re_if = _mm_and_ps(bigger, ef_re_if);
ef_im_if = _mm_and_ps(bigger, ef_im_if);
ef_re = _mm_andnot_ps(bigger, ef_re);
ef_im = _mm_andnot_ps(bigger, ef_im);
ef_re = _mm_or_ps(ef_re, ef_re_if);
ef_im = _mm_or_ps(ef_im, ef_im_if);
ef_re = _mm_mul_ps(ef_re, kMu);
ef_im = _mm_mul_ps(ef_im, kMu);
_mm_storeu_ps(&ef[0][i], ef_re);
_mm_storeu_ps(&ef[1][i], ef_im);
}
// scalar code for the remaining items.
for (; i < (PART_LEN1); i++) {
float absEf;
ef[0][i] /= (aec->xPow[i] + 1e-10f);
ef[1][i] /= (aec->xPow[i] + 1e-10f);
absEf = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]);
if (absEf > aec->errThresh) {
absEf = aec->errThresh / (absEf + 1e-10f);
ef[0][i] *= absEf;
ef[1][i] *= absEf;
}
// Stepsize factor
ef[0][i] *= aec->mu;
ef[1][i] *= aec->mu;
}
}
static void FilterAdaptationSSE2(aec_t *aec, float *fft, float ef[2][PART_LEN1],
int ip[IP_LEN], float wfft[W_LEN]) {
int i, j;
for (i = 0; i < NR_PART; i++) {
int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
int pos = i * PART_LEN1;
// Check for wrap
if (i + aec->xfBufBlockPos >= NR_PART) {
xPos -= NR_PART * PART_LEN1;
}
#ifdef UNCONSTR
for (j = 0; j < PART_LEN1; j++) {
aec->wfBuf[pos + j][0] += MulRe(aec->xfBuf[xPos + j][0],
-aec->xfBuf[xPos + j][1],
ef[j][0], ef[j][1]);
aec->wfBuf[pos + j][1] += MulIm(aec->xfBuf[xPos + j][0],
-aec->xfBuf[xPos + j][1],
ef[j][0], ef[j][1]);
}
#else
// Process the whole array...
for (j = 0; j < PART_LEN; j+= 4) {
// Load xfBuf and ef.
const __m128 xfBuf_re = _mm_loadu_ps(&aec->xfBuf[0][xPos + j]);
const __m128 xfBuf_im = _mm_loadu_ps(&aec->xfBuf[1][xPos + j]);
const __m128 ef_re = _mm_loadu_ps(&ef[0][j]);
const __m128 ef_im = _mm_loadu_ps(&ef[1][j]);
// Calculate the product of conjugate(xfBuf) by ef.
// re(conjugate(a) * b) = aRe * bRe + aIm * bIm
// im(conjugate(a) * b)= aRe * bIm - aIm * bRe
const __m128 a = _mm_mul_ps(xfBuf_re, ef_re);
const __m128 b = _mm_mul_ps(xfBuf_im, ef_im);
const __m128 c = _mm_mul_ps(xfBuf_re, ef_im);
const __m128 d = _mm_mul_ps(xfBuf_im, ef_re);
const __m128 e = _mm_add_ps(a, b);
const __m128 f = _mm_sub_ps(c, d);
// Interleave real and imaginary parts.
const __m128 g = _mm_unpacklo_ps(e, f);
const __m128 h = _mm_unpackhi_ps(e, f);
// Store
_mm_storeu_ps(&fft[2*j + 0], g);
_mm_storeu_ps(&fft[2*j + 4], h);
}
// ... and fixup the first imaginary entry.
fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN],
-aec->xfBuf[1][xPos + PART_LEN],
ef[0][PART_LEN], ef[1][PART_LEN]);
aec_rdft_128(-1, fft, ip, wfft);
memset(fft + PART_LEN, 0, sizeof(float)*PART_LEN);
// fft scaling
{
float scale = 2.0f / PART_LEN2;
const __m128 scale_ps = _mm_load_ps1(&scale);
for (j = 0; j < PART_LEN; j+=4) {
const __m128 fft_ps = _mm_loadu_ps(&fft[j]);
const __m128 fft_scale = _mm_mul_ps(fft_ps, scale_ps);
_mm_storeu_ps(&fft[j], fft_scale);
}
}
aec_rdft_128(1, fft, ip, wfft);
{
float wt1 = aec->wfBuf[1][pos];
aec->wfBuf[0][pos + PART_LEN] += fft[1];
for (j = 0; j < PART_LEN; j+= 4) {
__m128 wtBuf_re = _mm_loadu_ps(&aec->wfBuf[0][pos + j]);
__m128 wtBuf_im = _mm_loadu_ps(&aec->wfBuf[1][pos + j]);
const __m128 fft0 = _mm_loadu_ps(&fft[2 * j + 0]);
const __m128 fft4 = _mm_loadu_ps(&fft[2 * j + 4]);
const __m128 fft_re = _mm_shuffle_ps(fft0, fft4, _MM_SHUFFLE(2, 0, 2 ,0));
const __m128 fft_im = _mm_shuffle_ps(fft0, fft4, _MM_SHUFFLE(3, 1, 3 ,1));
wtBuf_re = _mm_add_ps(wtBuf_re, fft_re);
wtBuf_im = _mm_add_ps(wtBuf_im, fft_im);
_mm_storeu_ps(&aec->wfBuf[0][pos + j], wtBuf_re);
_mm_storeu_ps(&aec->wfBuf[1][pos + j], wtBuf_im);
}
aec->wfBuf[1][pos] = wt1;
}
#endif // UNCONSTR
}
}
#ifdef _MSC_VER /* visual c++ */
# define ALIGN16_BEG __declspec(align(16))
# define ALIGN16_END
#else /* gcc or icc */
# define ALIGN16_BEG
# define ALIGN16_END __attribute__((aligned(16)))
#endif
static __m128 mm_pow_ps(__m128 a, __m128 b)
{
// a^b = exp2(b * log2(a))
// exp2(x) and log2(x) are calculated using polynomial approximations.
__m128 log2_a, b_log2_a, a_exp_b;
// Calculate log2(x), x = a.
{
// To calculate log2(x), we decompose x like this:
// x = y * 2^n
// n is an integer
// y is in the [1.0, 2.0) range
//
// log2(x) = log2(y) + n
// n can be evaluated by playing with float representation.
// log2(y) in a small range can be approximated, this code uses an order
// five polynomial approximation. The coefficients have been
// estimated with the Remez algorithm and the resulting
// polynomial has a maximum relative error of 0.00086%.
// Compute n.
// This is done by masking the exponent, shifting it into the top bit of
// the mantissa, putting eight into the biased exponent (to shift/
// compensate the fact that the exponent has been shifted in the top/
// fractional part and finally getting rid of the implicit leading one
// from the mantissa by substracting it out.
static const ALIGN16_BEG int float_exponent_mask[4] ALIGN16_END =
{0x7F800000, 0x7F800000, 0x7F800000, 0x7F800000};
static const ALIGN16_BEG int eight_biased_exponent[4] ALIGN16_END =
{0x43800000, 0x43800000, 0x43800000, 0x43800000};
static const ALIGN16_BEG int implicit_leading_one[4] ALIGN16_END =
{0x43BF8000, 0x43BF8000, 0x43BF8000, 0x43BF8000};
static const int shift_exponent_into_top_mantissa = 8;
const __m128 two_n = _mm_and_ps(a, *((__m128 *)float_exponent_mask));
const __m128 n_1 = (__m128)_mm_srli_epi32((__m128i)two_n,
shift_exponent_into_top_mantissa);
const __m128 n_0 = _mm_or_ps(
(__m128)n_1, *((__m128 *)eight_biased_exponent));
const __m128 n = _mm_sub_ps(n_0, *((__m128 *)implicit_leading_one));
// Compute y.
static const ALIGN16_BEG int mantissa_mask[4] ALIGN16_END =
{0x007FFFFF, 0x007FFFFF, 0x007FFFFF, 0x007FFFFF};
static const ALIGN16_BEG int zero_biased_exponent_is_one[4] ALIGN16_END =
{0x3F800000, 0x3F800000, 0x3F800000, 0x3F800000};
const __m128 mantissa = _mm_and_ps(a, *((__m128 *)mantissa_mask));
const __m128 y = _mm_or_ps(
mantissa, *((__m128 *)zero_biased_exponent_is_one));
// Approximate log2(y) ~= (y - 1) * pol5(y).
// pol5(y) = C5 * y^5 + C4 * y^4 + C3 * y^3 + C2 * y^2 + C1 * y + C0
static const ALIGN16_BEG float ALIGN16_END C5[4] =
{-3.4436006e-2f, -3.4436006e-2f, -3.4436006e-2f, -3.4436006e-2f};
static const ALIGN16_BEG float ALIGN16_END C4[4] =
{3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f, 3.1821337e-1f};
static const ALIGN16_BEG float ALIGN16_END C3[4] =
{-1.2315303f, -1.2315303f, -1.2315303f, -1.2315303f};
static const ALIGN16_BEG float ALIGN16_END C2[4] =
{2.5988452f, 2.5988452f, 2.5988452f, 2.5988452f};
static const ALIGN16_BEG float ALIGN16_END C1[4] =
{-3.3241990f, -3.3241990f, -3.3241990f, -3.3241990f};
static const ALIGN16_BEG float ALIGN16_END C0[4] =
{3.1157899f, 3.1157899f, 3.1157899f, 3.1157899f};
const __m128 pol5_y_0 = _mm_mul_ps(y, *((__m128 *)C5));
const __m128 pol5_y_1 = _mm_add_ps(pol5_y_0, *((__m128 *)C4));
const __m128 pol5_y_2 = _mm_mul_ps(pol5_y_1, y);
const __m128 pol5_y_3 = _mm_add_ps(pol5_y_2, *((__m128 *)C3));
const __m128 pol5_y_4 = _mm_mul_ps(pol5_y_3, y);
const __m128 pol5_y_5 = _mm_add_ps(pol5_y_4, *((__m128 *)C2));
const __m128 pol5_y_6 = _mm_mul_ps(pol5_y_5, y);
const __m128 pol5_y_7 = _mm_add_ps(pol5_y_6, *((__m128 *)C1));
const __m128 pol5_y_8 = _mm_mul_ps(pol5_y_7, y);
const __m128 pol5_y = _mm_add_ps(pol5_y_8, *((__m128 *)C0));
const __m128 y_minus_one = _mm_sub_ps(
y, *((__m128 *)zero_biased_exponent_is_one));
const __m128 log2_y = _mm_mul_ps(y_minus_one , pol5_y);
// Combine parts.
log2_a = _mm_add_ps(n, log2_y);
}
// b * log2(a)
b_log2_a = _mm_mul_ps(b, log2_a);
// Calculate exp2(x), x = b * log2(a).
{
// To calculate 2^x, we decompose x like this:
// x = n + y
// n is an integer, the value of x - 0.5 rounded down, therefore
// y is in the [0.5, 1.5) range
//
// 2^x = 2^n * 2^y
// 2^n can be evaluated by playing with float representation.
// 2^y in a small range can be approximated, this code uses an order two
// polynomial approximation. The coefficients have been estimated
// with the Remez algorithm and the resulting polynomial has a
// maximum relative error of 0.17%.
// To avoid over/underflow, we reduce the range of input to ]-127, 129].
static const ALIGN16_BEG float max_input[4] ALIGN16_END =
{129.f, 129.f, 129.f, 129.f};
static const ALIGN16_BEG float min_input[4] ALIGN16_END =
{-126.99999f, -126.99999f, -126.99999f, -126.99999f};
const __m128 x_min = _mm_min_ps(b_log2_a, *((__m128 *)max_input));
const __m128 x_max = _mm_max_ps(x_min, *((__m128 *)min_input));
// Compute n.
static const ALIGN16_BEG float half[4] ALIGN16_END =
{0.5f, 0.5f, 0.5f, 0.5f};
const __m128 x_minus_half = _mm_sub_ps(x_max, *((__m128 *)half));
const __m128i x_minus_half_floor = _mm_cvtps_epi32(x_minus_half);
// Compute 2^n.
static const ALIGN16_BEG int float_exponent_bias[4] ALIGN16_END =
{127, 127, 127, 127};
static const int float_exponent_shift = 23;
const __m128i two_n_exponent = _mm_add_epi32(
x_minus_half_floor, *((__m128i *)float_exponent_bias));
const __m128 two_n = (__m128)_mm_slli_epi32(
two_n_exponent, float_exponent_shift);
// Compute y.
const __m128 y = _mm_sub_ps(x_max, _mm_cvtepi32_ps(x_minus_half_floor));
// Approximate 2^y ~= C2 * y^2 + C1 * y + C0.
static const ALIGN16_BEG float C2[4] ALIGN16_END =
{3.3718944e-1f, 3.3718944e-1f, 3.3718944e-1f, 3.3718944e-1f};
static const ALIGN16_BEG float C1[4] ALIGN16_END =
{6.5763628e-1f, 6.5763628e-1f, 6.5763628e-1f, 6.5763628e-1f};
static const ALIGN16_BEG float C0[4] ALIGN16_END =
{1.0017247f, 1.0017247f, 1.0017247f, 1.0017247f};
const __m128 exp2_y_0 = _mm_mul_ps(y, *((__m128 *)C2));
const __m128 exp2_y_1 = _mm_add_ps(exp2_y_0, *((__m128 *)C1));
const __m128 exp2_y_2 = _mm_mul_ps(exp2_y_1, y);
const __m128 exp2_y = _mm_add_ps(exp2_y_2, *((__m128 *)C0));
// Combine parts.
a_exp_b = _mm_mul_ps(exp2_y, two_n);
}
return a_exp_b;
}
extern const float WebRtcAec_weightCurve[65];
extern const float WebRtcAec_overDriveCurve[65];
static void OverdriveAndSuppressSSE2(aec_t *aec, float hNl[PART_LEN1],
const float hNlFb,
float efw[2][PART_LEN1]) {
int i;
const __m128 vec_hNlFb = _mm_set1_ps(hNlFb);
const __m128 vec_one = _mm_set1_ps(1.0f);
const __m128 vec_minus_one = _mm_set1_ps(-1.0f);
const __m128 vec_overDriveSm = _mm_set1_ps(aec->overDriveSm);
// vectorized code (four at once)
for (i = 0; i + 3 < PART_LEN1; i+=4) {
// Weight subbands
__m128 vec_hNl = _mm_loadu_ps(&hNl[i]);
const __m128 vec_weightCurve = _mm_loadu_ps(&WebRtcAec_weightCurve[i]);
const __m128 bigger = _mm_cmpgt_ps(vec_hNl, vec_hNlFb);
const __m128 vec_weightCurve_hNlFb = _mm_mul_ps(
vec_weightCurve, vec_hNlFb);
const __m128 vec_one_weightCurve = _mm_sub_ps(vec_one, vec_weightCurve);
const __m128 vec_one_weightCurve_hNl = _mm_mul_ps(
vec_one_weightCurve, vec_hNl);
const __m128 vec_if0 = _mm_andnot_ps(bigger, vec_hNl);
const __m128 vec_if1 = _mm_and_ps(
bigger, _mm_add_ps(vec_weightCurve_hNlFb, vec_one_weightCurve_hNl));
vec_hNl = _mm_or_ps(vec_if0, vec_if1);
{
const __m128 vec_overDriveCurve = _mm_loadu_ps(
&WebRtcAec_overDriveCurve[i]);
const __m128 vec_overDriveSm_overDriveCurve = _mm_mul_ps(
vec_overDriveSm, vec_overDriveCurve);
vec_hNl = mm_pow_ps(vec_hNl, vec_overDriveSm_overDriveCurve);
_mm_storeu_ps(&hNl[i], vec_hNl);
}
// Suppress error signal
{
__m128 vec_efw_re = _mm_loadu_ps(&efw[0][i]);
__m128 vec_efw_im = _mm_loadu_ps(&efw[1][i]);
vec_efw_re = _mm_mul_ps(vec_efw_re, vec_hNl);
vec_efw_im = _mm_mul_ps(vec_efw_im, vec_hNl);
// Ooura fft returns incorrect sign on imaginary component. It matters
// here because we are making an additive change with comfort noise.
vec_efw_im = _mm_mul_ps(vec_efw_im, vec_minus_one);
_mm_storeu_ps(&efw[0][i], vec_efw_re);
_mm_storeu_ps(&efw[1][i], vec_efw_im);
}
}
// scalar code for the remaining items.
for (; i < PART_LEN1; i++) {
// Weight subbands
if (hNl[i] > hNlFb) {
hNl[i] = WebRtcAec_weightCurve[i] * hNlFb +
(1 - WebRtcAec_weightCurve[i]) * hNl[i];
}
hNl[i] = powf(hNl[i], aec->overDriveSm * WebRtcAec_overDriveCurve[i]);
// Suppress error signal
efw[0][i] *= hNl[i];
efw[1][i] *= hNl[i];
// Ooura fft returns incorrect sign on imaginary component. It matters
// here because we are making an additive change with comfort noise.
efw[1][i] *= -1;
}
}
void WebRtcAec_InitAec_SSE2(void) {
WebRtcAec_FilterFar = FilterFarSSE2;
WebRtcAec_ScaleErrorSignal = ScaleErrorSignalSSE2;
WebRtcAec_FilterAdaptation = FilterAdaptationSSE2;
WebRtcAec_OverdriveAndSuppress = OverdriveAndSuppressSSE2;
}
#endif //__SSE2__

View File

@@ -0,0 +1,821 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* Contains the API functions for the AEC.
*/
#include <stdlib.h>
#include <string.h>
#include "echo_cancellation.h"
#include "aec_core.h"
#include "ring_buffer.h"
#include "resampler.h"
#ifdef AEC_DEBUG
#include <stdio.h>
#endif
#define BUF_SIZE_FRAMES 50 // buffer size (frames)
// Maximum length of resampled signal. Must be an integer multiple of frames
// (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN
// The factor of 2 handles wb, and the + 1 is as a safety margin
#define MAX_RESAMP_LEN (5 * FRAME_LEN)
static const int bufSizeSamp = BUF_SIZE_FRAMES * FRAME_LEN; // buffer size (samples)
static const int sampMsNb = 8; // samples per ms in nb
// Target suppression levels for nlp modes
// log{0.001, 0.00001, 0.00000001}
static const float targetSupp[3] = {-6.9f, -11.5f, -18.4f};
static const float minOverDrive[3] = {1.0f, 2.0f, 5.0f};
static const int initCheck = 42;
typedef struct {
int delayCtr;
int sampFreq;
int splitSampFreq;
int scSampFreq;
float sampFactor; // scSampRate / sampFreq
short nlpMode;
short autoOnOff;
short activity;
short skewMode;
short bufSizeStart;
//short bufResetCtr; // counts number of noncausal frames
int knownDelay;
// Stores the last frame added to the farend buffer
short farendOld[2][FRAME_LEN];
short initFlag; // indicates if AEC has been initialized
// Variables used for averaging far end buffer size
short counter;
short sum;
short firstVal;
short checkBufSizeCtr;
// Variables used for delay shifts
short msInSndCardBuf;
short filtDelay;
int timeForDelayChange;
int ECstartup;
int checkBuffSize;
int delayChange;
short lastDelayDiff;
#ifdef AEC_DEBUG
FILE *bufFile;
FILE *delayFile;
FILE *skewFile;
FILE *preCompFile;
FILE *postCompFile;
#endif // AEC_DEBUG
// Structures
void *farendBuf;
void *resampler;
int skewFrCtr;
int resample; // if the skew is small enough we don't resample
int highSkewCtr;
float skew;
int lastError;
aec_t *aec;
} aecpc_t;
// Estimates delay to set the position of the farend buffer read pointer
// (controlled by knownDelay)
static int EstBufDelay(aecpc_t *aecInst, short msInSndCardBuf);
// Stuffs the farend buffer if the estimated delay is too large
static int DelayComp(aecpc_t *aecInst);
WebRtc_Word32 WebRtcAec_Create(void **aecInst)
{
aecpc_t *aecpc;
if (aecInst == NULL) {
return -1;
}
aecpc = malloc(sizeof(aecpc_t));
*aecInst = aecpc;
if (aecpc == NULL) {
return -1;
}
if (WebRtcAec_CreateAec(&aecpc->aec) == -1) {
WebRtcAec_Free(aecpc);
aecpc = NULL;
return -1;
}
if (WebRtcApm_CreateBuffer(&aecpc->farendBuf, bufSizeSamp) == -1) {
WebRtcAec_Free(aecpc);
aecpc = NULL;
return -1;
}
if (WebRtcAec_CreateResampler(&aecpc->resampler) == -1) {
WebRtcAec_Free(aecpc);
aecpc = NULL;
return -1;
}
aecpc->initFlag = 0;
aecpc->lastError = 0;
#ifdef AEC_DEBUG
aecpc->aec->farFile = fopen("aecFar.pcm","wb");
aecpc->aec->nearFile = fopen("aecNear.pcm","wb");
aecpc->aec->outFile = fopen("aecOut.pcm","wb");
aecpc->aec->outLpFile = fopen("aecOutLp.pcm","wb");
aecpc->bufFile = fopen("aecBuf.dat", "wb");
aecpc->skewFile = fopen("aecSkew.dat", "wb");
aecpc->delayFile = fopen("aecDelay.dat", "wb");
aecpc->preCompFile = fopen("preComp.pcm", "wb");
aecpc->postCompFile = fopen("postComp.pcm", "wb");
#endif // AEC_DEBUG
return 0;
}
WebRtc_Word32 WebRtcAec_Free(void *aecInst)
{
aecpc_t *aecpc = aecInst;
if (aecpc == NULL) {
return -1;
}
#ifdef AEC_DEBUG
fclose(aecpc->aec->farFile);
fclose(aecpc->aec->nearFile);
fclose(aecpc->aec->outFile);
fclose(aecpc->aec->outLpFile);
fclose(aecpc->bufFile);
fclose(aecpc->skewFile);
fclose(aecpc->delayFile);
fclose(aecpc->preCompFile);
fclose(aecpc->postCompFile);
#endif // AEC_DEBUG
WebRtcAec_FreeAec(aecpc->aec);
WebRtcApm_FreeBuffer(aecpc->farendBuf);
WebRtcAec_FreeResampler(aecpc->resampler);
free(aecpc);
return 0;
}
WebRtc_Word32 WebRtcAec_Init(void *aecInst, WebRtc_Word32 sampFreq, WebRtc_Word32 scSampFreq)
{
aecpc_t *aecpc = aecInst;
AecConfig aecConfig;
if (aecpc == NULL) {
return -1;
}
if (sampFreq != 8000 && sampFreq != 16000 && sampFreq != 32000) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->sampFreq = sampFreq;
if (scSampFreq < 1 || scSampFreq > 96000) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->scSampFreq = scSampFreq;
// Initialize echo canceller core
if (WebRtcAec_InitAec(aecpc->aec, aecpc->sampFreq) == -1) {
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
// Initialize farend buffer
if (WebRtcApm_InitBuffer(aecpc->farendBuf) == -1) {
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
if (WebRtcAec_InitResampler(aecpc->resampler, aecpc->scSampFreq) == -1) {
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
aecpc->initFlag = initCheck; // indicates that initilisation has been done
if (aecpc->sampFreq == 32000) {
aecpc->splitSampFreq = 16000;
}
else {
aecpc->splitSampFreq = sampFreq;
}
aecpc->skewFrCtr = 0;
aecpc->activity = 0;
aecpc->delayChange = 1;
aecpc->delayCtr = 0;
aecpc->sum = 0;
aecpc->counter = 0;
aecpc->checkBuffSize = 1;
aecpc->firstVal = 0;
aecpc->ECstartup = 1;
aecpc->bufSizeStart = 0;
aecpc->checkBufSizeCtr = 0;
aecpc->filtDelay = 0;
aecpc->timeForDelayChange =0;
aecpc->knownDelay = 0;
aecpc->lastDelayDiff = 0;
aecpc->skew = 0;
aecpc->resample = kAecFalse;
aecpc->highSkewCtr = 0;
aecpc->sampFactor = (aecpc->scSampFreq * 1.0f) / aecpc->splitSampFreq;
memset(&aecpc->farendOld[0][0], 0, 160);
// Default settings.
aecConfig.nlpMode = kAecNlpModerate;
aecConfig.skewMode = kAecFalse;
aecConfig.metricsMode = kAecFalse;
if (WebRtcAec_set_config(aecpc, aecConfig) == -1) {
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
return 0;
}
// only buffer L band for farend
WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst, const WebRtc_Word16 *farend,
WebRtc_Word16 nrOfSamples)
{
aecpc_t *aecpc = aecInst;
WebRtc_Word32 retVal = 0;
short newNrOfSamples;
short newFarend[MAX_RESAMP_LEN];
float skew;
if (aecpc == NULL) {
return -1;
}
if (farend == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
// number of samples == 160 for SWB input
if (nrOfSamples != 80 && nrOfSamples != 160) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
skew = aecpc->skew;
// TODO: Is this really a good idea?
if (!aecpc->ECstartup) {
DelayComp(aecpc);
}
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
// Resample and get a new number of samples
newNrOfSamples = WebRtcAec_ResampleLinear(aecpc->resampler,
farend,
nrOfSamples,
skew,
newFarend);
WebRtcApm_WriteBuffer(aecpc->farendBuf, newFarend, newNrOfSamples);
#ifdef AEC_DEBUG
fwrite(farend, 2, nrOfSamples, aecpc->preCompFile);
fwrite(newFarend, 2, newNrOfSamples, aecpc->postCompFile);
#endif
}
else {
WebRtcApm_WriteBuffer(aecpc->farendBuf, farend, nrOfSamples);
}
return retVal;
}
WebRtc_Word32 WebRtcAec_Process(void *aecInst, const WebRtc_Word16 *nearend,
const WebRtc_Word16 *nearendH, WebRtc_Word16 *out, WebRtc_Word16 *outH,
WebRtc_Word16 nrOfSamples, WebRtc_Word16 msInSndCardBuf, WebRtc_Word32 skew)
{
aecpc_t *aecpc = aecInst;
WebRtc_Word32 retVal = 0;
short i;
short farend[FRAME_LEN];
short nmbrOfFilledBuffers;
short nBlocks10ms;
short nFrames;
#ifdef AEC_DEBUG
short msInAECBuf;
#endif
// Limit resampling to doubling/halving of signal
const float minSkewEst = -0.5f;
const float maxSkewEst = 1.0f;
if (aecpc == NULL) {
return -1;
}
if (nearend == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (out == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
// number of samples == 160 for SWB input
if (nrOfSamples != 80 && nrOfSamples != 160) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
// Check for valid pointers based on sampling rate
if (aecpc->sampFreq == 32000 && nearendH == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (msInSndCardBuf < 0) {
msInSndCardBuf = 0;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
retVal = -1;
}
else if (msInSndCardBuf > 500) {
msInSndCardBuf = 500;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
retVal = -1;
}
msInSndCardBuf += 10;
aecpc->msInSndCardBuf = msInSndCardBuf;
if (aecpc->skewMode == kAecTrue) {
if (aecpc->skewFrCtr < 25) {
aecpc->skewFrCtr++;
}
else {
retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
if (retVal == -1) {
aecpc->skew = 0;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
}
aecpc->skew /= aecpc->sampFactor*nrOfSamples;
if (aecpc->skew < 1.0e-3 && aecpc->skew > -1.0e-3) {
aecpc->resample = kAecFalse;
}
else {
aecpc->resample = kAecTrue;
}
if (aecpc->skew < minSkewEst) {
aecpc->skew = minSkewEst;
}
else if (aecpc->skew > maxSkewEst) {
aecpc->skew = maxSkewEst;
}
#ifdef AEC_DEBUG
fwrite(&aecpc->skew, sizeof(aecpc->skew), 1, aecpc->skewFile);
#endif
}
}
nFrames = nrOfSamples / FRAME_LEN;
nBlocks10ms = nFrames / aecpc->aec->mult;
if (aecpc->ECstartup) {
memcpy(out, nearend, sizeof(short) * nrOfSamples);
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecpc->farendBuf) / FRAME_LEN;
// The AEC is in the start up mode
// AEC is disabled until the soundcard buffer and farend buffers are OK
// Mechanism to ensure that the soundcard buffer is reasonably stable.
if (aecpc->checkBuffSize) {
aecpc->checkBufSizeCtr++;
// Before we fill up the far end buffer we require the amount of data on the
// sound card to be stable (+/-8 ms) compared to the first value. This
// comparison is made during the following 4 consecutive frames. If it seems
// to be stable then we start to fill up the far end buffer.
if (aecpc->counter == 0) {
aecpc->firstVal = aecpc->msInSndCardBuf;
aecpc->sum = 0;
}
if (abs(aecpc->firstVal - aecpc->msInSndCardBuf) <
WEBRTC_SPL_MAX(0.2 * aecpc->msInSndCardBuf, sampMsNb)) {
aecpc->sum += aecpc->msInSndCardBuf;
aecpc->counter++;
}
else {
aecpc->counter = 0;
}
if (aecpc->counter*nBlocks10ms >= 6) {
// The farend buffer size is determined in blocks of 80 samples
// Use 75% of the average value of the soundcard buffer
aecpc->bufSizeStart = WEBRTC_SPL_MIN((int) (0.75 * (aecpc->sum *
aecpc->aec->mult) / (aecpc->counter * 10)), BUF_SIZE_FRAMES);
// buffersize has now been determined
aecpc->checkBuffSize = 0;
}
if (aecpc->checkBufSizeCtr * nBlocks10ms > 50) {
// for really bad sound cards, don't disable echocanceller for more than 0.5 sec
aecpc->bufSizeStart = WEBRTC_SPL_MIN((int) (0.75 * (aecpc->msInSndCardBuf *
aecpc->aec->mult) / 10), BUF_SIZE_FRAMES);
aecpc->checkBuffSize = 0;
}
}
// if checkBuffSize changed in the if-statement above
if (!aecpc->checkBuffSize) {
// soundcard buffer is now reasonably stable
// When the far end buffer is filled with approximately the same amount of
// data as the amount on the sound card we end the start up phase and start
// to cancel echoes.
if (nmbrOfFilledBuffers == aecpc->bufSizeStart) {
aecpc->ECstartup = 0; // Enable the AEC
}
else if (nmbrOfFilledBuffers > aecpc->bufSizeStart) {
WebRtcApm_FlushBuffer(aecpc->farendBuf, WebRtcApm_get_buffer_size(aecpc->farendBuf) -
aecpc->bufSizeStart * FRAME_LEN);
aecpc->ECstartup = 0;
}
}
}
else {
// AEC is enabled
// Note only 1 block supported for nb and 2 blocks for wb
for (i = 0; i < nFrames; i++) {
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecpc->farendBuf) / FRAME_LEN;
// Check that there is data in the far end buffer
if (nmbrOfFilledBuffers > 0) {
// Get the next 80 samples from the farend buffer
WebRtcApm_ReadBuffer(aecpc->farendBuf, farend, FRAME_LEN);
// Always store the last frame for use when we run out of data
memcpy(&(aecpc->farendOld[i][0]), farend, FRAME_LEN * sizeof(short));
}
else {
// We have no data so we use the last played frame
memcpy(farend, &(aecpc->farendOld[i][0]), FRAME_LEN * sizeof(short));
}
// Call buffer delay estimator when all data is extracted,
// i.e. i = 0 for NB and i = 1 for WB or SWB
if ((i == 0 && aecpc->splitSampFreq == 8000) ||
(i == 1 && (aecpc->splitSampFreq == 16000))) {
EstBufDelay(aecpc, aecpc->msInSndCardBuf);
}
// Call the AEC
WebRtcAec_ProcessFrame(aecpc->aec, farend, &nearend[FRAME_LEN * i], &nearendH[FRAME_LEN * i],
&out[FRAME_LEN * i], &outH[FRAME_LEN * i], aecpc->knownDelay);
}
}
#ifdef AEC_DEBUG
msInAECBuf = WebRtcApm_get_buffer_size(aecpc->farendBuf) / (sampMsNb*aecpc->aec->mult);
fwrite(&msInAECBuf, 2, 1, aecpc->bufFile);
fwrite(&(aecpc->knownDelay), sizeof(aecpc->knownDelay), 1, aecpc->delayFile);
#endif
return retVal;
}
WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config)
{
aecpc_t *aecpc = aecInst;
if (aecpc == NULL) {
return -1;
}
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
if (config.skewMode != kAecFalse && config.skewMode != kAecTrue) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->skewMode = config.skewMode;
if (config.nlpMode != kAecNlpConservative && config.nlpMode !=
kAecNlpModerate && config.nlpMode != kAecNlpAggressive) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->nlpMode = config.nlpMode;
aecpc->aec->targetSupp = targetSupp[aecpc->nlpMode];
aecpc->aec->minOverDrive = minOverDrive[aecpc->nlpMode];
if (config.metricsMode != kAecFalse && config.metricsMode != kAecTrue) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->aec->metricsMode = config.metricsMode;
if (aecpc->aec->metricsMode == kAecTrue) {
WebRtcAec_InitMetrics(aecpc->aec);
}
return 0;
}
WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config)
{
aecpc_t *aecpc = aecInst;
if (aecpc == NULL) {
return -1;
}
if (config == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
config->nlpMode = aecpc->nlpMode;
config->skewMode = aecpc->skewMode;
config->metricsMode = aecpc->aec->metricsMode;
return 0;
}
WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status)
{
aecpc_t *aecpc = aecInst;
if (aecpc == NULL) {
return -1;
}
if (status == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
*status = aecpc->aec->echoState;
return 0;
}
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics)
{
const float upweight = 0.7f;
float dtmp;
short stmp;
aecpc_t *aecpc = aecInst;
if (aecpc == NULL) {
return -1;
}
if (metrics == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
// ERL
metrics->erl.instant = (short) aecpc->aec->erl.instant;
if ((aecpc->aec->erl.himean > offsetLevel) && (aecpc->aec->erl.average > offsetLevel)) {
// Use a mix between regular average and upper part average
dtmp = upweight * aecpc->aec->erl.himean + (1 - upweight) * aecpc->aec->erl.average;
metrics->erl.average = (short) dtmp;
}
else {
metrics->erl.average = offsetLevel;
}
metrics->erl.max = (short) aecpc->aec->erl.max;
if (aecpc->aec->erl.min < (offsetLevel * (-1))) {
metrics->erl.min = (short) aecpc->aec->erl.min;
}
else {
metrics->erl.min = offsetLevel;
}
// ERLE
metrics->erle.instant = (short) aecpc->aec->erle.instant;
if ((aecpc->aec->erle.himean > offsetLevel) && (aecpc->aec->erle.average > offsetLevel)) {
// Use a mix between regular average and upper part average
dtmp = upweight * aecpc->aec->erle.himean + (1 - upweight) * aecpc->aec->erle.average;
metrics->erle.average = (short) dtmp;
}
else {
metrics->erle.average = offsetLevel;
}
metrics->erle.max = (short) aecpc->aec->erle.max;
if (aecpc->aec->erle.min < (offsetLevel * (-1))) {
metrics->erle.min = (short) aecpc->aec->erle.min;
} else {
metrics->erle.min = offsetLevel;
}
// RERL
if ((metrics->erl.average > offsetLevel) && (metrics->erle.average > offsetLevel)) {
stmp = metrics->erl.average + metrics->erle.average;
}
else {
stmp = offsetLevel;
}
metrics->rerl.average = stmp;
// No other statistics needed, but returned for completeness
metrics->rerl.instant = stmp;
metrics->rerl.max = stmp;
metrics->rerl.min = stmp;
// A_NLP
metrics->aNlp.instant = (short) aecpc->aec->aNlp.instant;
if ((aecpc->aec->aNlp.himean > offsetLevel) && (aecpc->aec->aNlp.average > offsetLevel)) {
// Use a mix between regular average and upper part average
dtmp = upweight * aecpc->aec->aNlp.himean + (1 - upweight) * aecpc->aec->aNlp.average;
metrics->aNlp.average = (short) dtmp;
}
else {
metrics->aNlp.average = offsetLevel;
}
metrics->aNlp.max = (short) aecpc->aec->aNlp.max;
if (aecpc->aec->aNlp.min < (offsetLevel * (-1))) {
metrics->aNlp.min = (short) aecpc->aec->aNlp.min;
}
else {
metrics->aNlp.min = offsetLevel;
}
return 0;
}
WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
{
const char version[] = "AEC 2.5.0";
const short versionLen = (short)strlen(version) + 1; // +1 for null-termination
if (versionStr == NULL) {
return -1;
}
if (versionLen > len) {
return -1;
}
strncpy(versionStr, version, versionLen);
return 0;
}
WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst)
{
aecpc_t *aecpc = aecInst;
if (aecpc == NULL) {
return -1;
}
return aecpc->lastError;
}
static int EstBufDelay(aecpc_t *aecpc, short msInSndCardBuf)
{
short delayNew, nSampFar, nSampSndCard;
short diff;
nSampFar = WebRtcApm_get_buffer_size(aecpc->farendBuf);
nSampSndCard = msInSndCardBuf * sampMsNb * aecpc->aec->mult;
delayNew = nSampSndCard - nSampFar;
// Account for resampling frame delay
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
delayNew -= kResamplingDelay;
}
if (delayNew < FRAME_LEN) {
WebRtcApm_FlushBuffer(aecpc->farendBuf, FRAME_LEN);
delayNew += FRAME_LEN;
}
aecpc->filtDelay = WEBRTC_SPL_MAX(0, (short)(0.8*aecpc->filtDelay + 0.2*delayNew));
diff = aecpc->filtDelay - aecpc->knownDelay;
if (diff > 224) {
if (aecpc->lastDelayDiff < 96) {
aecpc->timeForDelayChange = 0;
}
else {
aecpc->timeForDelayChange++;
}
}
else if (diff < 96 && aecpc->knownDelay > 0) {
if (aecpc->lastDelayDiff > 224) {
aecpc->timeForDelayChange = 0;
}
else {
aecpc->timeForDelayChange++;
}
}
else {
aecpc->timeForDelayChange = 0;
}
aecpc->lastDelayDiff = diff;
if (aecpc->timeForDelayChange > 25) {
aecpc->knownDelay = WEBRTC_SPL_MAX((int)aecpc->filtDelay - 160, 0);
}
return 0;
}
static int DelayComp(aecpc_t *aecpc)
{
int nSampFar, nSampSndCard, delayNew, nSampAdd;
const int maxStuffSamp = 10 * FRAME_LEN;
nSampFar = WebRtcApm_get_buffer_size(aecpc->farendBuf);
nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->aec->mult;
delayNew = nSampSndCard - nSampFar;
// Account for resampling frame delay
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
delayNew -= kResamplingDelay;
}
if (delayNew > FAR_BUF_LEN - FRAME_LEN*aecpc->aec->mult) {
// The difference of the buffersizes is larger than the maximum
// allowed known delay. Compensate by stuffing the buffer.
nSampAdd = (int)(WEBRTC_SPL_MAX((int)(0.5 * nSampSndCard - nSampFar),
FRAME_LEN));
nSampAdd = WEBRTC_SPL_MIN(nSampAdd, maxStuffSamp);
WebRtcApm_StuffBuffer(aecpc->farendBuf, nSampAdd);
aecpc->delayChange = 1; // the delay needs to be updated
}
return 0;
}

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_INTERFACE_ECHO_CANCELLATION_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_INTERFACE_ECHO_CANCELLATION_H_
#include "typedefs.h"
// Errors
#define AEC_UNSPECIFIED_ERROR 12000
#define AEC_UNSUPPORTED_FUNCTION_ERROR 12001
#define AEC_UNINITIALIZED_ERROR 12002
#define AEC_NULL_POINTER_ERROR 12003
#define AEC_BAD_PARAMETER_ERROR 12004
// Warnings
#define AEC_BAD_PARAMETER_WARNING 12050
enum {
kAecNlpConservative = 0,
kAecNlpModerate,
kAecNlpAggressive
};
enum {
kAecFalse = 0,
kAecTrue
};
typedef struct {
WebRtc_Word16 nlpMode; // default kAecNlpModerate
WebRtc_Word16 skewMode; // default kAecFalse
WebRtc_Word16 metricsMode; // default kAecFalse
//float realSkew;
} AecConfig;
typedef struct {
WebRtc_Word16 instant;
WebRtc_Word16 average;
WebRtc_Word16 max;
WebRtc_Word16 min;
} AecLevel;
typedef struct {
AecLevel rerl;
AecLevel erl;
AecLevel erle;
AecLevel aNlp;
} AecMetrics;
#ifdef __cplusplus
extern "C" {
#endif
/*
* Allocates the memory needed by the AEC. The memory needs to be initialized
* separately using the WebRtcAec_Init() function.
*
* Inputs Description
* -------------------------------------------------------------------
* void **aecInst Pointer to the AEC instance to be created
* and initilized
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Create(void **aecInst);
/*
* This function releases the memory allocated by WebRtcAec_Create().
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Free(void *aecInst);
/*
* Initializes an AEC instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* WebRtc_Word32 sampFreq Sampling frequency of data
* WebRtc_Word32 scSampFreq Soundcard sampling frequency
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Init(void *aecInst,
WebRtc_Word32 sampFreq,
WebRtc_Word32 scSampFreq);
/*
* Inserts an 80 or 160 sample block of data into the farend buffer.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* WebRtc_Word16 *farend In buffer containing one frame of
* farend signal for L band
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst,
const WebRtc_Word16 *farend,
WebRtc_Word16 nrOfSamples);
/*
* Runs the echo canceller on an 80 or 160 sample blocks of data.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* WebRtc_Word16 *nearend In buffer containing one frame of
* nearend+echo signal for L band
* WebRtc_Word16 *nearendH In buffer containing one frame of
* nearend+echo signal for H band
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
* system buffers
* WebRtc_Word16 skew Difference between number of samples played
* and recorded at the soundcard (for clock skew
* compensation)
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
* for L band
* WebRtc_Word16 *outH Out buffer, one frame of processed nearend
* for H band
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_Process(void *aecInst,
const WebRtc_Word16 *nearend,
const WebRtc_Word16 *nearendH,
WebRtc_Word16 *out,
WebRtc_Word16 *outH,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 msInSndCardBuf,
WebRtc_Word32 skew);
/*
* This function enables the user to set certain parameters on-the-fly.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
* AecConfig config Config instance that contains all
* properties to be set
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_set_config(void *aecInst, AecConfig config);
/*
* Gets the on-the-fly paramters.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecConfig *config Pointer to the config instance that
* all properties will be written to
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_get_config(void *aecInst, AecConfig *config);
/*
* Gets the current echo status of the nearend signal.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *status 0: Almost certainly nearend single-talk
* 1: Might not be neared single-talk
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_get_echo_status(void *aecInst, WebRtc_Word16 *status);
/*
* Gets the current echo metrics for the session.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecMetrics *metrics Struct which will be filled out with the
* current echo metrics.
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_GetMetrics(void *aecInst, AecMetrics *metrics);
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 11000-11100: error code
*/
WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst);
/*
* Gets a version string.
*
* Inputs Description
* -------------------------------------------------------------------
* char *versionStr Pointer to a string array
* WebRtc_Word16 len The maximum length of the string
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word8 *versionStr Pointer to a string array
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAec_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len);
#ifdef __cplusplus
}
#endif
#endif /* WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_INTERFACE_ECHO_CANCELLATION_H_ */

View File

@@ -0,0 +1,235 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/* Resamples a signal to an arbitrary rate. Used by the AEC to compensate for clock
* skew by resampling the farend signal.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "resampler.h"
#include "aec_core.h"
enum { kFrameBufferSize = FRAME_LEN * 4 };
enum { kEstimateLengthFrames = 400 };
typedef struct {
short buffer[kFrameBufferSize];
float position;
int deviceSampleRateHz;
int skewData[kEstimateLengthFrames];
int skewDataIndex;
float skewEstimate;
} resampler_t;
static int EstimateSkew(const int* rawSkew,
int size,
int absLimit,
float *skewEst);
int WebRtcAec_CreateResampler(void **resampInst)
{
resampler_t *obj = malloc(sizeof(resampler_t));
*resampInst = obj;
if (obj == NULL) {
return -1;
}
return 0;
}
int WebRtcAec_InitResampler(void *resampInst, int deviceSampleRateHz)
{
resampler_t *obj = (resampler_t*) resampInst;
memset(obj->buffer, 0, sizeof(obj->buffer));
obj->position = 0.0;
obj->deviceSampleRateHz = deviceSampleRateHz;
memset(obj->skewData, 0, sizeof(obj->skewData));
obj->skewDataIndex = 0;
obj->skewEstimate = 0.0;
return 0;
}
int WebRtcAec_FreeResampler(void *resampInst)
{
resampler_t *obj = (resampler_t*) resampInst;
free(obj);
return 0;
}
int WebRtcAec_ResampleLinear(void *resampInst,
const short *inspeech,
int size,
float skew,
short *outspeech)
{
resampler_t *obj = (resampler_t*) resampInst;
short *y;
float be, tnew, interp;
int tn, outsize, mm;
if (size < 0 || size > 2 * FRAME_LEN) {
return -1;
}
// Add new frame data in lookahead
memcpy(&obj->buffer[FRAME_LEN + kResamplingDelay],
inspeech,
size * sizeof(short));
// Sample rate ratio
be = 1 + skew;
// Loop over input frame
mm = 0;
y = &obj->buffer[FRAME_LEN]; // Point at current frame
tnew = be * mm + obj->position;
tn = (int) tnew;
while (tn < size) {
// Interpolation
interp = y[tn] + (tnew - tn) * (y[tn+1] - y[tn]);
if (interp > 32767) {
interp = 32767;
}
else if (interp < -32768) {
interp = -32768;
}
outspeech[mm] = (short) interp;
mm++;
tnew = be * mm + obj->position;
tn = (int) tnew;
}
outsize = mm;
obj->position += outsize * be - size;
// Shift buffer
memmove(obj->buffer,
&obj->buffer[size],
(kFrameBufferSize - size) * sizeof(short));
return outsize;
}
int WebRtcAec_GetSkew(void *resampInst, int rawSkew, float *skewEst)
{
resampler_t *obj = (resampler_t*)resampInst;
int err = 0;
if (obj->skewDataIndex < kEstimateLengthFrames) {
obj->skewData[obj->skewDataIndex] = rawSkew;
obj->skewDataIndex++;
}
else if (obj->skewDataIndex == kEstimateLengthFrames) {
err = EstimateSkew(obj->skewData,
kEstimateLengthFrames,
obj->deviceSampleRateHz,
skewEst);
obj->skewEstimate = *skewEst;
obj->skewDataIndex++;
}
else {
*skewEst = obj->skewEstimate;
}
return err;
}
int EstimateSkew(const int* rawSkew,
const int size,
const int deviceSampleRateHz,
float *skewEst)
{
const int absLimitOuter = (int)(0.04f * deviceSampleRateHz);
const int absLimitInner = (int)(0.0025f * deviceSampleRateHz);
int i = 0;
int n = 0;
float rawAvg = 0;
float err = 0;
float rawAbsDev = 0;
int upperLimit = 0;
int lowerLimit = 0;
float cumSum = 0;
float x = 0;
float x2 = 0;
float y = 0;
float xy = 0;
float xAvg = 0;
float yAvg = 0;
float denom = 0;
float skew = 0;
*skewEst = 0; // Set in case of error below.
for (i = 0; i < size; i++) {
if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) {
n++;
rawAvg += rawSkew[i];
}
}
if (n == 0) {
return -1;
}
assert(n > 0);
rawAvg /= n;
for (i = 0; i < size; i++) {
if ((rawSkew[i] < absLimitOuter && rawSkew[i] > -absLimitOuter)) {
err = rawSkew[i] - rawAvg;
rawAbsDev += err >= 0 ? err : -err;
}
}
assert(n > 0);
rawAbsDev /= n;
upperLimit = (int)(rawAvg + 5 * rawAbsDev + 1); // +1 for ceiling.
lowerLimit = (int)(rawAvg - 5 * rawAbsDev - 1); // -1 for floor.
n = 0;
for (i = 0; i < size; i++) {
if ((rawSkew[i] < absLimitInner && rawSkew[i] > -absLimitInner) ||
(rawSkew[i] < upperLimit && rawSkew[i] > lowerLimit)) {
n++;
cumSum += rawSkew[i];
x += n;
x2 += n*n;
y += cumSum;
xy += n * cumSum;
}
}
if (n == 0) {
return -1;
}
assert(n > 0);
xAvg = x / n;
yAvg = y / n;
denom = x2 - xAvg*x;
if (denom != 0) {
skew = (xy - xAvg*y) / denom;
}
*skewEst = skew;
return 0;
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_RESAMPLER_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_RESAMPLER_H_
enum { kResamplingDelay = 1 };
// Unless otherwise specified, functions return 0 on success and -1 on error
int WebRtcAec_CreateResampler(void **resampInst);
int WebRtcAec_InitResampler(void *resampInst, int deviceSampleRateHz);
int WebRtcAec_FreeResampler(void *resampInst);
// Estimates skew from raw measurement.
int WebRtcAec_GetSkew(void *resampInst, int rawSkew, float *skewEst);
// Resamples input using linear interpolation.
// Returns size of resampled array.
int WebRtcAec_ResampleLinear(void *resampInst,
const short *inspeech,
int size,
float skew,
short *outspeech);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_RESAMPLER_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,313 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Performs echo control (suppression) with fft routines in fixed-point
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_
#define AECM_DYNAMIC_Q // turn on/off dynamic Q-domain
//#define AECM_WITH_ABS_APPROX
//#define AECM_SHORT // for 32 sample partition length (otherwise 64)
#include "typedefs.h"
#include "signal_processing_library.h"
#include "typedefs.h"
// Algorithm parameters
#define FRAME_LEN 80 // Total frame length, 10 ms
#ifdef AECM_SHORT
#define PART_LEN 32 // Length of partition
#define PART_LEN_SHIFT 6 // Length of (PART_LEN * 2) in base 2
#else
#define PART_LEN 64 // Length of partition
#define PART_LEN_SHIFT 7 // Length of (PART_LEN * 2) in base 2
#endif
#define PART_LEN1 (PART_LEN + 1) // Unique fft coefficients
#define PART_LEN2 (PART_LEN << 1) // Length of partition * 2
#define PART_LEN4 (PART_LEN << 2) // Length of partition * 4
#define FAR_BUF_LEN PART_LEN4 // Length of buffers
#define MAX_DELAY 100
// Counter parameters
#ifdef AECM_SHORT
#define CONV_LEN 1024 // Convergence length used at startup
#else
#define CONV_LEN 512 // Convergence length used at startup
#endif
#define CONV_LEN2 (CONV_LEN << 1) // Convergence length * 2 used at startup
// Energy parameters
#define MAX_BUF_LEN 64 // History length of energy signals
#define FAR_ENERGY_MIN 1025 // Lowest Far energy level: At least 2 in energy
#define FAR_ENERGY_DIFF 511 // Difference between max and min should be at least 2 (Q8)
#define ENERGY_DEV_OFFSET 0 // The energy error offset in Q8
#define ENERGY_DEV_TOL 400 // The energy estimation tolerance in Q8
#define FAR_ENERGY_VAD_REGION 230 // Far VAD tolerance region
// Stepsize parameters
#define MU_MIN 10 // Min stepsize 2^-MU_MIN (far end energy dependent)
#define MU_MAX 1 // Max stepsize 2^-MU_MAX (far end energy dependent)
#define MU_DIFF 9 // MU_MIN - MU_MAX
// Channel parameters
#define MIN_MSE_COUNT 20 // Min number of consecutive blocks with enough far end
// energy to compare channel estimates
#define MIN_MSE_DIFF 29 // The ratio between adapted and stored channel to
// accept a new storage (0.8 in Q-MSE_RESOLUTION)
#define MSE_RESOLUTION 5 // MSE parameter resolution
#define RESOLUTION_CHANNEL16 12 // W16 Channel in Q-RESOLUTION_CHANNEL16
#define RESOLUTION_CHANNEL32 28 // W32 Channel in Q-RESOLUTION_CHANNEL
#define CHANNEL_VAD 16 // Minimum energy in frequency band to update channel
// Suppression gain parameters: SUPGAIN_ parameters in Q-(RESOLUTION_SUPGAIN)
#define RESOLUTION_SUPGAIN 8 // Channel in Q-(RESOLUTION_SUPGAIN)
#define SUPGAIN_DEFAULT (1 << RESOLUTION_SUPGAIN) // Default suppression gain
#define SUPGAIN_ERROR_PARAM_A 3072 // Estimation error parameter (Maximum gain) (8 in Q8)
#define SUPGAIN_ERROR_PARAM_B 1536 // Estimation error parameter (Gain before going down)
#define SUPGAIN_ERROR_PARAM_D SUPGAIN_DEFAULT // Estimation error parameter
// (Should be the same as Default) (1 in Q8)
#define SUPGAIN_EPC_DT 200 // = SUPGAIN_ERROR_PARAM_C * ENERGY_DEV_TOL
// Defines for "check delay estimation"
#define CORR_WIDTH 31 // Number of samples to correlate over.
#define CORR_MAX 16 // Maximum correlation offset
#define CORR_MAX_BUF 63
#define CORR_DEV 4
#define CORR_MAX_LEVEL 20
#define CORR_MAX_LOW 4
#define CORR_BUF_LEN (CORR_MAX << 1) + 1
// Note that CORR_WIDTH + 2*CORR_MAX <= MAX_BUF_LEN
#define ONE_Q14 (1 << 14)
// NLP defines
#define NLP_COMP_LOW 3277 // 0.2 in Q14
#define NLP_COMP_HIGH ONE_Q14 // 1 in Q14
typedef struct
{
int farBufWritePos;
int farBufReadPos;
int knownDelay;
int lastKnownDelay;
void *farFrameBuf;
void *nearNoisyFrameBuf;
void *nearCleanFrameBuf;
void *outFrameBuf;
WebRtc_Word16 xBuf[PART_LEN2]; // farend
WebRtc_Word16 dBufClean[PART_LEN2]; // nearend
WebRtc_Word16 dBufNoisy[PART_LEN2]; // nearend
WebRtc_Word16 outBuf[PART_LEN];
WebRtc_Word16 farBuf[FAR_BUF_LEN];
WebRtc_Word16 mult;
WebRtc_UWord32 seed;
// Delay estimation variables
WebRtc_UWord16 medianYlogspec[PART_LEN1];
WebRtc_UWord16 medianXlogspec[PART_LEN1];
WebRtc_UWord16 medianBCount[MAX_DELAY];
WebRtc_UWord16 xfaHistory[PART_LEN1][MAX_DELAY];
WebRtc_Word16 delHistoryPos;
WebRtc_UWord32 bxHistory[MAX_DELAY];
WebRtc_UWord16 currentDelay;
WebRtc_UWord16 previousDelay;
WebRtc_Word16 delayAdjust;
WebRtc_Word16 nlpFlag;
WebRtc_Word16 fixedDelay;
WebRtc_UWord32 totCount;
WebRtc_Word16 xfaQDomainBuf[MAX_DELAY];
WebRtc_Word16 dfaCleanQDomain;
WebRtc_Word16 dfaCleanQDomainOld;
WebRtc_Word16 dfaNoisyQDomain;
WebRtc_Word16 dfaNoisyQDomainOld;
WebRtc_Word16 nearLogEnergy[MAX_BUF_LEN];
WebRtc_Word16 farLogEnergy[MAX_BUF_LEN];
WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN];
WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN];
WebRtc_Word16 channelAdapt16[PART_LEN1];
WebRtc_Word32 channelAdapt32[PART_LEN1];
WebRtc_Word16 channelStored[PART_LEN1];
WebRtc_Word32 echoFilt[PART_LEN1];
WebRtc_Word16 nearFilt[PART_LEN1];
WebRtc_Word32 noiseEst[PART_LEN1];
WebRtc_Word16 noiseEstQDomain[PART_LEN1];
WebRtc_Word16 noiseEstCtr;
WebRtc_Word16 cngMode;
WebRtc_Word32 mseAdaptOld;
WebRtc_Word32 mseStoredOld;
WebRtc_Word32 mseThreshold;
WebRtc_Word16 farEnergyMin;
WebRtc_Word16 farEnergyMax;
WebRtc_Word16 farEnergyMaxMin;
WebRtc_Word16 farEnergyVAD;
WebRtc_Word16 farEnergyMSE;
WebRtc_Word16 currentVADValue;
WebRtc_Word16 vadUpdateCount;
WebRtc_Word16 delayHistogram[MAX_DELAY];
WebRtc_Word16 delayVadCount;
WebRtc_Word16 maxDelayHistIdx;
WebRtc_Word16 lastMinPos;
WebRtc_Word16 startupState;
WebRtc_Word16 mseChannelCount;
WebRtc_Word16 delayCount;
WebRtc_Word16 newDelayCorrData;
WebRtc_Word16 lastDelayUpdateCount;
WebRtc_Word16 delayCorrelation[CORR_BUF_LEN];
WebRtc_Word16 supGain;
WebRtc_Word16 supGainOld;
WebRtc_Word16 delayOffsetFlag;
WebRtc_Word16 supGainErrParamA;
WebRtc_Word16 supGainErrParamD;
WebRtc_Word16 supGainErrParamDiffAB;
WebRtc_Word16 supGainErrParamDiffBD;
#ifdef AEC_DEBUG
FILE *farFile;
FILE *nearFile;
FILE *outFile;
#endif
} AecmCore_t;
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_CreateCore(...)
//
// Allocates the memory needed by the AECM. The memory needs to be
// initialized separately using the WebRtcAecm_InitCore() function.
//
// Input:
// - aecm : Instance that should be created
//
// Output:
// - aecm : Created instance
//
// Return value : 0 - Ok
// -1 - Error
//
int WebRtcAecm_CreateCore(AecmCore_t **aecm);
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_InitCore(...)
//
// This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
// Input:
// - aecm : Pointer to the AECM instance
// - samplingFreq : Sampling Frequency
//
// Output:
// - aecm : Initialized instance
//
// Return value : 0 - Ok
// -1 - Error
//
int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq);
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_FreeCore(...)
//
// This function releases the memory allocated by WebRtcAecm_CreateCore()
// Input:
// - aecm : Pointer to the AECM instance
//
// Return value : 0 - Ok
// -1 - Error
// 11001-11016: Error
//
int WebRtcAecm_FreeCore(AecmCore_t *aecm);
int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag, int delayOffsetFlag);
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_ProcessFrame(...)
//
// This function processes frames and sends blocks to WebRtcAecm_ProcessBlock(...)
//
// Inputs:
// - aecm : Pointer to the AECM instance
// - farend : In buffer containing one frame of echo signal
// - nearendNoisy : In buffer containing one frame of nearend+echo signal without NS
// - nearendClean : In buffer containing one frame of nearend+echo signal with NS
//
// Output:
// - out : Out buffer, one frame of nearend signal :
//
//
void WebRtcAecm_ProcessFrame(AecmCore_t * const aecm, const WebRtc_Word16 * const farend,
const WebRtc_Word16 * const nearendNoisy,
const WebRtc_Word16 * const nearendClean,
WebRtc_Word16 * const out);
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_ProcessBlock(...)
//
// This function is called for every block within one frame
// This function is called by WebRtcAecm_ProcessFrame(...)
//
// Inputs:
// - aecm : Pointer to the AECM instance
// - farend : In buffer containing one block of echo signal
// - nearendNoisy : In buffer containing one frame of nearend+echo signal without NS
// - nearendClean : In buffer containing one frame of nearend+echo signal with NS
//
// Output:
// - out : Out buffer, one block of nearend signal :
//
//
void WebRtcAecm_ProcessBlock(AecmCore_t * const aecm, const WebRtc_Word16 * const farend,
const WebRtc_Word16 * const nearendNoisy,
const WebRtc_Word16 * const noisyClean,
WebRtc_Word16 * const out);
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_BufferFarFrame()
//
// Inserts a frame of data into farend buffer.
//
// Inputs:
// - aecm : Pointer to the AECM instance
// - farend : In buffer containing one frame of farend signal
// - farLen : Length of frame
//
void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, const WebRtc_Word16 * const farend,
const int farLen);
///////////////////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_FetchFarFrame()
//
// Read the farend buffer to account for known delay
//
// Inputs:
// - aecm : Pointer to the AECM instance
// - farend : In buffer containing one frame of farend signal
// - farLen : Length of frame
// - knownDelay : known delay
//
void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend,
const int farLen, const int knownDelay);
#endif

View File

@@ -0,0 +1,733 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdlib.h>
//#include <string.h>
#include "echo_control_mobile.h"
#include "aecm_core.h"
#include "ring_buffer.h"
#ifdef AEC_DEBUG
#include <stdio.h>
#endif
#ifdef MAC_IPHONE_PRINT
#include <time.h>
#include <stdio.h>
#elif defined ARM_WINM_LOG
#include "windows.h"
extern HANDLE logFile;
#endif
#define BUF_SIZE_FRAMES 50 // buffer size (frames)
// Maximum length of resampled signal. Must be an integer multiple of frames
// (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN
// The factor of 2 handles wb, and the + 1 is as a safety margin
#define MAX_RESAMP_LEN (5 * FRAME_LEN)
static const int kBufSizeSamp = BUF_SIZE_FRAMES * FRAME_LEN; // buffer size (samples)
static const int kSampMsNb = 8; // samples per ms in nb
// Target suppression levels for nlp modes
// log{0.001, 0.00001, 0.00000001}
static const int kInitCheck = 42;
typedef struct
{
int sampFreq;
int scSampFreq;
short bufSizeStart;
int knownDelay;
// Stores the last frame added to the farend buffer
short farendOld[2][FRAME_LEN];
short initFlag; // indicates if AEC has been initialized
// Variables used for averaging far end buffer size
short counter;
short sum;
short firstVal;
short checkBufSizeCtr;
// Variables used for delay shifts
short msInSndCardBuf;
short filtDelay;
int timeForDelayChange;
int ECstartup;
int checkBuffSize;
int delayChange;
short lastDelayDiff;
WebRtc_Word16 echoMode;
#ifdef AEC_DEBUG
FILE *bufFile;
FILE *delayFile;
FILE *preCompFile;
FILE *postCompFile;
#endif // AEC_DEBUG
// Structures
void *farendBuf;
int lastError;
AecmCore_t *aecmCore;
} aecmob_t;
// Estimates delay to set the position of the farend buffer read pointer
// (controlled by knownDelay)
static int WebRtcAecm_EstBufDelay(aecmob_t *aecmInst, short msInSndCardBuf);
// Stuffs the farend buffer if the estimated delay is too large
static int WebRtcAecm_DelayComp(aecmob_t *aecmInst);
WebRtc_Word32 WebRtcAecm_Create(void **aecmInst)
{
aecmob_t *aecm;
if (aecmInst == NULL)
{
return -1;
}
aecm = malloc(sizeof(aecmob_t));
*aecmInst = aecm;
if (aecm == NULL)
{
return -1;
}
if (WebRtcAecm_CreateCore(&aecm->aecmCore) == -1)
{
WebRtcAecm_Free(aecm);
aecm = NULL;
return -1;
}
if (WebRtcApm_CreateBuffer(&aecm->farendBuf, kBufSizeSamp) == -1)
{
WebRtcAecm_Free(aecm);
aecm = NULL;
return -1;
}
aecm->initFlag = 0;
aecm->lastError = 0;
#ifdef AEC_DEBUG
aecm->aecmCore->farFile = fopen("aecFar.pcm","wb");
aecm->aecmCore->nearFile = fopen("aecNear.pcm","wb");
aecm->aecmCore->outFile = fopen("aecOut.pcm","wb");
//aecm->aecmCore->outLpFile = fopen("aecOutLp.pcm","wb");
aecm->bufFile = fopen("aecBuf.dat", "wb");
aecm->delayFile = fopen("aecDelay.dat", "wb");
aecm->preCompFile = fopen("preComp.pcm", "wb");
aecm->postCompFile = fopen("postComp.pcm", "wb");
#endif // AEC_DEBUG
return 0;
}
WebRtc_Word32 WebRtcAecm_Free(void *aecmInst)
{
aecmob_t *aecm = aecmInst;
if (aecm == NULL)
{
return -1;
}
#ifdef AEC_DEBUG
fclose(aecm->aecmCore->farFile);
fclose(aecm->aecmCore->nearFile);
fclose(aecm->aecmCore->outFile);
//fclose(aecm->aecmCore->outLpFile);
fclose(aecm->bufFile);
fclose(aecm->delayFile);
fclose(aecm->preCompFile);
fclose(aecm->postCompFile);
#endif // AEC_DEBUG
WebRtcAecm_FreeCore(aecm->aecmCore);
WebRtcApm_FreeBuffer(aecm->farendBuf);
free(aecm);
return 0;
}
WebRtc_Word32 WebRtcAecm_Init(void *aecmInst, WebRtc_Word32 sampFreq, WebRtc_Word32 scSampFreq)
{
aecmob_t *aecm = aecmInst;
AecmConfig aecConfig;
if (aecm == NULL)
{
return -1;
}
if (sampFreq != 8000 && sampFreq != 16000)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->sampFreq = sampFreq;
if (scSampFreq < 1 || scSampFreq > 96000)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->scSampFreq = scSampFreq;
// Initialize AECM core
if (WebRtcAecm_InitCore(aecm->aecmCore, aecm->sampFreq) == -1)
{
aecm->lastError = AECM_UNSPECIFIED_ERROR;
return -1;
}
// Initialize farend buffer
if (WebRtcApm_InitBuffer(aecm->farendBuf) == -1)
{
aecm->lastError = AECM_UNSPECIFIED_ERROR;
return -1;
}
aecm->initFlag = kInitCheck; // indicates that initialization has been done
aecm->delayChange = 1;
aecm->sum = 0;
aecm->counter = 0;
aecm->checkBuffSize = 1;
aecm->firstVal = 0;
aecm->ECstartup = 1;
aecm->bufSizeStart = 0;
aecm->checkBufSizeCtr = 0;
aecm->filtDelay = 0;
aecm->timeForDelayChange = 0;
aecm->knownDelay = 0;
aecm->lastDelayDiff = 0;
memset(&aecm->farendOld[0][0], 0, 160);
// Default settings.
aecConfig.cngMode = AecmTrue;
aecConfig.echoMode = 3;
if (WebRtcAecm_set_config(aecm, aecConfig) == -1)
{
aecm->lastError = AECM_UNSPECIFIED_ERROR;
return -1;
}
return 0;
}
WebRtc_Word32 WebRtcAecm_BufferFarend(void *aecmInst, const WebRtc_Word16 *farend,
WebRtc_Word16 nrOfSamples)
{
aecmob_t *aecm = aecmInst;
WebRtc_Word32 retVal = 0;
if (aecm == NULL)
{
return -1;
}
if (farend == NULL)
{
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
if (nrOfSamples != 80 && nrOfSamples != 160)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
// TODO: Is this really a good idea?
if (!aecm->ECstartup)
{
WebRtcAecm_DelayComp(aecm);
}
WebRtcApm_WriteBuffer(aecm->farendBuf, farend, nrOfSamples);
return retVal;
}
WebRtc_Word32 WebRtcAecm_Process(void *aecmInst, const WebRtc_Word16 *nearendNoisy,
const WebRtc_Word16 *nearendClean, WebRtc_Word16 *out,
WebRtc_Word16 nrOfSamples, WebRtc_Word16 msInSndCardBuf)
{
aecmob_t *aecm = aecmInst;
WebRtc_Word32 retVal = 0;
short i;
short farend[FRAME_LEN];
short nmbrOfFilledBuffers;
short nBlocks10ms;
short nFrames;
#ifdef AEC_DEBUG
short msInAECBuf;
#endif
#ifdef ARM_WINM_LOG
__int64 freq, start, end, diff;
unsigned int milliseconds;
DWORD temp;
#elif defined MAC_IPHONE_PRINT
// double endtime = 0, starttime = 0;
struct timeval starttime;
struct timeval endtime;
static long int timeused = 0;
static int timecount = 0;
#endif
if (aecm == NULL)
{
return -1;
}
if (nearendNoisy == NULL)
{
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (out == NULL)
{
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
if (nrOfSamples != 80 && nrOfSamples != 160)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
if (msInSndCardBuf < 0)
{
msInSndCardBuf = 0;
aecm->lastError = AECM_BAD_PARAMETER_WARNING;
retVal = -1;
} else if (msInSndCardBuf > 500)
{
msInSndCardBuf = 500;
aecm->lastError = AECM_BAD_PARAMETER_WARNING;
retVal = -1;
}
msInSndCardBuf += 10;
aecm->msInSndCardBuf = msInSndCardBuf;
nFrames = nrOfSamples / FRAME_LEN;
nBlocks10ms = nFrames / aecm->aecmCore->mult;
if (aecm->ECstartup)
{
if (nearendClean == NULL)
{
memcpy(out, nearendNoisy, sizeof(short) * nrOfSamples);
} else
{
memcpy(out, nearendClean, sizeof(short) * nrOfSamples);
}
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecm->farendBuf) / FRAME_LEN;
// The AECM is in the start up mode
// AECM is disabled until the soundcard buffer and farend buffers are OK
// Mechanism to ensure that the soundcard buffer is reasonably stable.
if (aecm->checkBuffSize)
{
aecm->checkBufSizeCtr++;
// Before we fill up the far end buffer we require the amount of data on the
// sound card to be stable (+/-8 ms) compared to the first value. This
// comparison is made during the following 4 consecutive frames. If it seems
// to be stable then we start to fill up the far end buffer.
if (aecm->counter == 0)
{
aecm->firstVal = aecm->msInSndCardBuf;
aecm->sum = 0;
}
if (abs(aecm->firstVal - aecm->msInSndCardBuf)
< WEBRTC_SPL_MAX(0.2 * aecm->msInSndCardBuf, kSampMsNb))
{
aecm->sum += aecm->msInSndCardBuf;
aecm->counter++;
} else
{
aecm->counter = 0;
}
if (aecm->counter * nBlocks10ms >= 6)
{
// The farend buffer size is determined in blocks of 80 samples
// Use 75% of the average value of the soundcard buffer
aecm->bufSizeStart
= WEBRTC_SPL_MIN((3 * aecm->sum
* aecm->aecmCore->mult) / (aecm->counter * 40), BUF_SIZE_FRAMES);
// buffersize has now been determined
aecm->checkBuffSize = 0;
}
if (aecm->checkBufSizeCtr * nBlocks10ms > 50)
{
// for really bad sound cards, don't disable echocanceller for more than 0.5 sec
aecm->bufSizeStart = WEBRTC_SPL_MIN((3 * aecm->msInSndCardBuf
* aecm->aecmCore->mult) / 40, BUF_SIZE_FRAMES);
aecm->checkBuffSize = 0;
}
}
// if checkBuffSize changed in the if-statement above
if (!aecm->checkBuffSize)
{
// soundcard buffer is now reasonably stable
// When the far end buffer is filled with approximately the same amount of
// data as the amount on the sound card we end the start up phase and start
// to cancel echoes.
if (nmbrOfFilledBuffers == aecm->bufSizeStart)
{
aecm->ECstartup = 0; // Enable the AECM
} else if (nmbrOfFilledBuffers > aecm->bufSizeStart)
{
WebRtcApm_FlushBuffer(
aecm->farendBuf,
WebRtcApm_get_buffer_size(aecm->farendBuf)
- aecm->bufSizeStart * FRAME_LEN);
aecm->ECstartup = 0;
}
}
} else
{
// AECM is enabled
// Note only 1 block supported for nb and 2 blocks for wb
for (i = 0; i < nFrames; i++)
{
nmbrOfFilledBuffers = WebRtcApm_get_buffer_size(aecm->farendBuf) / FRAME_LEN;
// Check that there is data in the far end buffer
if (nmbrOfFilledBuffers > 0)
{
// Get the next 80 samples from the farend buffer
WebRtcApm_ReadBuffer(aecm->farendBuf, farend, FRAME_LEN);
// Always store the last frame for use when we run out of data
memcpy(&(aecm->farendOld[i][0]), farend, FRAME_LEN * sizeof(short));
} else
{
// We have no data so we use the last played frame
memcpy(farend, &(aecm->farendOld[i][0]), FRAME_LEN * sizeof(short));
}
// Call buffer delay estimator when all data is extracted,
// i,e. i = 0 for NB and i = 1 for WB
if ((i == 0 && aecm->sampFreq == 8000) || (i == 1 && aecm->sampFreq == 16000))
{
WebRtcAecm_EstBufDelay(aecm, aecm->msInSndCardBuf);
}
#ifdef ARM_WINM_LOG
// measure tick start
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
QueryPerformanceCounter((LARGE_INTEGER*)&start);
#elif defined MAC_IPHONE_PRINT
// starttime = clock()/(double)CLOCKS_PER_SEC;
gettimeofday(&starttime, NULL);
#endif
// Call the AECM
/*WebRtcAecm_ProcessFrame(aecm->aecmCore, farend, &nearend[FRAME_LEN * i],
&out[FRAME_LEN * i], aecm->knownDelay);*/
if (nearendClean == NULL)
{
WebRtcAecm_ProcessFrame(aecm->aecmCore, farend, &nearendNoisy[FRAME_LEN * i],
NULL, &out[FRAME_LEN * i]);
} else
{
WebRtcAecm_ProcessFrame(aecm->aecmCore, farend, &nearendNoisy[FRAME_LEN * i],
&nearendClean[FRAME_LEN * i], &out[FRAME_LEN * i]);
}
#ifdef ARM_WINM_LOG
// measure tick end
QueryPerformanceCounter((LARGE_INTEGER*)&end);
if(end > start)
{
diff = ((end - start) * 1000) / (freq/1000);
milliseconds = (unsigned int)(diff & 0xffffffff);
WriteFile (logFile, &milliseconds, sizeof(unsigned int), &temp, NULL);
}
#elif defined MAC_IPHONE_PRINT
// endtime = clock()/(double)CLOCKS_PER_SEC;
// printf("%f\n", endtime - starttime);
gettimeofday(&endtime, NULL);
if( endtime.tv_usec > starttime.tv_usec)
{
timeused += endtime.tv_usec - starttime.tv_usec;
} else
{
timeused += endtime.tv_usec + 1000000 - starttime.tv_usec;
}
if(++timecount == 1000)
{
timecount = 0;
printf("AEC: %ld\n", timeused);
timeused = 0;
}
#endif
}
}
#ifdef AEC_DEBUG
msInAECBuf = WebRtcApm_get_buffer_size(aecm->farendBuf) / (kSampMsNb*aecm->aecmCore->mult);
fwrite(&msInAECBuf, 2, 1, aecm->bufFile);
fwrite(&(aecm->knownDelay), sizeof(aecm->knownDelay), 1, aecm->delayFile);
#endif
return retVal;
}
WebRtc_Word32 WebRtcAecm_set_config(void *aecmInst, AecmConfig config)
{
aecmob_t *aecm = aecmInst;
if (aecm == NULL)
{
return -1;
}
if (aecm->initFlag != kInitCheck)
{
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
if (config.cngMode != AecmFalse && config.cngMode != AecmTrue)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->aecmCore->cngMode = config.cngMode;
if (config.echoMode < 0 || config.echoMode > 4)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->echoMode = config.echoMode;
if (aecm->echoMode == 0)
{
aecm->aecmCore->supGain = SUPGAIN_DEFAULT >> 3;
aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT >> 3;
aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A >> 3;
aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D >> 3;
aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A >> 3)
- (SUPGAIN_ERROR_PARAM_B >> 3);
aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B >> 3)
- (SUPGAIN_ERROR_PARAM_D >> 3);
} else if (aecm->echoMode == 1)
{
aecm->aecmCore->supGain = SUPGAIN_DEFAULT >> 2;
aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT >> 2;
aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A >> 2;
aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D >> 2;
aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A >> 2)
- (SUPGAIN_ERROR_PARAM_B >> 2);
aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B >> 2)
- (SUPGAIN_ERROR_PARAM_D >> 2);
} else if (aecm->echoMode == 2)
{
aecm->aecmCore->supGain = SUPGAIN_DEFAULT >> 1;
aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT >> 1;
aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A >> 1;
aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D >> 1;
aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A >> 1)
- (SUPGAIN_ERROR_PARAM_B >> 1);
aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B >> 1)
- (SUPGAIN_ERROR_PARAM_D >> 1);
} else if (aecm->echoMode == 3)
{
aecm->aecmCore->supGain = SUPGAIN_DEFAULT;
aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT;
aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A;
aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D;
aecm->aecmCore->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B;
aecm->aecmCore->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D;
} else if (aecm->echoMode == 4)
{
aecm->aecmCore->supGain = SUPGAIN_DEFAULT << 1;
aecm->aecmCore->supGainOld = SUPGAIN_DEFAULT << 1;
aecm->aecmCore->supGainErrParamA = SUPGAIN_ERROR_PARAM_A << 1;
aecm->aecmCore->supGainErrParamD = SUPGAIN_ERROR_PARAM_D << 1;
aecm->aecmCore->supGainErrParamDiffAB = (SUPGAIN_ERROR_PARAM_A << 1)
- (SUPGAIN_ERROR_PARAM_B << 1);
aecm->aecmCore->supGainErrParamDiffBD = (SUPGAIN_ERROR_PARAM_B << 1)
- (SUPGAIN_ERROR_PARAM_D << 1);
}
return 0;
}
WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst, AecmConfig *config)
{
aecmob_t *aecm = aecmInst;
if (aecm == NULL)
{
return -1;
}
if (config == NULL)
{
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
config->cngMode = aecm->aecmCore->cngMode;
config->echoMode = aecm->echoMode;
return 0;
}
WebRtc_Word32 WebRtcAecm_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
{
const char version[] = "AECM 1.2.0";
const short versionLen = (short)strlen(version) + 1; // +1 for null-termination
if (versionStr == NULL)
{
return -1;
}
if (versionLen > len)
{
return -1;
}
strncpy(versionStr, version, versionLen);
return 0;
}
WebRtc_Word32 WebRtcAecm_get_error_code(void *aecmInst)
{
aecmob_t *aecm = aecmInst;
if (aecm == NULL)
{
return -1;
}
return aecm->lastError;
}
static int WebRtcAecm_EstBufDelay(aecmob_t *aecm, short msInSndCardBuf)
{
short delayNew, nSampFar, nSampSndCard;
short diff;
nSampFar = WebRtcApm_get_buffer_size(aecm->farendBuf);
nSampSndCard = msInSndCardBuf * kSampMsNb * aecm->aecmCore->mult;
delayNew = nSampSndCard - nSampFar;
if (delayNew < FRAME_LEN)
{
WebRtcApm_FlushBuffer(aecm->farendBuf, FRAME_LEN);
delayNew += FRAME_LEN;
}
aecm->filtDelay = WEBRTC_SPL_MAX(0, (8 * aecm->filtDelay + 2 * delayNew) / 10);
diff = aecm->filtDelay - aecm->knownDelay;
if (diff > 224)
{
if (aecm->lastDelayDiff < 96)
{
aecm->timeForDelayChange = 0;
} else
{
aecm->timeForDelayChange++;
}
} else if (diff < 96 && aecm->knownDelay > 0)
{
if (aecm->lastDelayDiff > 224)
{
aecm->timeForDelayChange = 0;
} else
{
aecm->timeForDelayChange++;
}
} else
{
aecm->timeForDelayChange = 0;
}
aecm->lastDelayDiff = diff;
if (aecm->timeForDelayChange > 25)
{
aecm->knownDelay = WEBRTC_SPL_MAX((int)aecm->filtDelay - 160, 0);
}
return 0;
}
static int WebRtcAecm_DelayComp(aecmob_t *aecm)
{
int nSampFar, nSampSndCard, delayNew, nSampAdd;
const int maxStuffSamp = 10 * FRAME_LEN;
nSampFar = WebRtcApm_get_buffer_size(aecm->farendBuf);
nSampSndCard = aecm->msInSndCardBuf * kSampMsNb * aecm->aecmCore->mult;
delayNew = nSampSndCard - nSampFar;
if (delayNew > FAR_BUF_LEN - FRAME_LEN * aecm->aecmCore->mult)
{
// The difference of the buffer sizes is larger than the maximum
// allowed known delay. Compensate by stuffing the buffer.
nSampAdd = (int)(WEBRTC_SPL_MAX(((nSampSndCard >> 1) - nSampFar),
FRAME_LEN));
nSampAdd = WEBRTC_SPL_MIN(nSampAdd, maxStuffSamp);
WebRtcApm_StuffBuffer(aecm->farendBuf, nSampAdd);
aecm->delayChange = 1; // the delay needs to be updated
}
return 0;
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_INTERFACE_ECHO_CONTROL_MOBILE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_INTERFACE_ECHO_CONTROL_MOBILE_H_
#include "typedefs.h"
enum {
AecmFalse = 0,
AecmTrue
};
// Errors
#define AECM_UNSPECIFIED_ERROR 12000
#define AECM_UNSUPPORTED_FUNCTION_ERROR 12001
#define AECM_UNINITIALIZED_ERROR 12002
#define AECM_NULL_POINTER_ERROR 12003
#define AECM_BAD_PARAMETER_ERROR 12004
// Warnings
#define AECM_BAD_PARAMETER_WARNING 12100
typedef struct {
WebRtc_Word16 cngMode; // AECM_FALSE, AECM_TRUE (default)
WebRtc_Word16 echoMode; // 0, 1, 2, 3 (default), 4
} AecmConfig;
#ifdef __cplusplus
extern "C" {
#endif
/*
* Allocates the memory needed by the AECM. The memory needs to be
* initialized separately using the WebRtcAecm_Init() function.
*
* Inputs Description
* -------------------------------------------------------------------
* void **aecmInst Pointer to the AECM instance to be
* created and initialized
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Create(void **aecmInst);
/*
* This function releases the memory allocated by WebRtcAecm_Create()
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Free(void *aecmInst);
/*
* Initializes an AECM instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word32 sampFreq Sampling frequency of data
* WebRtc_Word32 scSampFreq Soundcard sampling frequency
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Init(void* aecmInst,
WebRtc_Word32 sampFreq,
WebRtc_Word32 scSampFreq);
/*
* Inserts an 80 or 160 sample block of data into the farend buffer.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word16 *farend In buffer containing one frame of
* farend signal
* WebRtc_Word16 nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_BufferFarend(void* aecmInst,
const WebRtc_Word16* farend,
WebRtc_Word16 nrOfSamples);
/*
* Runs the AECM on an 80 or 160 sample blocks of data.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* WebRtc_Word16 *nearendNoisy In buffer containing one frame of
* reference nearend+echo signal. If
* noise reduction is active, provide
* the noisy signal here.
* WebRtc_Word16 *nearendClean In buffer containing one frame of
* nearend+echo signal. If noise
* reduction is active, provide the
* clean signal here. Otherwise pass a
* NULL pointer.
* WebRtc_Word16 nrOfSamples Number of samples in nearend buffer
* WebRtc_Word16 msInSndCardBuf Delay estimate for sound card and
* system buffers
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word16 *out Out buffer, one frame of processed nearend
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_Process(void* aecmInst,
const WebRtc_Word16* nearendNoisy,
const WebRtc_Word16* nearendClean,
WebRtc_Word16* out,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 msInSndCardBuf);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
* AecmConfig config Config instance that contains all
* properties to be set
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_set_config(void* aecmInst,
AecmConfig config);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecmConfig *config Pointer to the config instance that
* all properties will be written to
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst,
AecmConfig *config);
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void *aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word32 return 11000-11100: error code
*/
WebRtc_Word32 WebRtcAecm_get_error_code(void *aecmInst);
/*
* Gets a version string
*
* Inputs Description
* -------------------------------------------------------------------
* char *versionStr Pointer to a string array
* WebRtc_Word16 len The maximum length of the string
*
* Outputs Description
* -------------------------------------------------------------------
* WebRtc_Word8 *versionStr Pointer to a string array
* WebRtc_Word32 return 0: OK
* -1: error
*/
WebRtc_Word32 WebRtcAecm_get_version(WebRtc_Word8 *versionStr,
WebRtc_Word16 len);
#ifdef __cplusplus
}
#endif
#endif /* WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_INTERFACE_ECHO_CONTROL_MOBILE_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_SOURCE_ANALOG_AGC_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_SOURCE_ANALOG_AGC_H_
#include "typedefs.h"
#include "gain_control.h"
#include "digital_agc.h"
//#define AGC_DEBUG
//#define MIC_LEVEL_FEEDBACK
#ifdef AGC_DEBUG
#include <stdio.h>
#endif
/* Analog Automatic Gain Control variables:
* Constant declarations (inner limits inside which no changes are done)
* In the beginning the range is narrower to widen as soon as the measure
* 'Rxx160_LP' is inside it. Currently the starting limits are -22.2+/-1dBm0
* and the final limits -22.2+/-2.5dBm0. These levels makes the speech signal
* go towards -25.4dBm0 (-31.4dBov). Tuned with wbfile-31.4dBov.pcm
* The limits are created by running the AGC with a file having the desired
* signal level and thereafter plotting Rxx160_LP in the dBm0-domain defined
* by out=10*log10(in/260537279.7); Set the target level to the average level
* of our measure Rxx160_LP. Remember that the levels are in blocks of 16 in
* Q(-7). (Example matlab code: round(db2pow(-21.2)*16/2^7) )
*/
#define RXX_BUFFER_LEN 10
static const WebRtc_Word16 kMsecSpeechInner = 520;
static const WebRtc_Word16 kMsecSpeechOuter = 340;
static const WebRtc_Word16 kNormalVadThreshold = 400;
static const WebRtc_Word16 kAlphaShortTerm = 6; // 1 >> 6 = 0.0156
static const WebRtc_Word16 kAlphaLongTerm = 10; // 1 >> 10 = 0.000977
typedef struct
{
// Configurable parameters/variables
WebRtc_UWord32 fs; // Sampling frequency
WebRtc_Word16 compressionGaindB; // Fixed gain level in dB
WebRtc_Word16 targetLevelDbfs; // Target level in -dBfs of envelope (default -3)
WebRtc_Word16 agcMode; // Hard coded mode (adaptAna/adaptDig/fixedDig)
WebRtc_UWord8 limiterEnable; // Enabling limiter (on/off (default off))
WebRtcAgc_config_t defaultConfig;
WebRtcAgc_config_t usedConfig;
// General variables
WebRtc_Word16 initFlag;
WebRtc_Word16 lastError;
// Target level parameters
// Based on the above: analogTargetLevel = round((32767*10^(-22/20))^2*16/2^7)
WebRtc_Word32 analogTargetLevel; // = RXX_BUFFER_LEN * 846805; -22 dBfs
WebRtc_Word32 startUpperLimit; // = RXX_BUFFER_LEN * 1066064; -21 dBfs
WebRtc_Word32 startLowerLimit; // = RXX_BUFFER_LEN * 672641; -23 dBfs
WebRtc_Word32 upperPrimaryLimit; // = RXX_BUFFER_LEN * 1342095; -20 dBfs
WebRtc_Word32 lowerPrimaryLimit; // = RXX_BUFFER_LEN * 534298; -24 dBfs
WebRtc_Word32 upperSecondaryLimit;// = RXX_BUFFER_LEN * 2677832; -17 dBfs
WebRtc_Word32 lowerSecondaryLimit;// = RXX_BUFFER_LEN * 267783; -27 dBfs
WebRtc_UWord16 targetIdx; // Table index for corresponding target level
#ifdef MIC_LEVEL_FEEDBACK
WebRtc_UWord16 targetIdxOffset; // Table index offset for level compensation
#endif
WebRtc_Word16 analogTarget; // Digital reference level in ENV scale
// Analog AGC specific variables
WebRtc_Word32 filterState[8]; // For downsampling wb to nb
WebRtc_Word32 upperLimit; // Upper limit for mic energy
WebRtc_Word32 lowerLimit; // Lower limit for mic energy
WebRtc_Word32 Rxx160w32; // Average energy for one frame
WebRtc_Word32 Rxx16_LPw32; // Low pass filtered subframe energies
WebRtc_Word32 Rxx160_LPw32; // Low pass filtered frame energies
WebRtc_Word32 Rxx16_LPw32Max; // Keeps track of largest energy subframe
WebRtc_Word32 Rxx16_vectorw32[RXX_BUFFER_LEN];// Array with subframe energies
WebRtc_Word32 Rxx16w32_array[2][5];// Energy values of microphone signal
WebRtc_Word32 env[2][10]; // Envelope values of subframes
WebRtc_Word16 Rxx16pos; // Current position in the Rxx16_vectorw32
WebRtc_Word16 envSum; // Filtered scaled envelope in subframes
WebRtc_Word16 vadThreshold; // Threshold for VAD decision
WebRtc_Word16 inActive; // Inactive time in milliseconds
WebRtc_Word16 msTooLow; // Milliseconds of speech at a too low level
WebRtc_Word16 msTooHigh; // Milliseconds of speech at a too high level
WebRtc_Word16 changeToSlowMode; // Change to slow mode after some time at target
WebRtc_Word16 firstCall; // First call to the process-function
WebRtc_Word16 msZero; // Milliseconds of zero input
WebRtc_Word16 msecSpeechOuterChange;// Min ms of speech between volume changes
WebRtc_Word16 msecSpeechInnerChange;// Min ms of speech between volume changes
WebRtc_Word16 activeSpeech; // Milliseconds of active speech
WebRtc_Word16 muteGuardMs; // Counter to prevent mute action
WebRtc_Word16 inQueue; // 10 ms batch indicator
// Microphone level variables
WebRtc_Word32 micRef; // Remember ref. mic level for virtual mic
WebRtc_UWord16 gainTableIdx; // Current position in virtual gain table
WebRtc_Word32 micGainIdx; // Gain index of mic level to increase slowly
WebRtc_Word32 micVol; // Remember volume between frames
WebRtc_Word32 maxLevel; // Max possible vol level, incl dig gain
WebRtc_Word32 maxAnalog; // Maximum possible analog volume level
WebRtc_Word32 maxInit; // Initial value of "max"
WebRtc_Word32 minLevel; // Minimum possible volume level
WebRtc_Word32 minOutput; // Minimum output volume level
WebRtc_Word32 zeroCtrlMax; // Remember max gain => don't amp low input
WebRtc_Word16 scale; // Scale factor for internal volume levels
#ifdef MIC_LEVEL_FEEDBACK
WebRtc_Word16 numBlocksMicLvlSat;
WebRtc_UWord8 micLvlSat;
#endif
// Structs for VAD and digital_agc
AgcVad_t vadMic;
DigitalAgc_t digitalAgc;
#ifdef AGC_DEBUG
FILE* fpt;
FILE* agcLog;
WebRtc_Word32 fcount;
#endif
WebRtc_Word16 lowLevelSignal;
} Agc_t;
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_SOURCE_ANALOG_AGC_H_

View File

@@ -0,0 +1,780 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/* digital_agc.c
*
*/
#include <string.h>
#ifdef AGC_DEBUG
#include <stdio.h>
#endif
#include "digital_agc.h"
#include "gain_control.h"
// To generate the gaintable, copy&paste the following lines to a Matlab window:
// MaxGain = 6; MinGain = 0; CompRatio = 3; Knee = 1;
// zeros = 0:31; lvl = 2.^(1-zeros);
// A = -10*log10(lvl) * (CompRatio - 1) / CompRatio;
// B = MaxGain - MinGain;
// gains = round(2^16*10.^(0.05 * (MinGain + B * ( log(exp(-Knee*A)+exp(-Knee*B)) - log(1+exp(-Knee*B)) ) / log(1/(1+exp(Knee*B))))));
// fprintf(1, '\t%i, %i, %i, %i,\n', gains);
// % Matlab code for plotting the gain and input/output level characteristic (copy/paste the following 3 lines):
// in = 10*log10(lvl); out = 20*log10(gains/65536);
// subplot(121); plot(in, out); axis([-30, 0, -5, 20]); grid on; xlabel('Input (dB)'); ylabel('Gain (dB)');
// subplot(122); plot(in, in+out); axis([-30, 0, -30, 5]); grid on; xlabel('Input (dB)'); ylabel('Output (dB)');
// zoom on;
// Generator table for y=log2(1+e^x) in Q8.
static const WebRtc_UWord16 kGenFuncTable[128] = {
256, 485, 786, 1126, 1484, 1849, 2217, 2586,
2955, 3324, 3693, 4063, 4432, 4801, 5171, 5540,
5909, 6279, 6648, 7017, 7387, 7756, 8125, 8495,
8864, 9233, 9603, 9972, 10341, 10711, 11080, 11449,
11819, 12188, 12557, 12927, 13296, 13665, 14035, 14404,
14773, 15143, 15512, 15881, 16251, 16620, 16989, 17359,
17728, 18097, 18466, 18836, 19205, 19574, 19944, 20313,
20682, 21052, 21421, 21790, 22160, 22529, 22898, 23268,
23637, 24006, 24376, 24745, 25114, 25484, 25853, 26222,
26592, 26961, 27330, 27700, 28069, 28438, 28808, 29177,
29546, 29916, 30285, 30654, 31024, 31393, 31762, 32132,
32501, 32870, 33240, 33609, 33978, 34348, 34717, 35086,
35456, 35825, 36194, 36564, 36933, 37302, 37672, 38041,
38410, 38780, 39149, 39518, 39888, 40257, 40626, 40996,
41365, 41734, 42104, 42473, 42842, 43212, 43581, 43950,
44320, 44689, 45058, 45428, 45797, 46166, 46536, 46905
};
static const WebRtc_Word16 kAvgDecayTime = 250; // frames; < 3000
WebRtc_Word32 WebRtcAgc_CalculateGainTable(WebRtc_Word32 *gainTable, // Q16
WebRtc_Word16 digCompGaindB, // Q0
WebRtc_Word16 targetLevelDbfs,// Q0
WebRtc_UWord8 limiterEnable,
WebRtc_Word16 analogTarget) // Q0
{
// This function generates the compressor gain table used in the fixed digital part.
WebRtc_UWord32 tmpU32no1, tmpU32no2, absInLevel, logApprox;
WebRtc_Word32 inLevel, limiterLvl;
WebRtc_Word32 tmp32, tmp32no1, tmp32no2, numFIX, den, y32;
const WebRtc_UWord16 kLog10 = 54426; // log2(10) in Q14
const WebRtc_UWord16 kLog10_2 = 49321; // 10*log10(2) in Q14
const WebRtc_UWord16 kLogE_1 = 23637; // log2(e) in Q14
WebRtc_UWord16 constMaxGain;
WebRtc_UWord16 tmpU16, intPart, fracPart;
const WebRtc_Word16 kCompRatio = 3;
const WebRtc_Word16 kSoftLimiterLeft = 1;
WebRtc_Word16 limiterOffset = 0; // Limiter offset
WebRtc_Word16 limiterIdx, limiterLvlX;
WebRtc_Word16 constLinApprox, zeroGainLvl, maxGain, diffGain;
WebRtc_Word16 i, tmp16, tmp16no1;
int zeros, zerosScale;
// Constants
// kLogE_1 = 23637; // log2(e) in Q14
// kLog10 = 54426; // log2(10) in Q14
// kLog10_2 = 49321; // 10*log10(2) in Q14
// Calculate maximum digital gain and zero gain level
tmp32no1 = WEBRTC_SPL_MUL_16_16(digCompGaindB - analogTarget, kCompRatio - 1);
tmp16no1 = analogTarget - targetLevelDbfs;
tmp16no1 += WebRtcSpl_DivW32W16ResW16(tmp32no1 + (kCompRatio >> 1), kCompRatio);
maxGain = WEBRTC_SPL_MAX(tmp16no1, (analogTarget - targetLevelDbfs));
tmp32no1 = WEBRTC_SPL_MUL_16_16(maxGain, kCompRatio);
zeroGainLvl = digCompGaindB;
zeroGainLvl -= WebRtcSpl_DivW32W16ResW16(tmp32no1 + ((kCompRatio - 1) >> 1),
kCompRatio - 1);
if ((digCompGaindB <= analogTarget) && (limiterEnable))
{
zeroGainLvl += (analogTarget - digCompGaindB + kSoftLimiterLeft);
limiterOffset = 0;
}
// Calculate the difference between maximum gain and gain at 0dB0v:
// diffGain = maxGain + (compRatio-1)*zeroGainLvl/compRatio
// = (compRatio-1)*digCompGaindB/compRatio
tmp32no1 = WEBRTC_SPL_MUL_16_16(digCompGaindB, kCompRatio - 1);
diffGain = WebRtcSpl_DivW32W16ResW16(tmp32no1 + (kCompRatio >> 1), kCompRatio);
if (diffGain < 0)
{
return -1;
}
// Calculate the limiter level and index:
// limiterLvlX = analogTarget - limiterOffset
// limiterLvl = targetLevelDbfs + limiterOffset/compRatio
limiterLvlX = analogTarget - limiterOffset;
limiterIdx = 2
+ WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)limiterLvlX, 13),
WEBRTC_SPL_RSHIFT_U16(kLog10_2, 1));
tmp16no1 = WebRtcSpl_DivW32W16ResW16(limiterOffset + (kCompRatio >> 1), kCompRatio);
limiterLvl = targetLevelDbfs + tmp16no1;
// Calculate (through table lookup):
// constMaxGain = log2(1+2^(log2(e)*diffGain)); (in Q8)
constMaxGain = kGenFuncTable[diffGain]; // in Q8
// Calculate a parameter used to approximate the fractional part of 2^x with a
// piecewise linear function in Q14:
// constLinApprox = round(3/2*(4*(3-2*sqrt(2))/(log(2)^2)-0.5)*2^14);
constLinApprox = 22817; // in Q14
// Calculate a denominator used in the exponential part to convert from dB to linear scale:
// den = 20*constMaxGain (in Q8)
den = WEBRTC_SPL_MUL_16_U16(20, constMaxGain); // in Q8
for (i = 0; i < 32; i++)
{
// Calculate scaled input level (compressor):
// inLevel = fix((-constLog10_2*(compRatio-1)*(1-i)+fix(compRatio/2))/compRatio)
tmp16 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(kCompRatio - 1, i - 1); // Q0
tmp32 = WEBRTC_SPL_MUL_16_U16(tmp16, kLog10_2) + 1; // Q14
inLevel = WebRtcSpl_DivW32W16(tmp32, kCompRatio); // Q14
// Calculate diffGain-inLevel, to map using the genFuncTable
inLevel = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)diffGain, 14) - inLevel; // Q14
// Make calculations on abs(inLevel) and compensate for the sign afterwards.
absInLevel = (WebRtc_UWord32)WEBRTC_SPL_ABS_W32(inLevel); // Q14
// LUT with interpolation
intPart = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_U32(absInLevel, 14);
fracPart = (WebRtc_UWord16)(absInLevel & 0x00003FFF); // extract the fractional part
tmpU16 = kGenFuncTable[intPart + 1] - kGenFuncTable[intPart]; // Q8
tmpU32no1 = WEBRTC_SPL_UMUL_16_16(tmpU16, fracPart); // Q22
tmpU32no1 += WEBRTC_SPL_LSHIFT_U32((WebRtc_UWord32)kGenFuncTable[intPart], 14); // Q22
logApprox = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 8); // Q14
// Compensate for negative exponent using the relation:
// log2(1 + 2^-x) = log2(1 + 2^x) - x
if (inLevel < 0)
{
zeros = WebRtcSpl_NormU32(absInLevel);
zerosScale = 0;
if (zeros < 15)
{
// Not enough space for multiplication
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(absInLevel, 15 - zeros); // Q(zeros-1)
tmpU32no2 = WEBRTC_SPL_UMUL_32_16(tmpU32no2, kLogE_1); // Q(zeros+13)
if (zeros < 9)
{
tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 9 - zeros); // Q(zeros+13)
zerosScale = 9 - zeros;
} else
{
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, zeros - 9); // Q22
}
} else
{
tmpU32no2 = WEBRTC_SPL_UMUL_32_16(absInLevel, kLogE_1); // Q28
tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, 6); // Q22
}
logApprox = 0;
if (tmpU32no2 < tmpU32no1)
{
logApprox = WEBRTC_SPL_RSHIFT_U32(tmpU32no1 - tmpU32no2, 8 - zerosScale); //Q14
}
}
numFIX = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_U16(maxGain, constMaxGain), 6); // Q14
numFIX -= WEBRTC_SPL_MUL_32_16((WebRtc_Word32)logApprox, diffGain); // Q14
// Calculate ratio
// Shift numFIX as much as possible
zeros = WebRtcSpl_NormW32(numFIX);
numFIX = WEBRTC_SPL_LSHIFT_W32(numFIX, zeros); // Q(14+zeros)
// Shift den so we end up in Qy1
tmp32no1 = WEBRTC_SPL_SHIFT_W32(den, zeros - 8); // Q(zeros)
if (numFIX < 0)
{
numFIX -= WEBRTC_SPL_RSHIFT_W32(tmp32no1, 1);
} else
{
numFIX += WEBRTC_SPL_RSHIFT_W32(tmp32no1, 1);
}
y32 = WEBRTC_SPL_DIV(numFIX, tmp32no1); // in Q14
if (limiterEnable && (i < limiterIdx))
{
tmp32 = WEBRTC_SPL_MUL_16_U16(i - 1, kLog10_2); // Q14
tmp32 -= WEBRTC_SPL_LSHIFT_W32(limiterLvl, 14); // Q14
y32 = WebRtcSpl_DivW32W16(tmp32 + 10, 20);
}
if (y32 > 39000)
{
tmp32 = WEBRTC_SPL_MUL(y32 >> 1, kLog10) + 4096; // in Q27
tmp32 = WEBRTC_SPL_RSHIFT_W32(tmp32, 13); // in Q14
} else
{
tmp32 = WEBRTC_SPL_MUL(y32, kLog10) + 8192; // in Q28
tmp32 = WEBRTC_SPL_RSHIFT_W32(tmp32, 14); // in Q14
}
tmp32 += WEBRTC_SPL_LSHIFT_W32(16, 14); // in Q14 (Make sure final output is in Q16)
// Calculate power
if (tmp32 > 0)
{
intPart = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 14);
fracPart = (WebRtc_UWord16)(tmp32 & 0x00003FFF); // in Q14
if (WEBRTC_SPL_RSHIFT_W32(fracPart, 13))
{
tmp16 = WEBRTC_SPL_LSHIFT_W16(2, 14) - constLinApprox;
tmp32no2 = WEBRTC_SPL_LSHIFT_W32(1, 14) - fracPart;
tmp32no2 = WEBRTC_SPL_MUL_32_16(tmp32no2, tmp16);
tmp32no2 = WEBRTC_SPL_RSHIFT_W32(tmp32no2, 13);
tmp32no2 = WEBRTC_SPL_LSHIFT_W32(1, 14) - tmp32no2;
} else
{
tmp16 = constLinApprox - WEBRTC_SPL_LSHIFT_W16(1, 14);
tmp32no2 = WEBRTC_SPL_MUL_32_16(fracPart, tmp16);
tmp32no2 = WEBRTC_SPL_RSHIFT_W32(tmp32no2, 13);
}
fracPart = (WebRtc_UWord16)tmp32no2;
gainTable[i] = WEBRTC_SPL_LSHIFT_W32(1, intPart)
+ WEBRTC_SPL_SHIFT_W32(fracPart, intPart - 14);
} else
{
gainTable[i] = 0;
}
}
return 0;
}
WebRtc_Word32 WebRtcAgc_InitDigital(DigitalAgc_t *stt, WebRtc_Word16 agcMode)
{
if (agcMode == kAgcModeFixedDigital)
{
// start at minimum to find correct gain faster
stt->capacitorSlow = 0;
} else
{
// start out with 0 dB gain
stt->capacitorSlow = 134217728; // (WebRtc_Word32)(0.125f * 32768.0f * 32768.0f);
}
stt->capacitorFast = 0;
stt->gain = 65536;
stt->gatePrevious = 0;
stt->agcMode = agcMode;
#ifdef AGC_DEBUG
stt->frameCounter = 0;
#endif
// initialize VADs
WebRtcAgc_InitVad(&stt->vadNearend);
WebRtcAgc_InitVad(&stt->vadFarend);
return 0;
}
WebRtc_Word32 WebRtcAgc_AddFarendToDigital(DigitalAgc_t *stt, const WebRtc_Word16 *in_far,
WebRtc_Word16 nrSamples)
{
// Check for valid pointer
if (&stt->vadFarend == NULL)
{
return -1;
}
// VAD for far end
WebRtcAgc_ProcessVad(&stt->vadFarend, in_far, nrSamples);
return 0;
}
WebRtc_Word32 WebRtcAgc_ProcessDigital(DigitalAgc_t *stt, const WebRtc_Word16 *in_near,
const WebRtc_Word16 *in_near_H, WebRtc_Word16 *out,
WebRtc_Word16 *out_H, WebRtc_UWord32 FS,
WebRtc_Word16 lowlevelSignal)
{
// array for gains (one value per ms, incl start & end)
WebRtc_Word32 gains[11];
WebRtc_Word32 out_tmp, tmp32;
WebRtc_Word32 env[10];
WebRtc_Word32 nrg, max_nrg;
WebRtc_Word32 cur_level;
WebRtc_Word32 gain32, delta;
WebRtc_Word16 logratio;
WebRtc_Word16 lower_thr, upper_thr;
WebRtc_Word16 zeros, zeros_fast, frac;
WebRtc_Word16 decay;
WebRtc_Word16 gate, gain_adj;
WebRtc_Word16 k, n;
WebRtc_Word16 L, L2; // samples/subframe
// determine number of samples per ms
if (FS == 8000)
{
L = 8;
L2 = 3;
} else if (FS == 16000)
{
L = 16;
L2 = 4;
} else if (FS == 32000)
{
L = 16;
L2 = 4;
} else
{
return -1;
}
memcpy(out, in_near, 10 * L * sizeof(WebRtc_Word16));
if (FS == 32000)
{
memcpy(out_H, in_near_H, 10 * L * sizeof(WebRtc_Word16));
}
// VAD for near end
logratio = WebRtcAgc_ProcessVad(&stt->vadNearend, out, L * 10);
// Account for far end VAD
if (stt->vadFarend.counter > 10)
{
tmp32 = WEBRTC_SPL_MUL_16_16(3, logratio);
logratio = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32 - stt->vadFarend.logRatio, 2);
}
// Determine decay factor depending on VAD
// upper_thr = 1.0f;
// lower_thr = 0.25f;
upper_thr = 1024; // Q10
lower_thr = 0; // Q10
if (logratio > upper_thr)
{
// decay = -2^17 / DecayTime; -> -65
decay = -65;
} else if (logratio < lower_thr)
{
decay = 0;
} else
{
// decay = (WebRtc_Word16)(((lower_thr - logratio)
// * (2^27/(DecayTime*(upper_thr-lower_thr)))) >> 10);
// SUBSTITUTED: 2^27/(DecayTime*(upper_thr-lower_thr)) -> 65
tmp32 = WEBRTC_SPL_MUL_16_16((lower_thr - logratio), 65);
decay = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 10);
}
// adjust decay factor for long silence (detected as low standard deviation)
// This is only done in the adaptive modes
if (stt->agcMode != kAgcModeFixedDigital)
{
if (stt->vadNearend.stdLongTerm < 4000)
{
decay = 0;
} else if (stt->vadNearend.stdLongTerm < 8096)
{
// decay = (WebRtc_Word16)(((stt->vadNearend.stdLongTerm - 4000) * decay) >> 12);
tmp32 = WEBRTC_SPL_MUL_16_16((stt->vadNearend.stdLongTerm - 4000), decay);
decay = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 12);
}
if (lowlevelSignal != 0)
{
decay = 0;
}
}
#ifdef AGC_DEBUG
stt->frameCounter++;
fprintf(stt->logFile, "%5.2f\t%d\t%d\t%d\t", (float)(stt->frameCounter) / 100, logratio, decay, stt->vadNearend.stdLongTerm);
#endif
// Find max amplitude per sub frame
// iterate over sub frames
for (k = 0; k < 10; k++)
{
// iterate over samples
max_nrg = 0;
for (n = 0; n < L; n++)
{
nrg = WEBRTC_SPL_MUL_16_16(out[k * L + n], out[k * L + n]);
if (nrg > max_nrg)
{
max_nrg = nrg;
}
}
env[k] = max_nrg;
}
// Calculate gain per sub frame
gains[0] = stt->gain;
for (k = 0; k < 10; k++)
{
// Fast envelope follower
// decay time = -131000 / -1000 = 131 (ms)
stt->capacitorFast = AGC_SCALEDIFF32(-1000, stt->capacitorFast, stt->capacitorFast);
if (env[k] > stt->capacitorFast)
{
stt->capacitorFast = env[k];
}
// Slow envelope follower
if (env[k] > stt->capacitorSlow)
{
// increase capacitorSlow
stt->capacitorSlow
= AGC_SCALEDIFF32(500, (env[k] - stt->capacitorSlow), stt->capacitorSlow);
} else
{
// decrease capacitorSlow
stt->capacitorSlow
= AGC_SCALEDIFF32(decay, stt->capacitorSlow, stt->capacitorSlow);
}
// use maximum of both capacitors as current level
if (stt->capacitorFast > stt->capacitorSlow)
{
cur_level = stt->capacitorFast;
} else
{
cur_level = stt->capacitorSlow;
}
// Translate signal level into gain, using a piecewise linear approximation
// find number of leading zeros
zeros = WebRtcSpl_NormU32((WebRtc_UWord32)cur_level);
if (cur_level == 0)
{
zeros = 31;
}
tmp32 = (WEBRTC_SPL_LSHIFT_W32(cur_level, zeros) & 0x7FFFFFFF);
frac = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 19); // Q12
tmp32 = WEBRTC_SPL_MUL((stt->gainTable[zeros-1] - stt->gainTable[zeros]), frac);
gains[k + 1] = stt->gainTable[zeros] + WEBRTC_SPL_RSHIFT_W32(tmp32, 12);
#ifdef AGC_DEBUG
if (k == 0)
{
fprintf(stt->logFile, "%d\t%d\t%d\t%d\t%d\n", env[0], cur_level, stt->capacitorFast, stt->capacitorSlow, zeros);
}
#endif
}
// Gate processing (lower gain during absence of speech)
zeros = WEBRTC_SPL_LSHIFT_W16(zeros, 9) - WEBRTC_SPL_RSHIFT_W16(frac, 3);
// find number of leading zeros
zeros_fast = WebRtcSpl_NormU32((WebRtc_UWord32)stt->capacitorFast);
if (stt->capacitorFast == 0)
{
zeros_fast = 31;
}
tmp32 = (WEBRTC_SPL_LSHIFT_W32(stt->capacitorFast, zeros_fast) & 0x7FFFFFFF);
zeros_fast = WEBRTC_SPL_LSHIFT_W16(zeros_fast, 9);
zeros_fast -= (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 22);
gate = 1000 + zeros_fast - zeros - stt->vadNearend.stdShortTerm;
if (gate < 0)
{
stt->gatePrevious = 0;
} else
{
tmp32 = WEBRTC_SPL_MUL_16_16(stt->gatePrevious, 7);
gate = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)gate + tmp32, 3);
stt->gatePrevious = gate;
}
// gate < 0 -> no gate
// gate > 2500 -> max gate
if (gate > 0)
{
if (gate < 2500)
{
gain_adj = WEBRTC_SPL_RSHIFT_W16(2500 - gate, 5);
} else
{
gain_adj = 0;
}
for (k = 0; k < 10; k++)
{
if ((gains[k + 1] - stt->gainTable[0]) > 8388608)
{
// To prevent wraparound
tmp32 = WEBRTC_SPL_RSHIFT_W32((gains[k+1] - stt->gainTable[0]), 8);
tmp32 = WEBRTC_SPL_MUL(tmp32, (178 + gain_adj));
} else
{
tmp32 = WEBRTC_SPL_MUL((gains[k+1] - stt->gainTable[0]), (178 + gain_adj));
tmp32 = WEBRTC_SPL_RSHIFT_W32(tmp32, 8);
}
gains[k + 1] = stt->gainTable[0] + tmp32;
}
}
// Limit gain to avoid overload distortion
for (k = 0; k < 10; k++)
{
// To prevent wrap around
zeros = 10;
if (gains[k + 1] > 47453132)
{
zeros = 16 - WebRtcSpl_NormW32(gains[k + 1]);
}
gain32 = WEBRTC_SPL_RSHIFT_W32(gains[k+1], zeros) + 1;
gain32 = WEBRTC_SPL_MUL(gain32, gain32);
// check for overflow
while (AGC_MUL32(WEBRTC_SPL_RSHIFT_W32(env[k], 12) + 1, gain32)
> WEBRTC_SPL_SHIFT_W32((WebRtc_Word32)32767, 2 * (1 - zeros + 10)))
{
// multiply by 253/256 ==> -0.1 dB
if (gains[k + 1] > 8388607)
{
// Prevent wrap around
gains[k + 1] = WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(gains[k+1], 8), 253);
} else
{
gains[k + 1] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(gains[k+1], 253), 8);
}
gain32 = WEBRTC_SPL_RSHIFT_W32(gains[k+1], zeros) + 1;
gain32 = WEBRTC_SPL_MUL(gain32, gain32);
}
}
// gain reductions should be done 1 ms earlier than gain increases
for (k = 1; k < 10; k++)
{
if (gains[k] > gains[k + 1])
{
gains[k] = gains[k + 1];
}
}
// save start gain for next frame
stt->gain = gains[10];
// Apply gain
// handle first sub frame separately
delta = WEBRTC_SPL_LSHIFT_W32(gains[1] - gains[0], (4 - L2));
gain32 = WEBRTC_SPL_LSHIFT_W32(gains[0], 4);
// iterate over samples
for (n = 0; n < L; n++)
{
// For lower band
tmp32 = WEBRTC_SPL_MUL((WebRtc_Word32)out[n], WEBRTC_SPL_RSHIFT_W32(gain32 + 127, 7));
out_tmp = WEBRTC_SPL_RSHIFT_W32(tmp32 , 16);
if (out_tmp > 4095)
{
out[n] = (WebRtc_Word16)32767;
} else if (out_tmp < -4096)
{
out[n] = (WebRtc_Word16)-32768;
} else
{
tmp32 = WEBRTC_SPL_MUL((WebRtc_Word32)out[n], WEBRTC_SPL_RSHIFT_W32(gain32, 4));
out[n] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32 , 16);
}
// For higher band
if (FS == 32000)
{
tmp32 = WEBRTC_SPL_MUL((WebRtc_Word32)out_H[n],
WEBRTC_SPL_RSHIFT_W32(gain32 + 127, 7));
out_tmp = WEBRTC_SPL_RSHIFT_W32(tmp32 , 16);
if (out_tmp > 4095)
{
out_H[n] = (WebRtc_Word16)32767;
} else if (out_tmp < -4096)
{
out_H[n] = (WebRtc_Word16)-32768;
} else
{
tmp32 = WEBRTC_SPL_MUL((WebRtc_Word32)out_H[n],
WEBRTC_SPL_RSHIFT_W32(gain32, 4));
out_H[n] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32 , 16);
}
}
//
gain32 += delta;
}
// iterate over subframes
for (k = 1; k < 10; k++)
{
delta = WEBRTC_SPL_LSHIFT_W32(gains[k+1] - gains[k], (4 - L2));
gain32 = WEBRTC_SPL_LSHIFT_W32(gains[k], 4);
// iterate over samples
for (n = 0; n < L; n++)
{
// For lower band
tmp32 = WEBRTC_SPL_MUL((WebRtc_Word32)out[k * L + n],
WEBRTC_SPL_RSHIFT_W32(gain32, 4));
out[k * L + n] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32 , 16);
// For higher band
if (FS == 32000)
{
tmp32 = WEBRTC_SPL_MUL((WebRtc_Word32)out_H[k * L + n],
WEBRTC_SPL_RSHIFT_W32(gain32, 4));
out_H[k * L + n] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32 , 16);
}
gain32 += delta;
}
}
return 0;
}
void WebRtcAgc_InitVad(AgcVad_t *state)
{
WebRtc_Word16 k;
state->HPstate = 0; // state of high pass filter
state->logRatio = 0; // log( P(active) / P(inactive) )
// average input level (Q10)
state->meanLongTerm = WEBRTC_SPL_LSHIFT_W16(15, 10);
// variance of input level (Q8)
state->varianceLongTerm = WEBRTC_SPL_LSHIFT_W32(500, 8);
state->stdLongTerm = 0; // standard deviation of input level in dB
// short-term average input level (Q10)
state->meanShortTerm = WEBRTC_SPL_LSHIFT_W16(15, 10);
// short-term variance of input level (Q8)
state->varianceShortTerm = WEBRTC_SPL_LSHIFT_W32(500, 8);
state->stdShortTerm = 0; // short-term standard deviation of input level in dB
state->counter = 3; // counts updates
for (k = 0; k < 8; k++)
{
// downsampling filter
state->downState[k] = 0;
}
}
WebRtc_Word16 WebRtcAgc_ProcessVad(AgcVad_t *state, // (i) VAD state
const WebRtc_Word16 *in, // (i) Speech signal
WebRtc_Word16 nrSamples) // (i) number of samples
{
WebRtc_Word32 out, nrg, tmp32, tmp32b;
WebRtc_UWord16 tmpU16;
WebRtc_Word16 k, subfr, tmp16;
WebRtc_Word16 buf1[8];
WebRtc_Word16 buf2[4];
WebRtc_Word16 HPstate;
WebRtc_Word16 zeros, dB;
WebRtc_Word16 *buf1_ptr;
// process in 10 sub frames of 1 ms (to save on memory)
nrg = 0;
buf1_ptr = &buf1[0];
HPstate = state->HPstate;
for (subfr = 0; subfr < 10; subfr++)
{
// downsample to 4 kHz
if (nrSamples == 160)
{
for (k = 0; k < 8; k++)
{
tmp32 = (WebRtc_Word32)in[2 * k] + (WebRtc_Word32)in[2 * k + 1];
tmp32 = WEBRTC_SPL_RSHIFT_W32(tmp32, 1);
buf1[k] = (WebRtc_Word16)tmp32;
}
in += 16;
WebRtcSpl_DownsampleBy2(buf1, 8, buf2, state->downState);
} else
{
WebRtcSpl_DownsampleBy2(in, 8, buf2, state->downState);
in += 8;
}
// high pass filter and compute energy
for (k = 0; k < 4; k++)
{
out = buf2[k] + HPstate;
tmp32 = WEBRTC_SPL_MUL(600, out);
HPstate = (WebRtc_Word16)(WEBRTC_SPL_RSHIFT_W32(tmp32, 10) - buf2[k]);
tmp32 = WEBRTC_SPL_MUL(out, out);
nrg += WEBRTC_SPL_RSHIFT_W32(tmp32, 6);
}
}
state->HPstate = HPstate;
// find number of leading zeros
if (!(0xFFFF0000 & nrg))
{
zeros = 16;
} else
{
zeros = 0;
}
if (!(0xFF000000 & (nrg << zeros)))
{
zeros += 8;
}
if (!(0xF0000000 & (nrg << zeros)))
{
zeros += 4;
}
if (!(0xC0000000 & (nrg << zeros)))
{
zeros += 2;
}
if (!(0x80000000 & (nrg << zeros)))
{
zeros += 1;
}
// energy level (range {-32..30}) (Q10)
dB = WEBRTC_SPL_LSHIFT_W16(15 - zeros, 11);
// Update statistics
if (state->counter < kAvgDecayTime)
{
// decay time = AvgDecTime * 10 ms
state->counter++;
}
// update short-term estimate of mean energy level (Q10)
tmp32 = (WEBRTC_SPL_MUL_16_16(state->meanShortTerm, 15) + (WebRtc_Word32)dB);
state->meanShortTerm = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 4);
// update short-term estimate of variance in energy level (Q8)
tmp32 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(dB, dB), 12);
tmp32 += WEBRTC_SPL_MUL(state->varianceShortTerm, 15);
state->varianceShortTerm = WEBRTC_SPL_RSHIFT_W32(tmp32, 4);
// update short-term estimate of standard deviation in energy level (Q10)
tmp32 = WEBRTC_SPL_MUL_16_16(state->meanShortTerm, state->meanShortTerm);
tmp32 = WEBRTC_SPL_LSHIFT_W32(state->varianceShortTerm, 12) - tmp32;
state->stdShortTerm = (WebRtc_Word16)WebRtcSpl_Sqrt(tmp32);
// update long-term estimate of mean energy level (Q10)
tmp32 = WEBRTC_SPL_MUL_16_16(state->meanLongTerm, state->counter) + (WebRtc_Word32)dB;
state->meanLongTerm = WebRtcSpl_DivW32W16ResW16(tmp32,
WEBRTC_SPL_ADD_SAT_W16(state->counter, 1));
// update long-term estimate of variance in energy level (Q8)
tmp32 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(dB, dB), 12);
tmp32 += WEBRTC_SPL_MUL(state->varianceLongTerm, state->counter);
state->varianceLongTerm = WebRtcSpl_DivW32W16(tmp32,
WEBRTC_SPL_ADD_SAT_W16(state->counter, 1));
// update long-term estimate of standard deviation in energy level (Q10)
tmp32 = WEBRTC_SPL_MUL_16_16(state->meanLongTerm, state->meanLongTerm);
tmp32 = WEBRTC_SPL_LSHIFT_W32(state->varianceLongTerm, 12) - tmp32;
state->stdLongTerm = (WebRtc_Word16)WebRtcSpl_Sqrt(tmp32);
// update voice activity measure (Q10)
tmp16 = WEBRTC_SPL_LSHIFT_W16(3, 12);
tmp32 = WEBRTC_SPL_MUL_16_16(tmp16, (dB - state->meanLongTerm));
tmp32 = WebRtcSpl_DivW32W16(tmp32, state->stdLongTerm);
tmpU16 = WEBRTC_SPL_LSHIFT_U16((WebRtc_UWord16)13, 12);
tmp32b = WEBRTC_SPL_MUL_16_U16(state->logRatio, tmpU16);
tmp32 += WEBRTC_SPL_RSHIFT_W32(tmp32b, 10);
state->logRatio = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 6);
// limit
if (state->logRatio > 2048)
{
state->logRatio = 2048;
}
if (state->logRatio < -2048)
{
state->logRatio = -2048;
}
return state->logRatio; // Q10
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_SOURCE_DIGITAL_AGC_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_SOURCE_DIGITAL_AGC_H_
#ifdef AGC_DEBUG
#include <stdio.h>
#endif
#include "typedefs.h"
#include "signal_processing_library.h"
// the 32 most significant bits of A(19) * B(26) >> 13
#define AGC_MUL32(A, B) (((B)>>13)*(A) + ( ((0x00001FFF & (B))*(A)) >> 13 ))
// C + the 32 most significant bits of A * B
#define AGC_SCALEDIFF32(A, B, C) ((C) + ((B)>>16)*(A) + ( ((0x0000FFFF & (B))*(A)) >> 16 ))
typedef struct
{
WebRtc_Word32 downState[8];
WebRtc_Word16 HPstate;
WebRtc_Word16 counter;
WebRtc_Word16 logRatio; // log( P(active) / P(inactive) ) (Q10)
WebRtc_Word16 meanLongTerm; // Q10
WebRtc_Word32 varianceLongTerm; // Q8
WebRtc_Word16 stdLongTerm; // Q10
WebRtc_Word16 meanShortTerm; // Q10
WebRtc_Word32 varianceShortTerm; // Q8
WebRtc_Word16 stdShortTerm; // Q10
} AgcVad_t; // total = 54 bytes
typedef struct
{
WebRtc_Word32 capacitorSlow;
WebRtc_Word32 capacitorFast;
WebRtc_Word32 gain;
WebRtc_Word32 gainTable[32];
WebRtc_Word16 gatePrevious;
WebRtc_Word16 agcMode;
AgcVad_t vadNearend;
AgcVad_t vadFarend;
#ifdef AGC_DEBUG
FILE* logFile;
int frameCounter;
#endif
} DigitalAgc_t;
WebRtc_Word32 WebRtcAgc_InitDigital(DigitalAgc_t *digitalAgcInst, WebRtc_Word16 agcMode);
WebRtc_Word32 WebRtcAgc_ProcessDigital(DigitalAgc_t *digitalAgcInst, const WebRtc_Word16 *inNear,
const WebRtc_Word16 *inNear_H, WebRtc_Word16 *out,
WebRtc_Word16 *out_H, WebRtc_UWord32 FS,
WebRtc_Word16 lowLevelSignal);
WebRtc_Word32 WebRtcAgc_AddFarendToDigital(DigitalAgc_t *digitalAgcInst, const WebRtc_Word16 *inFar,
WebRtc_Word16 nrSamples);
void WebRtcAgc_InitVad(AgcVad_t *vadInst);
WebRtc_Word16 WebRtcAgc_ProcessVad(AgcVad_t *vadInst, // (i) VAD state
const WebRtc_Word16 *in, // (i) Speech signal
WebRtc_Word16 nrSamples); // (i) number of samples
WebRtc_Word32 WebRtcAgc_CalculateGainTable(WebRtc_Word32 *gainTable, // Q16
WebRtc_Word16 compressionGaindB, // Q0 (in dB)
WebRtc_Word16 targetLevelDbfs,// Q0 (in dB)
WebRtc_UWord8 limiterEnable, WebRtc_Word16 analogTarget);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_SOURCE_ANALOG_AGC_H_

View File

@@ -0,0 +1,273 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_INTERFACE_GAIN_CONTROL_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_INTERFACE_GAIN_CONTROL_H_
#include "typedefs.h"
// Errors
#define AGC_UNSPECIFIED_ERROR 18000
#define AGC_UNSUPPORTED_FUNCTION_ERROR 18001
#define AGC_UNINITIALIZED_ERROR 18002
#define AGC_NULL_POINTER_ERROR 18003
#define AGC_BAD_PARAMETER_ERROR 18004
// Warnings
#define AGC_BAD_PARAMETER_WARNING 18050
enum
{
kAgcModeUnchanged,
kAgcModeAdaptiveAnalog,
kAgcModeAdaptiveDigital,
kAgcModeFixedDigital
};
enum
{
kAgcFalse = 0,
kAgcTrue
};
typedef struct
{
WebRtc_Word16 targetLevelDbfs; // default 3 (-3 dBOv)
WebRtc_Word16 compressionGaindB; // default 9 dB
WebRtc_UWord8 limiterEnable; // default kAgcTrue (on)
} WebRtcAgc_config_t;
#if defined(__cplusplus)
extern "C"
{
#endif
/*
* This function processes a 10/20ms frame of far-end speech to determine
* if there is active speech. Far-end speech length can be either 10ms or
* 20ms. The length of the input speech vector must be given in samples
* (80/160 when FS=8000, and 160/320 when FS=16000 or FS=32000).
*
* Input:
* - agcInst : AGC instance.
* - inFar : Far-end input speech vector (10 or 20ms)
* - samples : Number of samples in input vector
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_AddFarend(void* agcInst,
const WebRtc_Word16* inFar,
WebRtc_Word16 samples);
/*
* This function processes a 10/20ms frame of microphone speech to determine
* if there is active speech. Microphone speech length can be either 10ms or
* 20ms. The length of the input speech vector must be given in samples
* (80/160 when FS=8000, and 160/320 when FS=16000 or FS=32000). For very low
* input levels, the input signal is increased in level by multiplying and
* overwriting the samples in inMic[].
*
* This function should be called before any further processing of the
* near-end microphone signal.
*
* Input:
* - agcInst : AGC instance.
* - inMic : Microphone input speech vector (10 or 20 ms) for
* L band
* - inMic_H : Microphone input speech vector (10 or 20 ms) for
* H band
* - samples : Number of samples in input vector
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_AddMic(void* agcInst,
WebRtc_Word16* inMic,
WebRtc_Word16* inMic_H,
WebRtc_Word16 samples);
/*
* This function replaces the analog microphone with a virtual one.
* It is a digital gain applied to the input signal and is used in the
* agcAdaptiveDigital mode where no microphone level is adjustable.
* Microphone speech length can be either 10ms or 20ms. The length of the
* input speech vector must be given in samples (80/160 when FS=8000, and
* 160/320 when FS=16000 or FS=32000).
*
* Input:
* - agcInst : AGC instance.
* - inMic : Microphone input speech vector for (10 or 20 ms)
* L band
* - inMic_H : Microphone input speech vector for (10 or 20 ms)
* H band
* - samples : Number of samples in input vector
* - micLevelIn : Input level of microphone (static)
*
* Output:
* - inMic : Microphone output after processing (L band)
* - inMic_H : Microphone output after processing (H band)
* - micLevelOut : Adjusted microphone level after processing
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_VirtualMic(void* agcInst,
WebRtc_Word16* inMic,
WebRtc_Word16* inMic_H,
WebRtc_Word16 samples,
WebRtc_Word32 micLevelIn,
WebRtc_Word32* micLevelOut);
/*
* This function processes a 10/20ms frame and adjusts (normalizes) the gain
* both analog and digitally. The gain adjustments are done only during
* active periods of speech. The input speech length can be either 10ms or
* 20ms and the output is of the same length. The length of the speech
* vectors must be given in samples (80/160 when FS=8000, and 160/320 when
* FS=16000 or FS=32000). The echo parameter can be used to ensure the AGC will
* not adjust upward in the presence of echo.
*
* This function should be called after processing the near-end microphone
* signal, in any case after any echo cancellation.
*
* Input:
* - agcInst : AGC instance
* - inNear : Near-end input speech vector (10 or 20 ms) for
* L band
* - inNear_H : Near-end input speech vector (10 or 20 ms) for
* H band
* - samples : Number of samples in input/output vector
* - inMicLevel : Current microphone volume level
* - echo : Set to 0 if the signal passed to add_mic is
* almost certainly free of echo; otherwise set
* to 1. If you have no information regarding echo
* set to 0.
*
* Output:
* - outMicLevel : Adjusted microphone volume level
* - out : Gain-adjusted near-end speech vector (L band)
* : May be the same vector as the input.
* - out_H : Gain-adjusted near-end speech vector (H band)
* - saturationWarning : A returned value of 1 indicates a saturation event
* has occurred and the volume cannot be further
* reduced. Otherwise will be set to 0.
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_Process(void* agcInst,
const WebRtc_Word16* inNear,
const WebRtc_Word16* inNear_H,
WebRtc_Word16 samples,
WebRtc_Word16* out,
WebRtc_Word16* out_H,
WebRtc_Word32 inMicLevel,
WebRtc_Word32* outMicLevel,
WebRtc_Word16 echo,
WebRtc_UWord8* saturationWarning);
/*
* This function sets the config parameters (targetLevelDbfs,
* compressionGaindB and limiterEnable).
*
* Input:
* - agcInst : AGC instance
* - config : config struct
*
* Output:
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_set_config(void* agcInst, WebRtcAgc_config_t config);
/*
* This function returns the config parameters (targetLevelDbfs,
* compressionGaindB and limiterEnable).
*
* Input:
* - agcInst : AGC instance
*
* Output:
* - config : config struct
*
* Return value:
* : 0 - Normal operation.
* : -1 - Error
*/
int WebRtcAgc_get_config(void* agcInst, WebRtcAgc_config_t* config);
/*
* This function creates an AGC instance, which will contain the state
* information for one (duplex) channel.
*
* Return value : AGC instance if successful
* : 0 (i.e., a NULL pointer) if unsuccessful
*/
int WebRtcAgc_Create(void **agcInst);
/*
* This function frees the AGC instance created at the beginning.
*
* Input:
* - agcInst : AGC instance.
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcAgc_Free(void *agcInst);
/*
* This function initializes an AGC instance.
*
* Input:
* - agcInst : AGC instance.
* - minLevel : Minimum possible mic level
* - maxLevel : Maximum possible mic level
* - agcMode : 0 - Unchanged
* : 1 - Adaptive Analog Automatic Gain Control -3dBOv
* : 2 - Adaptive Digital Automatic Gain Control -3dBOv
* : 3 - Fixed Digital Gain 0dB
* - fs : Sampling frequency
*
* Return value : 0 - Ok
* -1 - Error
*/
int WebRtcAgc_Init(void *agcInst,
WebRtc_Word32 minLevel,
WebRtc_Word32 maxLevel,
WebRtc_Word16 agcMode,
WebRtc_UWord32 fs);
/*
* This function returns a text string containing the version.
*
* Input:
* - length : Length of the char array pointed to by version
* Output:
* - version : Pointer to a char array of to which the version
* : string will be copied.
*
* Return value : 0 - OK
* -1 - Error
*/
int WebRtcAgc_Version(WebRtc_Word8 *versionStr, WebRtc_Word16 length);
#if defined(__cplusplus)
}
#endif
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_MAIN_INTERFACE_GAIN_CONTROL_H_

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc_cng.h"
#include "signal_processing_library.h"
#include "typedefs.h"
#include "cng_helpfuns.h"
#ifdef __cplusplus
extern "C" {
#endif
void WebRtcCng_K2a16(
WebRtc_Word16 *k, /* Q15. */
int useOrder,
WebRtc_Word16 *a /* Q12. */
)
{
WebRtc_Word16 any[WEBRTC_SPL_MAX_LPC_ORDER+1];
WebRtc_Word16 *aptr, *aptr2, *anyptr;
G_CONST WebRtc_Word16 *kptr;
int m, i;
kptr = k;
*a = 4096; /* i.e., (Word16_MAX >> 3)+1 */
*any = *a;
a[1] = (*k+4) >> 3;
for( m=1; m<useOrder; m++ )
{
kptr++;
aptr = a;
aptr++;
aptr2 = &a[m];
anyptr = any;
anyptr++;
any[m+1] = (*kptr+4) >> 3;
for( i=0; i<m; i++ ) {
*anyptr++ = (*aptr++) + (WebRtc_Word16)( (( (WebRtc_Word32)(*aptr2--) * (WebRtc_Word32)*kptr )+16384) >> 15);
}
aptr = a;
anyptr = any;
for( i=0; i<(m+2); i++ ){
*aptr++ = *anyptr++;
}
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_SOURCE_CNG_HELPFUNS_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_SOURCE_CNG_HELPFUNS_H_
extern WebRtc_Word32 lpc_lagwinTbl_fixw32[WEBRTC_CNG_MAX_LPC_ORDER + 1];
#ifdef __cplusplus
extern "C" {
#endif
void WebRtcCng_K2a16(WebRtc_Word16 *k, int useOrder, WebRtc_Word16 *a);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_SOURCE_CNG_HELPFUNS_H_

View File

@@ -0,0 +1,735 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include <stdlib.h>
#include "webrtc_cng.h"
#include "signal_processing_library.h"
#include "cng_helpfuns.h"
#include "stdio.h"
typedef struct WebRtcCngDecInst_t_ {
WebRtc_UWord32 dec_seed;
WebRtc_Word32 dec_target_energy;
WebRtc_Word32 dec_used_energy;
WebRtc_Word16 dec_target_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 dec_used_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 dec_filtstate[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 dec_filtstateLow[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 dec_Efiltstate[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 dec_EfiltstateLow[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 dec_order;
WebRtc_Word16 dec_target_scale_factor; /*Q29*/
WebRtc_Word16 dec_used_scale_factor; /*Q29*/
WebRtc_Word16 target_scale_factor; /* Q13 */
WebRtc_Word16 errorcode;
WebRtc_Word16 initflag;
} WebRtcCngDecInst_t;
typedef struct WebRtcCngEncInst_t_ {
WebRtc_Word16 enc_nrOfCoefs;
WebRtc_Word16 enc_sampfreq;
WebRtc_Word16 enc_interval;
WebRtc_Word16 enc_msSinceSID;
WebRtc_Word32 enc_Energy;
WebRtc_Word16 enc_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word32 enc_corrVector[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 enc_filtstate[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 enc_filtstateLow[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_UWord32 enc_seed;
WebRtc_Word16 errorcode;
WebRtc_Word16 initflag;
} WebRtcCngEncInst_t;
const WebRtc_Word32 WebRtcCng_kDbov[94]={
1081109975, 858756178, 682134279, 541838517, 430397633, 341876992,
271562548, 215709799, 171344384, 136103682, 108110997, 85875618,
68213428, 54183852, 43039763, 34187699, 27156255, 21570980,
17134438, 13610368, 10811100, 8587562, 6821343, 5418385,
4303976, 3418770, 2715625, 2157098, 1713444, 1361037,
1081110, 858756, 682134, 541839, 430398, 341877,
271563, 215710, 171344, 136104, 108111, 85876,
68213, 54184, 43040, 34188, 27156, 21571,
17134, 13610, 10811, 8588, 6821, 5418,
4304, 3419, 2716, 2157, 1713, 1361,
1081, 859, 682, 542, 430, 342,
272, 216, 171, 136, 108, 86,
68, 54, 43, 34, 27, 22,
17, 14, 11, 9, 7, 5,
4, 3, 3, 2, 2, 1,
1, 1, 1, 1
};
const WebRtc_Word16 WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = {
32702, 32636, 32570, 32505, 32439, 32374,
32309, 32244, 32179, 32114, 32049, 31985
};
/****************************************************************************
* WebRtcCng_Version(...)
*
* These functions returns the version name (string must be at least
* 500 characters long)
*
* Output:
* - version : Pointer to character string
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_Version(WebRtc_Word8 *version)
{
strcpy((char*)version,(const char*)"1.2.0\n");
return(0);
}
/****************************************************************************
* WebRtcCng_AssignSizeEnc/Dec(...)
*
* These functions get the size needed for storing the instance for encoder
* and decoder, respectively
*
* Input/Output:
* - sizeinbytes : Pointer to integer where the size is returned
*
* Return value : 0
*/
WebRtc_Word16 WebRtcCng_AssignSizeEnc(int *sizeinbytes)
{
*sizeinbytes=sizeof(WebRtcCngEncInst_t)*2/sizeof(WebRtc_Word16);
return(0);
}
WebRtc_Word16 WebRtcCng_AssignSizeDec(int *sizeinbytes)
{
*sizeinbytes=sizeof(WebRtcCngDecInst_t)*2/sizeof(WebRtc_Word16);
return(0);
}
/****************************************************************************
* WebRtcCng_AssignEnc/Dec(...)
*
* These functions Assignes memory for the instances.
*
* Input:
* - CNG_inst_Addr : Adress to where to assign memory
* Output:
* - inst : Pointer to the instance that should be created
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_AssignEnc(CNG_enc_inst **inst, void *CNG_inst_Addr)
{
if (CNG_inst_Addr!=NULL) {
*inst = (CNG_enc_inst*)CNG_inst_Addr;
(*(WebRtcCngEncInst_t**) inst)->errorcode = 0;
(*(WebRtcCngEncInst_t**) inst)->initflag = 0;
return(0);
} else {
/* The memory could not be allocated */
return(-1);
}
}
WebRtc_Word16 WebRtcCng_AssignDec(CNG_dec_inst **inst, void *CNG_inst_Addr)
{
if (CNG_inst_Addr!=NULL) {
*inst = (CNG_dec_inst*)CNG_inst_Addr;
(*(WebRtcCngDecInst_t**) inst)->errorcode = 0;
(*(WebRtcCngDecInst_t**) inst)->initflag = 0;
return(0);
} else {
/* The memory could not be allocated */
return(-1);
}
}
/****************************************************************************
* WebRtcCng_CreateEnc/Dec(...)
*
* These functions create an instance to the specified structure
*
* Input:
* - XXX_inst : Pointer to created instance that should be created
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_CreateEnc(CNG_enc_inst **cng_inst)
{
*cng_inst=(CNG_enc_inst*)malloc(sizeof(WebRtcCngEncInst_t));
if(cng_inst!=NULL) {
(*(WebRtcCngEncInst_t**) cng_inst)->errorcode = 0;
(*(WebRtcCngEncInst_t**) cng_inst)->initflag = 0;
return(0);
}
else {
/* The memory could not be allocated */
return(-1);
}
}
WebRtc_Word16 WebRtcCng_CreateDec(CNG_dec_inst **cng_inst)
{
*cng_inst=(CNG_dec_inst*)malloc(sizeof(WebRtcCngDecInst_t));
if(cng_inst!=NULL) {
(*(WebRtcCngDecInst_t**) cng_inst)->errorcode = 0;
(*(WebRtcCngDecInst_t**) cng_inst)->initflag = 0;
return(0);
}
else {
/* The memory could not be allocated */
return(-1);
}
}
/****************************************************************************
* WebRtcCng_InitEnc/Dec(...)
*
* This function initializes a instance
*
* Input:
* - cng_inst : Instance that should be initialized
*
* - fs : 8000 for narrowband and 16000 for wideband
* - interval : generate SID data every interval ms
* - quality : TBD
*
* Output:
* - cng_inst : Initialized instance
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_InitEnc(CNG_enc_inst *cng_inst,
WebRtc_Word16 fs,
WebRtc_Word16 interval,
WebRtc_Word16 quality)
{
int i;
WebRtcCngEncInst_t* inst=(WebRtcCngEncInst_t*)cng_inst;
memset(inst, 0, sizeof(WebRtcCngEncInst_t));
/* Check LPC order */
if (quality>WEBRTC_CNG_MAX_LPC_ORDER) {
inst->errorcode = CNG_DISALLOWED_LPC_ORDER;
return (-1);
}
if (fs<=0) {
inst->errorcode = CNG_DISALLOWED_SAMPLING_FREQUENCY;
return (-1);
}
inst->enc_sampfreq=fs;
inst->enc_interval=interval;
inst->enc_nrOfCoefs=quality;
inst->enc_msSinceSID=0;
inst->enc_seed=7777; /*For debugging only*/
inst->enc_Energy=0;
for(i=0;i<(WEBRTC_CNG_MAX_LPC_ORDER+1);i++){
inst->enc_reflCoefs[i]=0;
inst->enc_corrVector[i]=0;
}
inst->initflag=1;
return(0);
}
WebRtc_Word16 WebRtcCng_InitDec(CNG_dec_inst *cng_inst)
{
int i;
WebRtcCngDecInst_t* inst=(WebRtcCngDecInst_t*)cng_inst;
memset(inst, 0, sizeof(WebRtcCngDecInst_t));
inst->dec_seed=7777; /*For debugging only*/
inst->dec_order=5;
inst->dec_target_scale_factor=0;
inst->dec_used_scale_factor=0;
for(i=0;i<(WEBRTC_CNG_MAX_LPC_ORDER+1);i++){
inst->dec_filtstate[i]=0;
inst->dec_target_reflCoefs[i]=0;
inst->dec_used_reflCoefs[i]=0;
}
inst->dec_target_reflCoefs[0]=0;
inst->dec_used_reflCoefs[0]=0;
inst ->dec_used_energy=0;
inst->initflag=1;
return(0);
}
/****************************************************************************
* WebRtcCng_FreeEnc/Dec(...)
*
* These functions frees the dynamic memory of a specified instance
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_FreeEnc(CNG_enc_inst *cng_inst)
{
free(cng_inst);
return(0);
}
WebRtc_Word16 WebRtcCng_FreeDec(CNG_dec_inst *cng_inst)
{
free(cng_inst);
return(0);
}
/****************************************************************************
* WebRtcCng_Encode(...)
*
* These functions analyzes background noise
*
* Input:
* - cng_inst : Pointer to created instance
* - speech : Signal (noise) to be analyzed
* - nrOfSamples : Size of speech vector
* - bytesOut : Nr of bytes to transmit, might be 0
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_Encode(CNG_enc_inst *cng_inst,
WebRtc_Word16 *speech,
WebRtc_Word16 nrOfSamples,
WebRtc_UWord8* SIDdata,
WebRtc_Word16* bytesOut,
WebRtc_Word16 forceSID)
{
WebRtcCngEncInst_t* inst=(WebRtcCngEncInst_t*)cng_inst;
WebRtc_Word16 arCoefs[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word32 corrVector[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 refCs[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 hanningW[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
WebRtc_Word16 ReflBeta=19661; /*0.6 in q15*/
WebRtc_Word16 ReflBetaComp=13107; /*0.4 in q15*/
WebRtc_Word32 outEnergy;
int outShifts;
int i, stab;
int acorrScale;
int index;
WebRtc_Word32 diff;
WebRtc_Word16 ind,factor;
WebRtc_Word32 *bptr, blo, bhi;
WebRtc_Word16 negate;
const WebRtc_Word16 *aptr;
WebRtc_Word16 speechBuf[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
/* check if encoder initiated */
if (inst->initflag != 1) {
inst->errorcode = CNG_ENCODER_NOT_INITIATED;
return (-1);
}
/* check framesize */
if (nrOfSamples>WEBRTC_CNG_MAX_OUTSIZE_ORDER) {
inst->errorcode = CNG_DISALLOWED_FRAME_SIZE;
return (-1);
}
for(i=0;i<nrOfSamples;i++){
speechBuf[i]=speech[i];
}
factor=nrOfSamples;
/* Calculate energy and a coefficients */
outEnergy =WebRtcSpl_Energy(speechBuf, nrOfSamples, &outShifts);
while(outShifts>0){
if(outShifts>5){ /*We can only do 5 shifts without destroying accuracy in division factor*/
outEnergy<<=(outShifts-5);
outShifts=5;
}
else{
factor/=2;
outShifts--;
}
}
outEnergy=WebRtcSpl_DivW32W16(outEnergy,factor);
if (outEnergy > 1){
/* Create Hanning Window */
WebRtcSpl_GetHanningWindow(hanningW, nrOfSamples/2);
for( i=0;i<(nrOfSamples/2);i++ )
hanningW[nrOfSamples-i-1]=hanningW[i];
WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, nrOfSamples, 14);
WebRtcSpl_AutoCorrelation( speechBuf, nrOfSamples, inst->enc_nrOfCoefs, corrVector, &acorrScale );
if( *corrVector==0 )
*corrVector = WEBRTC_SPL_WORD16_MAX;
/* Adds the bandwidth expansion */
aptr = WebRtcCng_kCorrWindow;
bptr = corrVector;
// (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700)
for( ind=0; ind<inst->enc_nrOfCoefs; ind++ )
{
// The below code multiplies the 16 b corrWindow values (Q15) with
// the 32 b corrvector (Q0) and shifts the result down 15 steps.
negate = *bptr<0;
if( negate )
*bptr = -*bptr;
blo = (WebRtc_Word32)*aptr * (*bptr & 0xffff);
bhi = ((blo >> 16) & 0xffff) + ((WebRtc_Word32)(*aptr++) * ((*bptr >> 16) & 0xffff));
blo = (blo & 0xffff) | ((bhi & 0xffff) << 16);
*bptr = (( (bhi>>16) & 0x7fff) << 17) | ((WebRtc_UWord32)blo >> 15);
if( negate )
*bptr = -*bptr;
bptr++;
}
// end of bandwidth expansion
stab=WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs, inst->enc_nrOfCoefs);
if(!stab){
// disregard from this frame
*bytesOut=0;
return(0);
}
}
else {
for(i=0;i<inst->enc_nrOfCoefs; i++)
refCs[i]=0;
}
if(forceSID){
/*Read instantaneous values instead of averaged*/
for(i=0;i<inst->enc_nrOfCoefs;i++)
inst->enc_reflCoefs[i]=refCs[i];
inst->enc_Energy=outEnergy;
}
else{
/*Average history with new values*/
for(i=0;i<(inst->enc_nrOfCoefs);i++){
inst->enc_reflCoefs[i]=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->enc_reflCoefs[i],ReflBeta,15);
inst->enc_reflCoefs[i]+=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(refCs[i],ReflBetaComp,15);
}
inst->enc_Energy=(outEnergy>>2)+(inst->enc_Energy>>1)+(inst->enc_Energy>>2);
}
if(inst->enc_Energy<1){
inst->enc_Energy=1;
}
if((inst->enc_msSinceSID>(inst->enc_interval-1))||forceSID){
/* Search for best dbov value */
/* Clumsy linear search that can be optimized since database is sorted */
index=0;
diff=WEBRTC_SPL_ABS_W32(inst->enc_Energy-WebRtcCng_kDbov[index]);
for(i=1;i<93;i++){
/* Always round downwards */
if((inst->enc_Energy-WebRtcCng_kDbov[i])>0){
index=i;
break;
}
}
if((i==93)&&(index==0))
index=94;
SIDdata[0]=index;
/* Quantize coefs with tweak for WebRtc implementation of RFC3389 */
if(inst->enc_nrOfCoefs==WEBRTC_CNG_MAX_LPC_ORDER){
for(i=0;i<inst->enc_nrOfCoefs;i++){
SIDdata[i+1]=((inst->enc_reflCoefs[i]+128)>>8); /* Q15 to Q7*/ /* +127 */
}
}else{
for(i=0;i<inst->enc_nrOfCoefs;i++){
SIDdata[i+1]=(127+((inst->enc_reflCoefs[i]+128)>>8)); /* Q15 to Q7*/ /* +127 */
}
}
inst->enc_msSinceSID=0;
*bytesOut=inst->enc_nrOfCoefs+1;
inst->enc_msSinceSID+=(1000*nrOfSamples)/inst->enc_sampfreq;
return(inst->enc_nrOfCoefs+1);
}else{
inst->enc_msSinceSID+=(1000*nrOfSamples)/inst->enc_sampfreq;
*bytesOut=0;
return(0);
}
}
/****************************************************************************
* WebRtcCng_UpdateSid(...)
*
* These functions updates the CN state, when a new SID packet arrives
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
* - SID : SID packet, all headers removed
* - length : Length in bytes of SID packet
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_UpdateSid(CNG_dec_inst *cng_inst,
WebRtc_UWord8 *SID,
WebRtc_Word16 length)
{
WebRtcCngDecInst_t* inst=(WebRtcCngDecInst_t*)cng_inst;
WebRtc_Word16 refCs[WEBRTC_CNG_MAX_LPC_ORDER];
WebRtc_Word32 targetEnergy;
int i;
if (inst->initflag != 1) {
inst->errorcode = CNG_DECODER_NOT_INITIATED;
return (-1);
}
/*Throw away reflection coefficients of higher order than we can handle*/
if(length> (WEBRTC_CNG_MAX_LPC_ORDER+1))
length=WEBRTC_CNG_MAX_LPC_ORDER+1;
inst->dec_order=length-1;
if(SID[0]>93)
SID[0]=93;
targetEnergy=WebRtcCng_kDbov[SID[0]];
/* Take down target energy to 75% */
targetEnergy=targetEnergy>>1;
targetEnergy+=targetEnergy>>2;
inst->dec_target_energy=targetEnergy;
/* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389 */
if(inst->dec_order==WEBRTC_CNG_MAX_LPC_ORDER){
for(i=0;i<(inst->dec_order);i++){
refCs[i]=SID[i+1]<<8; /* Q7 to Q15*/
inst->dec_target_reflCoefs[i]=refCs[i];
}
}else{
for(i=0;i<(inst->dec_order);i++){
refCs[i]=(SID[i+1]-127)<<8; /* Q7 to Q15*/
inst->dec_target_reflCoefs[i]=refCs[i];
}
}
for(i=(inst->dec_order);i<WEBRTC_CNG_MAX_LPC_ORDER;i++){
refCs[i]=0;
inst->dec_target_reflCoefs[i]=refCs[i];
}
return(0);
}
/****************************************************************************
* WebRtcCng_Generate(...)
*
* These functions generates CN data when needed
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
* - outData : pointer to area to write CN data
* - nrOfSamples : How much data to generate
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_Generate(CNG_dec_inst *cng_inst,
WebRtc_Word16 *outData,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 new_period)
{
WebRtcCngDecInst_t* inst=(WebRtcCngDecInst_t*)cng_inst;
int i;
WebRtc_Word16 excitation[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
WebRtc_Word16 low[WEBRTC_CNG_MAX_OUTSIZE_ORDER];
WebRtc_Word16 lpPoly[WEBRTC_CNG_MAX_LPC_ORDER+1];
WebRtc_Word16 ReflBetaStd=26214; /*0.8 in q15*/
WebRtc_Word16 ReflBetaCompStd=6553; /*0.2in q15*/
WebRtc_Word16 ReflBetaNewP=19661; /*0.6 in q15*/
WebRtc_Word16 ReflBetaCompNewP=13107; /*0.4 in q15*/
WebRtc_Word16 Beta,BetaC, tmp1, tmp2, tmp3;
WebRtc_Word32 targetEnergy;
WebRtc_Word16 En;
WebRtc_Word16 temp16;
if (nrOfSamples>WEBRTC_CNG_MAX_OUTSIZE_ORDER) {
inst->errorcode = CNG_DISALLOWED_FRAME_SIZE;
return (-1);
}
if (new_period) {
inst->dec_used_scale_factor=inst->dec_target_scale_factor;
Beta=ReflBetaNewP;
BetaC=ReflBetaCompNewP;
} else {
Beta=ReflBetaStd;
BetaC=ReflBetaCompStd;
}
/*Here we use a 0.5 weighting, should possibly be modified to 0.6*/
tmp1=inst->dec_used_scale_factor<<2; /* Q13->Q15 */
tmp2=inst->dec_target_scale_factor<<2; /* Q13->Q15 */
tmp3=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp1,Beta,15);
tmp3+=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp2,BetaC,15);
inst->dec_used_scale_factor=tmp3>>2; /* Q15->Q13 */
inst->dec_used_energy=inst->dec_used_energy>>1;
inst->dec_used_energy+=inst->dec_target_energy>>1;
/* Do the same for the reflection coeffs */
for (i=0;i<WEBRTC_CNG_MAX_LPC_ORDER;i++) {
inst->dec_used_reflCoefs[i]=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->dec_used_reflCoefs[i],Beta,15);
inst->dec_used_reflCoefs[i]+=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->dec_target_reflCoefs[i],BetaC,15);
}
/* Compute the polynomial coefficients */
WebRtcCng_K2a16(inst->dec_used_reflCoefs, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly);
/***/
targetEnergy=inst->dec_used_energy;
// Calculate scaling factor based on filter energy
En=8192; //1.0 in Q13
for (i=0; i<(WEBRTC_CNG_MAX_LPC_ORDER); i++) {
// Floating point value for reference
// E*=1.0-((float)inst->dec_used_reflCoefs[i]/32768.0)*((float)inst->dec_used_reflCoefs[i]/32768.0);
// Same in fixed point
temp16=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(inst->dec_used_reflCoefs[i],inst->dec_used_reflCoefs[i],15); // K(i).^2 in Q15
temp16=0x7fff - temp16; // 1 - K(i).^2 in Q15
En=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(En,temp16,15);
}
//float scaling= sqrt(E*inst->dec_target_energy/((1<<24)));
//Calculate sqrt(En*target_energy/exctiation energy)
targetEnergy=WebRtcSpl_Sqrt(inst->dec_used_energy);
En=(WebRtc_Word16)WebRtcSpl_Sqrt(En)<<6; //We are missing a factor sqrt(2) here
En=(En*3)>>1; //1.5 estimates sqrt(2)
inst->dec_used_scale_factor=(WebRtc_Word16)((En*targetEnergy)>>12);
/***/
/*Generate excitation*/
/*Excitation energy per sample is 2.^24 - Q13 N(0,1) */
for(i=0;i<nrOfSamples;i++){
excitation[i]=WebRtcSpl_RandN(&inst->dec_seed)>>1;
}
/*Scale to correct energy*/
WebRtcSpl_ScaleVector(excitation, excitation, inst->dec_used_scale_factor, nrOfSamples, 13);
WebRtcSpl_FilterAR(
lpPoly, /* Coefficients in Q12 */
WEBRTC_CNG_MAX_LPC_ORDER+1,
excitation, /* Speech samples */
nrOfSamples,
inst->dec_filtstate, /* State preservation */
WEBRTC_CNG_MAX_LPC_ORDER,
inst->dec_filtstateLow, /* State preservation */
WEBRTC_CNG_MAX_LPC_ORDER,
outData, /* Filtered speech samples */
low,
nrOfSamples
);
return(0);
}
/****************************************************************************
* WebRtcCng_GetErrorCodeEnc/Dec(...)
*
* This functions can be used to check the error code of a CNG instance. When
* a function returns -1 a error code will be set for that instance. The
* function below extract the code of the last error that occured in the
* specified instance.
*
* Input:
* - CNG_inst : CNG enc/dec instance
*
* Return value : Error code
*/
WebRtc_Word16 WebRtcCng_GetErrorCodeEnc(CNG_enc_inst *cng_inst)
{
/* typecast pointer to real structure */
WebRtcCngEncInst_t* inst=(WebRtcCngEncInst_t*)cng_inst;
return inst->errorcode;
}
WebRtc_Word16 WebRtcCng_GetErrorCodeDec(CNG_dec_inst *cng_inst)
{
/* typecast pointer to real structure */
WebRtcCngDecInst_t* inst=(WebRtcCngDecInst_t*)cng_inst;
return inst->errorcode;
}

View File

@@ -0,0 +1,236 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_INTERFACE_WEBRTC_CNG_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_INTERFACE_WEBRTC_CNG_H_
#include "typedefs.h"
#ifdef __cplusplus
extern "C" {
#endif
#define WEBRTC_CNG_MAX_LPC_ORDER 12
#define WEBRTC_CNG_MAX_OUTSIZE_ORDER 640
/* Define Error codes */
/* 6100 Encoder */
#define CNG_ENCODER_MEMORY_ALLOCATION_FAILED 6110
#define CNG_ENCODER_NOT_INITIATED 6120
#define CNG_DISALLOWED_LPC_ORDER 6130
#define CNG_DISALLOWED_FRAME_SIZE 6140
#define CNG_DISALLOWED_SAMPLING_FREQUENCY 6150
/* 6200 Decoder */
#define CNG_DECODER_MEMORY_ALLOCATION_FAILED 6210
#define CNG_DECODER_NOT_INITIATED 6220
typedef struct WebRtcCngEncInst CNG_enc_inst;
typedef struct WebRtcCngDecInst CNG_dec_inst;
/****************************************************************************
* WebRtcCng_Version(...)
*
* These functions returns the version name (string must be at least
* 500 characters long)
*
* Output:
* - version : Pointer to character string
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_Version(WebRtc_Word8 *version);
/****************************************************************************
* WebRtcCng_AssignSizeEnc/Dec(...)
*
* These functions get the size needed for storing the instance for encoder
* and decoder, respectively
*
* Input/Output:
* - sizeinbytes : Pointer to integer where the size is returned
*
* Return value : 0
*/
WebRtc_Word16 WebRtcCng_AssignSizeEnc(int *sizeinbytes);
WebRtc_Word16 WebRtcCng_AssignSizeDec(int *sizeinbytes);
/****************************************************************************
* WebRtcCng_AssignEnc/Dec(...)
*
* These functions Assignes memory for the instances.
*
* Input:
* - CNG_inst_Addr : Adress to where to assign memory
* Output:
* - inst : Pointer to the instance that should be created
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_AssignEnc(CNG_enc_inst **inst, void *CNG_inst_Addr);
WebRtc_Word16 WebRtcCng_AssignDec(CNG_dec_inst **inst, void *CNG_inst_Addr);
/****************************************************************************
* WebRtcCng_CreateEnc/Dec(...)
*
* These functions create an instance to the specified structure
*
* Input:
* - XXX_inst : Pointer to created instance that should be created
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_CreateEnc(CNG_enc_inst **cng_inst);
WebRtc_Word16 WebRtcCng_CreateDec(CNG_dec_inst **cng_inst);
/****************************************************************************
* WebRtcCng_InitEnc/Dec(...)
*
* This function initializes a instance
*
* Input:
* - cng_inst : Instance that should be initialized
*
* - fs : 8000 for narrowband and 16000 for wideband
* - interval : generate SID data every interval ms
* - quality : Number of refl. coefs, maximum allowed is 12
*
* Output:
* - cng_inst : Initialized instance
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_InitEnc(CNG_enc_inst *cng_inst,
WebRtc_Word16 fs,
WebRtc_Word16 interval,
WebRtc_Word16 quality);
WebRtc_Word16 WebRtcCng_InitDec(CNG_dec_inst *cng_dec_inst);
/****************************************************************************
* WebRtcCng_FreeEnc/Dec(...)
*
* These functions frees the dynamic memory of a specified instance
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_FreeEnc(CNG_enc_inst *cng_inst);
WebRtc_Word16 WebRtcCng_FreeDec(CNG_dec_inst *cng_inst);
/****************************************************************************
* WebRtcCng_Encode(...)
*
* These functions analyzes background noise
*
* Input:
* - cng_inst : Pointer to created instance
* - speech : Signal to be analyzed
* - nrOfSamples : Size of speech vector
* - forceSID : not zero to force SID frame and reset
*
* Output:
* - bytesOut : Nr of bytes to transmit, might be 0
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_Encode(CNG_enc_inst *cng_inst,
WebRtc_Word16 *speech,
WebRtc_Word16 nrOfSamples,
WebRtc_UWord8* SIDdata,
WebRtc_Word16 *bytesOut,
WebRtc_Word16 forceSID);
/****************************************************************************
* WebRtcCng_UpdateSid(...)
*
* These functions updates the CN state, when a new SID packet arrives
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
* - SID : SID packet, all headers removed
* - length : Length in bytes of SID packet
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_UpdateSid(CNG_dec_inst *cng_inst,
WebRtc_UWord8 *SID,
WebRtc_Word16 length);
/****************************************************************************
* WebRtcCng_Generate(...)
*
* These functions generates CN data when needed
*
* Input:
* - cng_inst : Pointer to created instance that should be freed
* - outData : pointer to area to write CN data
* - nrOfSamples : How much data to generate
* - new_period : >0 if a new period of CNG, will reset history
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcCng_Generate(CNG_dec_inst *cng_inst,
WebRtc_Word16 * outData,
WebRtc_Word16 nrOfSamples,
WebRtc_Word16 new_period);
/*****************************************************************************
* WebRtcCng_GetErrorCodeEnc/Dec(...)
*
* This functions can be used to check the error code of a CNG instance. When
* a function returns -1 a error code will be set for that instance. The
* function below extract the code of the last error that occurred in the
* specified instance.
*
* Input:
* - CNG_inst : CNG enc/dec instance
*
* Return value : Error code
*/
WebRtc_Word16 WebRtcCng_GetErrorCodeEnc(CNG_enc_inst *cng_inst);
WebRtc_Word16 WebRtcCng_GetErrorCodeDec(CNG_dec_inst *cng_inst);
#ifdef __cplusplus
}
#endif
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_CNG_MAIN_INTERFACE_WEBRTC_CNG_H_

View File

@@ -0,0 +1,595 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_COMMON_TYPES_H
#define WEBRTC_COMMON_TYPES_H
#include "typedefs.h"
#ifdef WEBRTC_EXPORT
#define WEBRTC_DLLEXPORT _declspec(dllexport)
#elif WEBRTC_DLL
#define WEBRTC_DLLEXPORT _declspec(dllimport)
#else
#define WEBRTC_DLLEXPORT
#endif
#ifndef NULL
#define NULL 0
#endif
namespace webrtc {
class InStream
{
public:
virtual int Read(void *buf,int len) = 0;
virtual int Rewind() {return -1;}
virtual ~InStream() {}
protected:
InStream() {}
};
class OutStream
{
public:
virtual bool Write(const void *buf,int len) = 0;
virtual int Rewind() {return -1;}
virtual ~OutStream() {}
protected:
OutStream() {}
};
enum TraceModule
{
// not a module, triggered from the engine code
kTraceVoice = 0x0001,
// not a module, triggered from the engine code
kTraceVideo = 0x0002,
// not a module, triggered from the utility code
kTraceUtility = 0x0003,
kTraceRtpRtcp = 0x0004,
kTraceTransport = 0x0005,
kTraceSrtp = 0x0006,
kTraceAudioCoding = 0x0007,
kTraceAudioMixerServer = 0x0008,
kTraceAudioMixerClient = 0x0009,
kTraceFile = 0x000a,
kTraceAudioProcessing = 0x000b,
kTraceVideoCoding = 0x0010,
kTraceVideoMixer = 0x0011,
kTraceAudioDevice = 0x0012,
kTraceVideoRenderer = 0x0014,
kTraceVideoCapture = 0x0015,
kTraceVideoPreocessing = 0x0016
};
enum TraceLevel
{
kTraceNone = 0x0000, // no trace
kTraceStateInfo = 0x0001,
kTraceWarning = 0x0002,
kTraceError = 0x0004,
kTraceCritical = 0x0008,
kTraceApiCall = 0x0010,
kTraceDefault = 0x00ff,
kTraceModuleCall = 0x0020,
kTraceMemory = 0x0100, // memory info
kTraceTimer = 0x0200, // timing info
kTraceStream = 0x0400, // "continuous" stream of data
// used for debug purposes
kTraceDebug = 0x0800, // debug
kTraceInfo = 0x1000, // debug info
kTraceAll = 0xffff
};
// External Trace API
class TraceCallback
{
public:
virtual void Print(const TraceLevel level,
const char *traceString,
const int length) = 0;
protected:
virtual ~TraceCallback() {}
TraceCallback() {}
};
enum FileFormats
{
kFileFormatWavFile = 1,
kFileFormatCompressedFile = 2,
kFileFormatAviFile = 3,
kFileFormatPreencodedFile = 4,
kFileFormatPcm16kHzFile = 7,
kFileFormatPcm8kHzFile = 8,
kFileFormatPcm32kHzFile = 9
};
enum ProcessingTypes
{
kPlaybackPerChannel = 0,
kPlaybackAllChannelsMixed,
kRecordingPerChannel,
kRecordingAllChannelsMixed
};
// Encryption enums
enum CipherTypes
{
kCipherNull = 0,
kCipherAes128CounterMode = 1
};
enum AuthenticationTypes
{
kAuthNull = 0,
kAuthHmacSha1 = 3
};
enum SecurityLevels
{
kNoProtection = 0,
kEncryption = 1,
kAuthentication = 2,
kEncryptionAndAuthentication = 3
};
class Encryption
{
public:
virtual void encrypt(
int channel_no,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
virtual void decrypt(
int channel_no,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
virtual void encrypt_rtcp(
int channel_no,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
virtual void decrypt_rtcp(
int channel_no,
unsigned char* in_data,
unsigned char* out_data,
int bytes_in,
int* bytes_out) = 0;
protected:
virtual ~Encryption() {}
Encryption() {}
};
// External transport callback interface
class Transport
{
public:
virtual int SendPacket(int channel, const void *data, int len) = 0;
virtual int SendRTCPPacket(int channel, const void *data, int len) = 0;
protected:
virtual ~Transport() {}
Transport() {}
};
// ==================================================================
// Voice specific types
// ==================================================================
// Each codec supported can be described by this structure.
struct CodecInst
{
int pltype;
char plname[32];
int plfreq;
int pacsize;
int channels;
int rate;
};
enum FrameType
{
kFrameEmpty = 0,
kAudioFrameSpeech = 1,
kAudioFrameCN = 2,
kVideoFrameKey = 3, // independent frame
kVideoFrameDelta = 4, // depends on the previus frame
kVideoFrameGolden = 5, // depends on a old known previus frame
kVideoFrameAltRef = 6
};
// RTP
enum {kRtpCsrcSize = 15}; // RFC 3550 page 13
enum RTPDirections
{
kRtpIncoming = 0,
kRtpOutgoing
};
enum PayloadFrequencies
{
kFreq8000Hz = 8000,
kFreq16000Hz = 16000,
kFreq32000Hz = 32000
};
enum VadModes // degree of bandwidth reduction
{
kVadConventional = 0, // lowest reduction
kVadAggressiveLow,
kVadAggressiveMid,
kVadAggressiveHigh // highest reduction
};
struct NetworkStatistics // NETEQ statistics
{
// current jitter buffer size in ms
WebRtc_UWord16 currentBufferSize;
// preferred (optimal) buffer size in ms
WebRtc_UWord16 preferredBufferSize;
// loss rate (network + late) in percent (in Q14)
WebRtc_UWord16 currentPacketLossRate;
// late loss rate in percent (in Q14)
WebRtc_UWord16 currentDiscardRate;
// fraction (of original stream) of synthesized speech inserted through
// expansion (in Q14)
WebRtc_UWord16 currentExpandRate;
// fraction of synthesized speech inserted through pre-emptive expansion
// (in Q14)
WebRtc_UWord16 currentPreemptiveRate;
// fraction of data removed through acceleration (in Q14)
WebRtc_UWord16 currentAccelerateRate;
};
struct JitterStatistics
{
// smallest Jitter Buffer size during call in ms
WebRtc_UWord32 jbMinSize;
// largest Jitter Buffer size during call in ms
WebRtc_UWord32 jbMaxSize;
// the average JB size, measured over time - ms
WebRtc_UWord32 jbAvgSize;
// number of times the Jitter Buffer changed (using Accelerate or
// Pre-emptive Expand)
WebRtc_UWord32 jbChangeCount;
// amount (in ms) of audio data received late
WebRtc_UWord32 lateLossMs;
// milliseconds removed to reduce jitter buffer size
WebRtc_UWord32 accelerateMs;
// milliseconds discarded through buffer flushing
WebRtc_UWord32 flushedMs;
// milliseconds of generated silence
WebRtc_UWord32 generatedSilentMs;
// milliseconds of synthetic audio data (non-background noise)
WebRtc_UWord32 interpolatedVoiceMs;
// milliseconds of synthetic audio data (background noise level)
WebRtc_UWord32 interpolatedSilentMs;
// count of tiny expansions in output audio
WebRtc_UWord32 countExpandMoreThan120ms;
// count of small expansions in output audio
WebRtc_UWord32 countExpandMoreThan250ms;
// count of medium expansions in output audio
WebRtc_UWord32 countExpandMoreThan500ms;
// count of long expansions in output audio
WebRtc_UWord32 countExpandMoreThan2000ms;
// duration of longest audio drop-out
WebRtc_UWord32 longestExpandDurationMs;
// count of times we got small network outage (inter-arrival time in
// [500, 1000) ms)
WebRtc_UWord32 countIAT500ms;
// count of times we got medium network outage (inter-arrival time in
// [1000, 2000) ms)
WebRtc_UWord32 countIAT1000ms;
// count of times we got large network outage (inter-arrival time >=
// 2000 ms)
WebRtc_UWord32 countIAT2000ms;
// longest packet inter-arrival time in ms
WebRtc_UWord32 longestIATms;
// min time incoming Packet "waited" to be played
WebRtc_UWord32 minPacketDelayMs;
// max time incoming Packet "waited" to be played
WebRtc_UWord32 maxPacketDelayMs;
// avg time incoming Packet "waited" to be played
WebRtc_UWord32 avgPacketDelayMs;
};
typedef struct
{
int min; // minumum
int max; // maximum
int average; // average
} StatVal;
typedef struct // All levels are reported in dBm0
{
StatVal speech_rx; // long-term speech levels on receiving side
StatVal speech_tx; // long-term speech levels on transmitting side
StatVal noise_rx; // long-term noise/silence levels on receiving side
StatVal noise_tx; // long-term noise/silence levels on transmitting side
} LevelStatistics;
typedef struct // All levels are reported in dB
{
StatVal erl; // Echo Return Loss
StatVal erle; // Echo Return Loss Enhancement
StatVal rerl; // RERL = ERL + ERLE
// Echo suppression inside EC at the point just before its NLP
StatVal a_nlp;
} EchoStatistics;
enum TelephoneEventDetectionMethods
{
kInBand = 0,
kOutOfBand = 1,
kInAndOutOfBand = 2
};
enum NsModes // type of Noise Suppression
{
kNsUnchanged = 0, // previously set mode
kNsDefault, // platform default
kNsConference, // conferencing default
kNsLowSuppression, // lowest suppression
kNsModerateSuppression,
kNsHighSuppression,
kNsVeryHighSuppression, // highest suppression
};
enum AgcModes // type of Automatic Gain Control
{
kAgcUnchanged = 0, // previously set mode
kAgcDefault, // platform default
// adaptive mode for use when analog volume control exists (e.g. for
// PC softphone)
kAgcAdaptiveAnalog,
// scaling takes place in the digital domain (e.g. for conference servers
// and embedded devices)
kAgcAdaptiveDigital,
// can be used on embedded devices where the the capture signal is level
// is predictable
kAgcFixedDigital
};
// EC modes
enum EcModes // type of Echo Control
{
kEcUnchanged = 0, // previously set mode
kEcDefault, // platform default
kEcConference, // conferencing default (aggressive AEC)
kEcAec, // Acoustic Echo Cancellation
kEcAecm, // AEC mobile
};
// AECM modes
enum AecmModes // mode of AECM
{
kAecmQuietEarpieceOrHeadset = 0,
// Quiet earpiece or headset use
kAecmEarpiece, // most earpiece use
kAecmLoudEarpiece, // Loud earpiece or quiet speakerphone use
kAecmSpeakerphone, // most speakerphone use (default)
kAecmLoudSpeakerphone // Loud speakerphone
};
// AGC configuration
typedef struct
{
unsigned short targetLeveldBOv;
unsigned short digitalCompressionGaindB;
bool limiterEnable;
} AgcConfig; // AGC configuration parameters
enum StereoChannel
{
kStereoLeft = 0,
kStereoRight,
kStereoBoth
};
// Audio device layers
enum AudioLayers
{
kAudioPlatformDefault = 0,
kAudioWindowsWave = 1,
kAudioWindowsCore = 2,
kAudioLinuxAlsa = 3,
kAudioLinuxPulse = 4
};
enum NetEqModes // NetEQ playout configurations
{
// Optimized trade-off between low delay and jitter robustness for two-way
// communication.
kNetEqDefault = 0,
// Improved jitter robustness at the cost of increased delay. Can be
// used in one-way communication.
kNetEqStreaming = 1,
// Optimzed for decodability of fax signals rather than for perceived audio
// quality.
kNetEqFax = 2,
};
enum NetEqBgnModes // NetEQ Background Noise (BGN) configurations
{
// BGN is always on and will be generated when the incoming RTP stream
// stops (default).
kBgnOn = 0,
// The BGN is faded to zero (complete silence) after a few seconds.
kBgnFade = 1,
// BGN is not used at all. Silence is produced after speech extrapolation
// has faded.
kBgnOff = 2,
};
enum OnHoldModes // On Hold direction
{
kHoldSendAndPlay = 0, // Put both sending and playing in on-hold state.
kHoldSendOnly, // Put only sending in on-hold state.
kHoldPlayOnly // Put only playing in on-hold state.
};
enum AmrMode
{
kRfc3267BwEfficient = 0,
kRfc3267OctetAligned = 1,
kRfc3267FileStorage = 2,
};
// ==================================================================
// Video specific types
// ==================================================================
// Raw video types
enum RawVideoType
{
kVideoI420 = 0,
kVideoYV12 = 1,
kVideoYUY2 = 2,
kVideoUYVY = 3,
kVideoIYUV = 4,
kVideoARGB = 5,
kVideoRGB24 = 6,
kVideoRGB565 = 7,
kVideoARGB4444 = 8,
kVideoARGB1555 = 9,
kVideoMJPEG = 10,
kVideoNV12 = 11,
kVideoNV21 = 12,
kVideoUnknown = 99
};
// Video codec
enum { kConfigParameterSize = 128};
enum { kPayloadNameSize = 32};
// H.263 specific
struct VideoCodecH263
{
char quality;
};
// H.264 specific
enum H264Packetization
{
kH264SingleMode = 0,
kH264NonInterleavedMode = 1
};
enum VideoCodecComplexity
{
kComplexityNormal = 0,
kComplexityHigh = 1,
kComplexityHigher = 2,
kComplexityMax = 3
};
enum VideoCodecProfile
{
kProfileBase = 0x00,
kProfileMain = 0x01
};
struct VideoCodecH264
{
H264Packetization packetization;
VideoCodecComplexity complexity;
VideoCodecProfile profile;
char level;
char quality;
bool useFMO;
unsigned char configParameters[kConfigParameterSize];
unsigned char configParametersSize;
};
// VP8 specific
struct VideoCodecVP8
{
bool pictureLossIndicationOn;
bool feedbackModeOn;
VideoCodecComplexity complexity;
};
// MPEG-4 specific
struct VideoCodecMPEG4
{
unsigned char configParameters[kConfigParameterSize];
unsigned char configParametersSize;
char level;
};
// Unknown specific
struct VideoCodecGeneric
{
};
// Video codec types
enum VideoCodecType
{
kVideoCodecH263,
kVideoCodecH264,
kVideoCodecVP8,
kVideoCodecMPEG4,
kVideoCodecI420,
kVideoCodecRED,
kVideoCodecULPFEC,
kVideoCodecUnknown
};
union VideoCodecUnion
{
VideoCodecH263 H263;
VideoCodecH264 H264;
VideoCodecVP8 VP8;
VideoCodecMPEG4 MPEG4;
VideoCodecGeneric Generic;
};
// Common video codec properties
struct VideoCodec
{
VideoCodecType codecType;
char plName[kPayloadNameSize];
unsigned char plType;
unsigned short width;
unsigned short height;
unsigned int startBitrate;
unsigned int maxBitrate;
unsigned int minBitrate;
unsigned char maxFramerate;
VideoCodecUnion codecSpecific;
unsigned int qpMax;
};
} // namespace webrtc
#endif // WEBRTC_COMMON_TYPES_H

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_ENGINE_CONFIGURATIONS_H_
#define WEBRTC_ENGINE_CONFIGURATIONS_H_
// ============================================================================
// Voice and Video
// ============================================================================
// #define WEBRTC_EXTERNAL_TRANSPORT
// ----------------------------------------------------------------------------
// [Voice] Codec settings
// ----------------------------------------------------------------------------
#define WEBRTC_CODEC_ILBC
#define WEBRTC_CODEC_ISAC // floating-point iSAC implementation (default)
// #define WEBRTC_CODEC_ISACFX // fix-point iSAC implementation
#define WEBRTC_CODEC_G722
#define WEBRTC_CODEC_PCM16
#define WEBRTC_CODEC_RED
#define WEBRTC_CODEC_AVT
// ----------------------------------------------------------------------------
// [Video] Codec settings
// ----------------------------------------------------------------------------
#define VIDEOCODEC_I420
#define VIDEOCODEC_VP8
// ============================================================================
// VoiceEngine
// ============================================================================
// ----------------------------------------------------------------------------
// Settings for VoiceEngine
// ----------------------------------------------------------------------------
#define WEBRTC_VOICE_ENGINE_AGC // Near-end AGC
#define WEBRTC_VOICE_ENGINE_ECHO // Near-end AEC
#define WEBRTC_VOICE_ENGINE_NR // Near-end NS
#define WEBRTC_VOICE_ENGINE_TYPING_DETECTION
#define WEBRTC_VOE_EXTERNAL_REC_AND_PLAYOUT
// ----------------------------------------------------------------------------
// VoiceEngine sub-APIs
// ----------------------------------------------------------------------------
#define WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API
#define WEBRTC_VOICE_ENGINE_CALL_REPORT_API
#define WEBRTC_VOICE_ENGINE_CODEC_API
#define WEBRTC_VOICE_ENGINE_DTMF_API
#define WEBRTC_VOICE_ENGINE_ENCRYPTION_API
#define WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API
#define WEBRTC_VOICE_ENGINE_FILE_API
#define WEBRTC_VOICE_ENGINE_HARDWARE_API
#define WEBRTC_VOICE_ENGINE_NETEQ_STATS_API
#define WEBRTC_VOICE_ENGINE_NETWORK_API
#define WEBRTC_VOICE_ENGINE_RTP_RTCP_API
#define WEBRTC_VOICE_ENGINE_VIDEO_SYNC_API
#define WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API
// ============================================================================
// VideoEngine
// ============================================================================
// ----------------------------------------------------------------------------
// Settings for special VideoEngine configurations
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// VideoEngine sub-API:s
// ----------------------------------------------------------------------------
#define WEBRTC_VIDEO_ENGINE_CAPTURE_API
#define WEBRTC_VIDEO_ENGINE_CODEC_API
#define WEBRTC_VIDEO_ENGINE_ENCRYPTION_API
#define WEBRTC_VIDEO_ENGINE_FILE_API
#define WEBRTC_VIDEO_ENGINE_IMAGE_PROCESS_API
#define WEBRTC_VIDEO_ENGINE_NETWORK_API
#define WEBRTC_VIDEO_ENGINE_RENDER_API
#define WEBRTC_VIDEO_ENGINE_RTP_RTCP_API
// #define WEBRTC_VIDEO_ENGINE_EXTERNAL_CODEC_API
// ============================================================================
// Platform specific configurations
// ============================================================================
// ----------------------------------------------------------------------------
// VideoEngine Windows
// ----------------------------------------------------------------------------
#if defined(_WIN32)
// #define DIRECTDRAW_RENDERING
#define DIRECT3D9_RENDERING // Requires DirectX 9.
#endif
// ----------------------------------------------------------------------------
// VideoEngine MAC
// ----------------------------------------------------------------------------
#if defined(WEBRTC_MAC) && !defined(MAC_IPHONE)
// #define CARBON_RENDERING
#define COCOA_RENDERING
#endif
// ----------------------------------------------------------------------------
// VideoEngine Mobile iPhone
// ----------------------------------------------------------------------------
#if defined(MAC_IPHONE)
#define EAGL_RENDERING
#endif
// ----------------------------------------------------------------------------
// Deprecated
// ----------------------------------------------------------------------------
// #define WEBRTC_CODEC_G729
// #define WEBRTC_DTMF_DETECTION
// #define WEBRTC_SRTP
// #define WEBRTC_SRTP_ALLOW_ROC_ITERATION
#endif // WEBRTC_ENGINE_CONFIGURATIONS_H_

View File

@@ -0,0 +1,83 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* g711.c - A-law and u-law transcoding routines
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2006 Steve Underwood
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
* $Id: g711.c,v 1.1 2006/06/07 15:46:39 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Removed unused include files
* -Changed to use WebRtc types
* -Added option to run encoder bitexact with ITU-T reference implementation
*/
/*! \file */
#include "g711.h"
#include "typedefs.h"
/* Copied from the CCITT G.711 specification */
static const WebRtc_UWord8 ulaw_to_alaw_table[256] =
{
42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37,
58, 59, 56, 57, 62, 63, 60, 61, 50, 51, 48, 49, 54, 55, 52, 53,
10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 26,
27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21, 106,
104, 105, 110, 111, 108, 109, 98, 99, 96, 97, 102, 103, 100, 101, 122, 120,
126, 127, 124, 125, 114, 115, 112, 113, 118, 119, 116, 117, 75, 73, 79, 77,
66, 67, 64, 65, 70, 71, 68, 69, 90, 91, 88, 89, 94, 95, 92, 93,
82, 82, 83, 83, 80, 80, 81, 81, 86, 86, 87, 87, 84, 84, 85, 85,
170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165,
186, 187, 184, 185, 190, 191, 188, 189, 178, 179, 176, 177, 182, 183, 180, 181,
138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 154,
155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, 234,
232, 233, 238, 239, 236, 237, 226, 227, 224, 225, 230, 231, 228, 229, 250, 248,
254, 255, 252, 253, 242, 243, 240, 241, 246, 247, 244, 245, 203, 201, 207, 205,
194, 195, 192, 193, 198, 199, 196, 197, 218, 219, 216, 217, 222, 223, 220, 221,
210, 210, 211, 211, 208, 208, 209, 209, 214, 214, 215, 215, 212, 212, 213, 213
};
/* These transcoding tables are copied from the CCITT G.711 specification. To achieve
optimal results, do not change them. */
static const WebRtc_UWord8 alaw_to_ulaw_table[256] =
{
42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37,
57, 58, 55, 56, 61, 62, 59, 60, 49, 50, 47, 48, 53, 54, 51, 52,
10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5,
26, 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21,
98, 99, 96, 97, 102, 103, 100, 101, 93, 93, 92, 92, 95, 95, 94, 94,
116, 118, 112, 114, 124, 126, 120, 122, 106, 107, 104, 105, 110, 111, 108, 109,
72, 73, 70, 71, 76, 77, 74, 75, 64, 65, 63, 63, 68, 69, 66, 67,
86, 87, 84, 85, 90, 91, 88, 89, 79, 79, 78, 78, 82, 83, 80, 81,
170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165,
185, 186, 183, 184, 189, 190, 187, 188, 177, 178, 175, 176, 181, 182, 179, 180,
138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 133,
154, 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149,
226, 227, 224, 225, 230, 231, 228, 229, 221, 221, 220, 220, 223, 223, 222, 222,
244, 246, 240, 242, 252, 254, 248, 250, 234, 235, 232, 233, 238, 239, 236, 237,
200, 201, 198, 199, 204, 205, 202, 203, 192, 193, 191, 191, 196, 197, 194, 195,
214, 215, 212, 213, 218, 219, 216, 217, 207, 207, 206, 206, 210, 211, 208, 209
};
WebRtc_UWord8 alaw_to_ulaw(WebRtc_UWord8 alaw)
{
return alaw_to_ulaw_table[alaw];
}
/*- End of function --------------------------------------------------------*/
WebRtc_UWord8 ulaw_to_alaw(WebRtc_UWord8 ulaw)
{
return ulaw_to_alaw_table[ulaw];
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

382
src/libs/webrtc/g711/g711.h Normal file
View File

@@ -0,0 +1,382 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* g711.h - In line A-law and u-law conversion routines
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2001 Steve Underwood
*
* Despite my general liking of the GPL, I place this code in the
* public domain for the benefit of all mankind - even the slimy
* ones who might try to proprietize my work and use it to my
* detriment.
*
* $Id: g711.h,v 1.1 2006/06/07 15:46:39 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Changed to use WebRtc types
* -Changed __inline__ to __inline
* -Two changes to make implementation bitexact with ITU-T reference implementation
*/
/*! \file */
/*! \page g711_page A-law and mu-law handling
Lookup tables for A-law and u-law look attractive, until you consider the impact
on the CPU cache. If it causes a substantial area of your processor cache to get
hit too often, cache sloshing will severely slow things down. The main reason
these routines are slow in C, is the lack of direct access to the CPU's "find
the first 1" instruction. A little in-line assembler fixes that, and the
conversion routines can be faster than lookup tables, in most real world usage.
A "find the first 1" instruction is available on most modern CPUs, and is a
much underused feature.
If an assembly language method of bit searching is not available, these routines
revert to a method that can be a little slow, so the cache thrashing might not
seem so bad :(
Feel free to submit patches to add fast "find the first 1" support for your own
favourite processor.
Look up tables are used for transcoding between A-law and u-law, since it is
difficult to achieve the precise transcoding procedure laid down in the G.711
specification by other means.
*/
#if !defined(_G711_H_)
#define _G711_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "typedefs.h"
#if defined(__i386__)
/*! \brief Find the bit position of the highest set bit in a word
\param bits The word to be searched
\return The bit number of the highest set bit, or -1 if the word is zero. */
static __inline__ int top_bit(unsigned int bits)
{
int res;
__asm__ __volatile__(" movl $-1,%%edx;\n"
" bsrl %%eax,%%edx;\n"
: "=d" (res)
: "a" (bits));
return res;
}
/*- End of function --------------------------------------------------------*/
/*! \brief Find the bit position of the lowest set bit in a word
\param bits The word to be searched
\return The bit number of the lowest set bit, or -1 if the word is zero. */
static __inline__ int bottom_bit(unsigned int bits)
{
int res;
__asm__ __volatile__(" movl $-1,%%edx;\n"
" bsfl %%eax,%%edx;\n"
: "=d" (res)
: "a" (bits));
return res;
}
/*- End of function --------------------------------------------------------*/
#elif defined(__x86_64__)
static __inline__ int top_bit(unsigned int bits)
{
int res;
__asm__ __volatile__(" movq $-1,%%rdx;\n"
" bsrq %%rax,%%rdx;\n"
: "=d" (res)
: "a" (bits));
return res;
}
/*- End of function --------------------------------------------------------*/
static __inline__ int bottom_bit(unsigned int bits)
{
int res;
__asm__ __volatile__(" movq $-1,%%rdx;\n"
" bsfq %%rax,%%rdx;\n"
: "=d" (res)
: "a" (bits));
return res;
}
/*- End of function --------------------------------------------------------*/
#else
static __inline int top_bit(unsigned int bits)
{
int i;
if (bits == 0)
return -1;
i = 0;
if (bits & 0xFFFF0000)
{
bits &= 0xFFFF0000;
i += 16;
}
if (bits & 0xFF00FF00)
{
bits &= 0xFF00FF00;
i += 8;
}
if (bits & 0xF0F0F0F0)
{
bits &= 0xF0F0F0F0;
i += 4;
}
if (bits & 0xCCCCCCCC)
{
bits &= 0xCCCCCCCC;
i += 2;
}
if (bits & 0xAAAAAAAA)
{
bits &= 0xAAAAAAAA;
i += 1;
}
return i;
}
/*- End of function --------------------------------------------------------*/
static __inline int bottom_bit(unsigned int bits)
{
int i;
if (bits == 0)
return -1;
i = 32;
if (bits & 0x0000FFFF)
{
bits &= 0x0000FFFF;
i -= 16;
}
if (bits & 0x00FF00FF)
{
bits &= 0x00FF00FF;
i -= 8;
}
if (bits & 0x0F0F0F0F)
{
bits &= 0x0F0F0F0F;
i -= 4;
}
if (bits & 0x33333333)
{
bits &= 0x33333333;
i -= 2;
}
if (bits & 0x55555555)
{
bits &= 0x55555555;
i -= 1;
}
return i;
}
/*- End of function --------------------------------------------------------*/
#endif
/* N.B. It is tempting to use look-up tables for A-law and u-law conversion.
* However, you should consider the cache footprint.
*
* A 64K byte table for linear to x-law and a 512 byte table for x-law to
* linear sound like peanuts these days, and shouldn't an array lookup be
* real fast? No! When the cache sloshes as badly as this one will, a tight
* calculation may be better. The messiest part is normally finding the
* segment, but a little inline assembly can fix that on an i386, x86_64 and
* many other modern processors.
*/
/*
* Mu-law is basically as follows:
*
* Biased Linear Input Code Compressed Code
* ------------------------ ---------------
* 00000001wxyza 000wxyz
* 0000001wxyzab 001wxyz
* 000001wxyzabc 010wxyz
* 00001wxyzabcd 011wxyz
* 0001wxyzabcde 100wxyz
* 001wxyzabcdef 101wxyz
* 01wxyzabcdefg 110wxyz
* 1wxyzabcdefgh 111wxyz
*
* Each biased linear code has a leading 1 which identifies the segment
* number. The value of the segment number is equal to 7 minus the number
* of leading 0's. The quantization interval is directly available as the
* four bits wxyz. * The trailing bits (a - h) are ignored.
*
* Ordinarily the complement of the resulting code word is used for
* transmission, and so the code word is complemented before it is returned.
*
* For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476.
*/
//#define ULAW_ZEROTRAP /* turn on the trap as per the MIL-STD */
#define ULAW_BIAS 0x84 /* Bias for linear code. */
/*! \brief Encode a linear sample to u-law
\param linear The sample to encode.
\return The u-law value.
*/
static __inline WebRtc_UWord8 linear_to_ulaw(int linear)
{
WebRtc_UWord8 u_val;
int mask;
int seg;
/* Get the sign and the magnitude of the value. */
if (linear < 0)
{
/* WebRtc, tlegrand: -1 added to get bitexact to reference implementation */
linear = ULAW_BIAS - linear - 1;
mask = 0x7F;
}
else
{
linear = ULAW_BIAS + linear;
mask = 0xFF;
}
seg = top_bit(linear | 0xFF) - 7;
/*
* Combine the sign, segment, quantization bits,
* and complement the code word.
*/
if (seg >= 8)
u_val = (WebRtc_UWord8) (0x7F ^ mask);
else
u_val = (WebRtc_UWord8) (((seg << 4) | ((linear >> (seg + 3)) & 0xF)) ^ mask);
#ifdef ULAW_ZEROTRAP
/* Optional ITU trap */
if (u_val == 0)
u_val = 0x02;
#endif
return u_val;
}
/*- End of function --------------------------------------------------------*/
/*! \brief Decode an u-law sample to a linear value.
\param ulaw The u-law sample to decode.
\return The linear value.
*/
static __inline WebRtc_Word16 ulaw_to_linear(WebRtc_UWord8 ulaw)
{
int t;
/* Complement to obtain normal u-law value. */
ulaw = ~ulaw;
/*
* Extract and bias the quantization bits. Then
* shift up by the segment number and subtract out the bias.
*/
t = (((ulaw & 0x0F) << 3) + ULAW_BIAS) << (((int) ulaw & 0x70) >> 4);
return (WebRtc_Word16) ((ulaw & 0x80) ? (ULAW_BIAS - t) : (t - ULAW_BIAS));
}
/*- End of function --------------------------------------------------------*/
/*
* A-law is basically as follows:
*
* Linear Input Code Compressed Code
* ----------------- ---------------
* 0000000wxyza 000wxyz
* 0000001wxyza 001wxyz
* 000001wxyzab 010wxyz
* 00001wxyzabc 011wxyz
* 0001wxyzabcd 100wxyz
* 001wxyzabcde 101wxyz
* 01wxyzabcdef 110wxyz
* 1wxyzabcdefg 111wxyz
*
* For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476.
*/
#define ALAW_AMI_MASK 0x55
/*! \brief Encode a linear sample to A-law
\param linear The sample to encode.
\return The A-law value.
*/
static __inline WebRtc_UWord8 linear_to_alaw(int linear)
{
int mask;
int seg;
if (linear >= 0)
{
/* Sign (bit 7) bit = 1 */
mask = ALAW_AMI_MASK | 0x80;
}
else
{
/* Sign (bit 7) bit = 0 */
mask = ALAW_AMI_MASK;
/* WebRtc, tlegrand: Changed from -8 to -1 to get bitexact to reference
* implementation */
linear = -linear - 1;
}
/* Convert the scaled magnitude to segment number. */
seg = top_bit(linear | 0xFF) - 7;
if (seg >= 8)
{
if (linear >= 0)
{
/* Out of range. Return maximum value. */
return (WebRtc_UWord8) (0x7F ^ mask);
}
/* We must be just a tiny step below zero */
return (WebRtc_UWord8) (0x00 ^ mask);
}
/* Combine the sign, segment, and quantization bits. */
return (WebRtc_UWord8) (((seg << 4) | ((linear >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask);
}
/*- End of function --------------------------------------------------------*/
/*! \brief Decode an A-law sample to a linear value.
\param alaw The A-law sample to decode.
\return The linear value.
*/
static __inline WebRtc_Word16 alaw_to_linear(WebRtc_UWord8 alaw)
{
int i;
int seg;
alaw ^= ALAW_AMI_MASK;
i = ((alaw & 0x0F) << 4);
seg = (((int) alaw & 0x70) >> 4);
if (seg)
i = (i + 0x108) << (seg - 1);
else
i += 8;
return (WebRtc_Word16) ((alaw & 0x80) ? i : -i);
}
/*- End of function --------------------------------------------------------*/
/*! \brief Transcode from A-law to u-law, using the procedure defined in G.711.
\param alaw The A-law sample to transcode.
\return The best matching u-law value.
*/
WebRtc_UWord8 alaw_to_ulaw(WebRtc_UWord8 alaw);
/*! \brief Transcode from u-law to A-law, using the procedure defined in G.711.
\param alaw The u-law sample to transcode.
\return The best matching A-law value.
*/
WebRtc_UWord8 ulaw_to_alaw(WebRtc_UWord8 ulaw);
#ifdef __cplusplus
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include "g711.h"
#include "g711_interface.h"
#include "typedefs.h"
WebRtc_Word16 WebRtcG711_EncodeA(void *state,
WebRtc_Word16 *speechIn,
WebRtc_Word16 len,
WebRtc_Word16 *encoded)
{
int n;
WebRtc_UWord16 tempVal, tempVal2;
// Set and discard to avoid getting warnings
(void)(state = NULL);
// Sanity check of input length
if (len < 0) {
return (-1);
}
// Loop over all samples
for (n = 0; n < len; n++) {
tempVal = (WebRtc_UWord16)linear_to_alaw(speechIn[n]);
#ifdef WEBRTC_BIG_ENDIAN
if ((n & 0x1) == 1) {
encoded[n>>1]|=((WebRtc_UWord16)tempVal);
} else {
encoded[n>>1]=((WebRtc_UWord16)tempVal)<<8;
}
#else
if ((n & 0x1) == 1) {
tempVal2 |= ((WebRtc_UWord16) tempVal) << 8;
encoded[n >> 1] |= ((WebRtc_UWord16) tempVal) << 8;
} else {
tempVal2 = ((WebRtc_UWord16) tempVal);
encoded[n >> 1] = ((WebRtc_UWord16) tempVal);
}
#endif
}
return (len);
}
WebRtc_Word16 WebRtcG711_EncodeU(void *state,
WebRtc_Word16 *speechIn,
WebRtc_Word16 len,
WebRtc_Word16 *encoded)
{
int n;
WebRtc_UWord16 tempVal;
// Set and discard to avoid getting warnings
(void)(state = NULL);
// Sanity check of input length
if (len < 0) {
return (-1);
}
// Loop over all samples
for (n = 0; n < len; n++) {
tempVal = (WebRtc_UWord16)linear_to_ulaw(speechIn[n]);
#ifdef WEBRTC_BIG_ENDIAN
if ((n & 0x1) == 1) {
encoded[n>>1]|=((WebRtc_UWord16)tempVal);
} else {
encoded[n>>1]=((WebRtc_UWord16)tempVal)<<8;
}
#else
if ((n & 0x1) == 1) {
encoded[n >> 1] |= ((WebRtc_UWord16) tempVal) << 8;
} else {
encoded[n >> 1] = ((WebRtc_UWord16) tempVal);
}
#endif
}
return (len);
}
WebRtc_Word16 WebRtcG711_DecodeA(void *state,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType)
{
int n;
WebRtc_UWord16 tempVal;
// Set and discard to avoid getting warnings
(void)(state = NULL);
// Sanity check of input length
if (len < 0) {
return (-1);
}
for (n = 0; n < len; n++) {
#ifdef WEBRTC_BIG_ENDIAN
if ((n & 0x1) == 1) {
tempVal=((WebRtc_UWord16)encoded[n>>1] & 0xFF);
} else {
tempVal=((WebRtc_UWord16)encoded[n>>1] >> 8);
}
#else
if ((n & 0x1) == 1) {
tempVal = (encoded[n >> 1] >> 8);
} else {
tempVal = (encoded[n >> 1] & 0xFF);
}
#endif
decoded[n] = (WebRtc_Word16) alaw_to_linear(tempVal);
}
*speechType = 1;
return (len);
}
WebRtc_Word16 WebRtcG711_DecodeU(void *state,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType)
{
int n;
WebRtc_UWord16 tempVal;
// Set and discard to avoid getting warnings
(void)(state = NULL);
// Sanity check of input length
if (len < 0) {
return (-1);
}
for (n = 0; n < len; n++) {
#ifdef WEBRTC_BIG_ENDIAN
if ((n & 0x1) == 1) {
tempVal=((WebRtc_UWord16)encoded[n>>1] & 0xFF);
} else {
tempVal=((WebRtc_UWord16)encoded[n>>1] >> 8);
}
#else
if ((n & 0x1) == 1) {
tempVal = (encoded[n >> 1] >> 8);
} else {
tempVal = (encoded[n >> 1] & 0xFF);
}
#endif
decoded[n] = (WebRtc_Word16) ulaw_to_linear(tempVal);
}
*speechType = 1;
return (len);
}
WebRtc_Word16 WebRtcG711_Version(char* version, WebRtc_Word16 lenBytes)
{
strncpy(version, "2.0.0", lenBytes);
return 0;
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_CODING_CODECS_G711_MAIN_INTERFACE_G711_INTERFACE_H_
#define MODULES_AUDIO_CODING_CODECS_G711_MAIN_INTERFACE_G711_INTERFACE_H_
#include "typedefs.h"
// Comfort noise constants
#define G711_WEBRTC_SPEECH 1
#define G711_WEBRTC_CNG 2
#ifdef __cplusplus
extern "C" {
#endif
/****************************************************************************
* WebRtcG711_EncodeA(...)
*
* This function encodes a G711 A-law frame and inserts it into a packet.
* Input speech length has be of any length.
*
* Input:
* - state : Dummy state to make this codec look more like
* other codecs
* - speechIn : Input speech vector
* - len : Samples in speechIn
*
* Output:
* - encoded : The encoded data vector
*
* Return value : >0 - Length (in bytes) of coded data
* -1 - Error
*/
WebRtc_Word16 WebRtcG711_EncodeA(void *state,
WebRtc_Word16 *speechIn,
WebRtc_Word16 len,
WebRtc_Word16 *encoded);
/****************************************************************************
* WebRtcG711_EncodeU(...)
*
* This function encodes a G711 U-law frame and inserts it into a packet.
* Input speech length has be of any length.
*
* Input:
* - state : Dummy state to make this codec look more like
* other codecs
* - speechIn : Input speech vector
* - len : Samples in speechIn
*
* Output:
* - encoded : The encoded data vector
*
* Return value : >0 - Length (in bytes) of coded data
* -1 - Error
*/
WebRtc_Word16 WebRtcG711_EncodeU(void *state,
WebRtc_Word16 *speechIn,
WebRtc_Word16 len,
WebRtc_Word16 *encoded);
/****************************************************************************
* WebRtcG711_DecodeA(...)
*
* This function decodes a packet G711 A-law frame.
*
* Input:
* - state : Dummy state to make this codec look more like
* other codecs
* - encoded : Encoded data
* - len : Bytes in encoded vector
*
* Output:
* - decoded : The decoded vector
* - speechType : 1 normal, 2 CNG (for G711 it should
* always return 1 since G711 does not have a
* built-in DTX/CNG scheme)
*
* Return value : >0 - Samples in decoded vector
* -1 - Error
*/
WebRtc_Word16 WebRtcG711_DecodeA(void *state,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType);
/****************************************************************************
* WebRtcG711_DecodeU(...)
*
* This function decodes a packet G711 U-law frame.
*
* Input:
* - state : Dummy state to make this codec look more like
* other codecs
* - encoded : Encoded data
* - len : Bytes in encoded vector
*
* Output:
* - decoded : The decoded vector
* - speechType : 1 normal, 2 CNG (for G711 it should
* always return 1 since G711 does not have a
* built-in DTX/CNG scheme)
*
* Return value : >0 - Samples in decoded vector
* -1 - Error
*/
WebRtc_Word16 WebRtcG711_DecodeU(void *state,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType);
/**********************************************************************
* WebRtcG711_Version(...)
*
* This function gives the version string of the G.711 codec.
*
* Input:
* - lenBytes: the size of Allocated space (in Bytes) where
* the version number is written to (in string format).
*
* Output:
* - version: Pointer to a buffer where the version number is
* written to.
*
*/
WebRtc_Word16 WebRtcG711_Version(char* version, WebRtc_Word16 lenBytes);
#ifdef __cplusplus
}
#endif
#endif /* MODULES_AUDIO_CODING_CODECS_G711_MAIN_INTERFACE_G711_INTERFACE_H_ */

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_AbsQuant.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "abs_quant_loop.h"
/*----------------------------------------------------------------*
* predictive noise shaping encoding of scaled start state
* (subrutine for WebRtcIlbcfix_StateSearch)
*---------------------------------------------------------------*/
void WebRtcIlbcfix_AbsQuant(
iLBC_Enc_Inst_t *iLBCenc_inst,
/* (i) Encoder instance */
iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax
and idxVec, uses state_first as
input) */
WebRtc_Word16 *in, /* (i) vector to encode */
WebRtc_Word16 *weightDenum /* (i) denominator of synthesis filter */
) {
WebRtc_Word16 *syntOut;
WebRtc_Word16 quantLen[2];
/* Stack based */
WebRtc_Word16 syntOutBuf[LPC_FILTERORDER+STATE_SHORT_LEN_30MS];
WebRtc_Word16 in_weightedVec[STATE_SHORT_LEN_30MS+LPC_FILTERORDER];
WebRtc_Word16 *in_weighted = &in_weightedVec[LPC_FILTERORDER];
/* Initialize the buffers */
WebRtcSpl_MemSetW16(syntOutBuf, 0, LPC_FILTERORDER+STATE_SHORT_LEN_30MS);
syntOut = &syntOutBuf[LPC_FILTERORDER];
/* Start with zero state */
WebRtcSpl_MemSetW16(in_weightedVec, 0, LPC_FILTERORDER);
/* Perform the quantization loop in two sections of length quantLen[i],
where the perceptual weighting filter is updated at the subframe
border */
if (iLBC_encbits->state_first) {
quantLen[0]=SUBL;
quantLen[1]=iLBCenc_inst->state_short_len-SUBL;
} else {
quantLen[0]=iLBCenc_inst->state_short_len-SUBL;
quantLen[1]=SUBL;
}
/* Calculate the weighted residual, switch perceptual weighting
filter at the subframe border */
WebRtcSpl_FilterARFastQ12(
in, in_weighted,
weightDenum, LPC_FILTERORDER+1, quantLen[0]);
WebRtcSpl_FilterARFastQ12(
&in[quantLen[0]], &in_weighted[quantLen[0]],
&weightDenum[LPC_FILTERORDER+1], LPC_FILTERORDER+1, quantLen[1]);
WebRtcIlbcfix_AbsQuantLoop(
syntOut,
in_weighted,
weightDenum,
quantLen,
iLBC_encbits->idxVec);
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_AbsQuant.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
#include "defines.h"
/*----------------------------------------------------------------*
* predictive noise shaping encoding of scaled start state
* (subrutine for WebRtcIlbcfix_StateSearch)
*---------------------------------------------------------------*/
void WebRtcIlbcfix_AbsQuant(
iLBC_Enc_Inst_t *iLBCenc_inst,
/* (i) Encoder instance */
iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits (outputs idxForMax
and idxVec, uses state_first as
input) */
WebRtc_Word16 *in, /* (i) vector to encode */
WebRtc_Word16 *weightDenum /* (i) denominator of synthesis filter */
);
#endif

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_AbsQuantLoop.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "sort_sq.h"
void WebRtcIlbcfix_AbsQuantLoop(
WebRtc_Word16 *syntOutIN,
WebRtc_Word16 *in_weightedIN,
WebRtc_Word16 *weightDenumIN,
WebRtc_Word16 *quantLenIN,
WebRtc_Word16 *idxVecIN
)
{
int n, k1, k2;
WebRtc_Word16 index;
WebRtc_Word32 toQW32;
WebRtc_Word32 toQ32;
WebRtc_Word16 tmp16a;
WebRtc_Word16 xq;
WebRtc_Word16 *syntOut = syntOutIN;
WebRtc_Word16 *in_weighted = in_weightedIN;
WebRtc_Word16 *weightDenum = weightDenumIN;
WebRtc_Word16 *quantLen = quantLenIN;
WebRtc_Word16 *idxVec = idxVecIN;
n=0;
for(k1=0;k1<2;k1++) {
for(k2=0;k2<quantLen[k1];k2++){
/* Filter to get the predicted value */
WebRtcSpl_FilterARFastQ12(
syntOut, syntOut,
weightDenum, LPC_FILTERORDER+1, 1);
/* the quantizer */
toQW32 = (WebRtc_Word32)(*in_weighted) - (WebRtc_Word32)(*syntOut);
toQ32 = (((WebRtc_Word32)toQW32)<<2);
if (toQ32 > 32767) {
toQ32 = (WebRtc_Word32) 32767;
} else if (toQ32 < -32768) {
toQ32 = (WebRtc_Word32) -32768;
}
/* Quantize the state */
if (toQW32<(-7577)) {
/* To prevent negative overflow */
index=0;
} else if (toQW32>8151) {
/* To prevent positive overflow */
index=7;
} else {
/* Find the best quantization index
(state_sq3Tbl is in Q13 and toQ is in Q11)
*/
WebRtcIlbcfix_SortSq(&xq, &index,
(WebRtc_Word16)toQ32,
WebRtcIlbcfix_kStateSq3, 8);
}
/* Store selected index */
(*idxVec++) = index;
/* Compute decoded sample and update of the prediction filter */
tmp16a = ((WebRtcIlbcfix_kStateSq3[index] + 2 ) >> 2);
*syntOut = (WebRtc_Word16) (tmp16a + (WebRtc_Word32)(*in_weighted) - toQW32);
n++;
syntOut++; in_weighted++;
}
/* Update perceptual weighting filter at subframe border */
weightDenum += 11;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_AbsQuantLoop.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
#include "defines.h"
/*----------------------------------------------------------------*
* predictive noise shaping encoding of scaled start state
* (subrutine for WebRtcIlbcfix_StateSearch)
*---------------------------------------------------------------*/
void WebRtcIlbcfix_AbsQuantLoop(
WebRtc_Word16 *syntOutIN,
WebRtc_Word16 *in_weightedIN,
WebRtc_Word16 *weightDenumIN,
WebRtc_Word16 *quantLenIN,
WebRtc_Word16 *idxVecIN
);
#endif

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_AugmentedCbCorr.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "augmented_cb_corr.h"
void WebRtcIlbcfix_AugmentedCbCorr(
WebRtc_Word16 *target, /* (i) Target vector */
WebRtc_Word16 *buffer, /* (i) Memory buffer */
WebRtc_Word16 *interpSamples, /* (i) buffer with
interpolated samples */
WebRtc_Word32 *crossDot, /* (o) The cross correlation between
the target and the Augmented
vector */
WebRtc_Word16 low, /* (i) Lag to start from (typically
20) */
WebRtc_Word16 high, /* (i) Lag to end at (typically 39) */
WebRtc_Word16 scale) /* (i) Scale factor to use for
the crossDot */
{
int lagcount;
WebRtc_Word16 ilow;
WebRtc_Word16 *targetPtr;
WebRtc_Word32 *crossDotPtr;
WebRtc_Word16 *iSPtr=interpSamples;
/* Calculate the correlation between the target and the
interpolated codebook. The correlation is calculated in
3 sections with the interpolated part in the middle */
crossDotPtr=crossDot;
for (lagcount=low; lagcount<=high; lagcount++) {
ilow = (WebRtc_Word16) (lagcount-4);
/* Compute dot product for the first (lagcount-4) samples */
(*crossDotPtr) = WebRtcSpl_DotProductWithScale(target, buffer-lagcount, ilow, scale);
/* Compute dot product on the interpolated samples */
(*crossDotPtr) += WebRtcSpl_DotProductWithScale(target+ilow, iSPtr, 4, scale);
targetPtr = target + lagcount;
iSPtr += lagcount-ilow;
/* Compute dot product for the remaining samples */
(*crossDotPtr) += WebRtcSpl_DotProductWithScale(targetPtr, buffer-lagcount, SUBL-lagcount, scale);
crossDotPtr++;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_AugmentedCbCorr.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Calculate correlation between target and Augmented codebooks
*---------------------------------------------------------------*/
void WebRtcIlbcfix_AugmentedCbCorr(
WebRtc_Word16 *target, /* (i) Target vector */
WebRtc_Word16 *buffer, /* (i) Memory buffer */
WebRtc_Word16 *interpSamples, /* (i) buffer with
interpolated samples */
WebRtc_Word32 *crossDot, /* (o) The cross correlation between
the target and the Augmented
vector */
WebRtc_Word16 low, /* (i) Lag to start from (typically
20) */
WebRtc_Word16 high, /* (i) Lag to end at (typically 39 */
WebRtc_Word16 scale); /* (i) Scale factor to use for
the crossDot */
#endif

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_BwExpand.c
******************************************************************/
#include "defines.h"
/*----------------------------------------------------------------*
* lpc bandwidth expansion
*---------------------------------------------------------------*/
/* The output is in the same domain as the input */
void WebRtcIlbcfix_BwExpand(
WebRtc_Word16 *out, /* (o) the bandwidth expanded lpc coefficients */
WebRtc_Word16 *in, /* (i) the lpc coefficients before bandwidth
expansion */
WebRtc_Word16 *coef, /* (i) the bandwidth expansion factor Q15 */
WebRtc_Word16 length /* (i) the length of lpc coefficient vectors */
) {
int i;
out[0] = in[0];
for (i = 1; i < length; i++) {
/* out[i] = coef[i] * in[i] with rounding.
in[] and out[] are in Q12 and coef[] is in Q15
*/
out[i] = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16(coef[i], in[i])+16384)>>15);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_BwExpand.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
#include "defines.h"
/*----------------------------------------------------------------*
* lpc bandwidth expansion
*---------------------------------------------------------------*/
void WebRtcIlbcfix_BwExpand(
WebRtc_Word16 *out, /* (o) the bandwidth expanded lpc coefficients */
WebRtc_Word16 *in, /* (i) the lpc coefficients before bandwidth
expansion */
WebRtc_Word16 *coef, /* (i) the bandwidth expansion factor Q15 */
WebRtc_Word16 length /* (i) the length of lpc coefficient vectors */
);
#endif

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbConstruct.c
******************************************************************/
#include "defines.h"
#include "gain_dequant.h"
#include "get_cd_vec.h"
/*----------------------------------------------------------------*
* Construct decoded vector from codebook and gains.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_CbConstruct(
WebRtc_Word16 *decvector, /* (o) Decoded vector */
WebRtc_Word16 *index, /* (i) Codebook indices */
WebRtc_Word16 *gain_index, /* (i) Gain quantization indices */
WebRtc_Word16 *mem, /* (i) Buffer for codevector construction */
WebRtc_Word16 lMem, /* (i) Length of buffer */
WebRtc_Word16 veclen /* (i) Length of vector */
){
int j;
WebRtc_Word16 gain[CB_NSTAGES];
/* Stack based */
WebRtc_Word16 cbvec0[SUBL];
WebRtc_Word16 cbvec1[SUBL];
WebRtc_Word16 cbvec2[SUBL];
WebRtc_Word32 a32;
WebRtc_Word16 *gainPtr;
/* gain de-quantization */
gain[0] = WebRtcIlbcfix_GainDequant(gain_index[0], 16384, 0);
gain[1] = WebRtcIlbcfix_GainDequant(gain_index[1], gain[0], 1);
gain[2] = WebRtcIlbcfix_GainDequant(gain_index[2], gain[1], 2);
/* codebook vector construction and construction of total vector */
/* Stack based */
WebRtcIlbcfix_GetCbVec(cbvec0, mem, index[0], lMem, veclen);
WebRtcIlbcfix_GetCbVec(cbvec1, mem, index[1], lMem, veclen);
WebRtcIlbcfix_GetCbVec(cbvec2, mem, index[2], lMem, veclen);
gainPtr = &gain[0];
for (j=0;j<veclen;j++) {
a32 = WEBRTC_SPL_MUL_16_16(*gainPtr++, cbvec0[j]);
a32 += WEBRTC_SPL_MUL_16_16(*gainPtr++, cbvec1[j]);
a32 += WEBRTC_SPL_MUL_16_16(*gainPtr, cbvec2[j]);
gainPtr -= 2;
decvector[j] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(a32 + 8192, 14);
}
return;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbConstruct.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Construct decoded vector from codebook and gains.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_CbConstruct(
WebRtc_Word16 *decvector, /* (o) Decoded vector */
WebRtc_Word16 *index, /* (i) Codebook indices */
WebRtc_Word16 *gain_index, /* (i) Gain quantization indices */
WebRtc_Word16 *mem, /* (i) Buffer for codevector construction */
WebRtc_Word16 lMem, /* (i) Length of buffer */
WebRtc_Word16 veclen /* (i) Length of vector */
);
#endif

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbMemEnergy.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "cb_mem_energy_calc.h"
/*----------------------------------------------------------------*
* Function WebRtcIlbcfix_CbMemEnergy computes the energy of all
* the vectors in the codebook memory that will be used in the
* following search for the best match.
*----------------------------------------------------------------*/
void WebRtcIlbcfix_CbMemEnergy(
WebRtc_Word16 range,
WebRtc_Word16 *CB, /* (i) The CB memory (1:st section) */
WebRtc_Word16 *filteredCB, /* (i) The filtered CB memory (2:nd section) */
WebRtc_Word16 lMem, /* (i) Length of the CB memory */
WebRtc_Word16 lTarget, /* (i) Length of the target vector */
WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */
WebRtc_Word16 *energyShifts, /* (o) Shift value of the energy */
WebRtc_Word16 scale, /* (i) The scaling of all energy values */
WebRtc_Word16 base_size /* (i) Index to where the energy values should be stored */
) {
WebRtc_Word16 *ppi, *ppo, *pp;
WebRtc_Word32 energy, tmp32;
/* Compute the energy and store it in a vector. Also the
* corresponding shift values are stored. The energy values
* are reused in all three stages. */
/* Calculate the energy in the first block of 'lTarget' sampels. */
ppi = CB+lMem-lTarget-1;
ppo = CB+lMem-1;
pp=CB+lMem-lTarget;
energy = WebRtcSpl_DotProductWithScale( pp, pp, lTarget, scale);
/* Normalize the energy and store the number of shifts */
energyShifts[0] = (WebRtc_Word16)WebRtcSpl_NormW32(energy);
tmp32 = WEBRTC_SPL_LSHIFT_W32(energy, energyShifts[0]);
energyW16[0] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 16);
/* Compute the energy of the rest of the cb memory
* by step wise adding and subtracting the next
* sample and the last sample respectively. */
WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, 0);
/* Next, precompute the energy values for the filtered cb section */
energy=0;
pp=filteredCB+lMem-lTarget;
energy = WebRtcSpl_DotProductWithScale( pp, pp, lTarget, scale);
/* Normalize the energy and store the number of shifts */
energyShifts[base_size] = (WebRtc_Word16)WebRtcSpl_NormW32(energy);
tmp32 = WEBRTC_SPL_LSHIFT_W32(energy, energyShifts[base_size]);
energyW16[base_size] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 16);
ppi = filteredCB + lMem - 1 - lTarget;
ppo = filteredCB + lMem - 1;
WebRtcIlbcfix_CbMemEnergyCalc(energy, range, ppi, ppo, energyW16, energyShifts, scale, base_size);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbMemEnergy.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
void WebRtcIlbcfix_CbMemEnergy(
WebRtc_Word16 range,
WebRtc_Word16 *CB, /* (i) The CB memory (1:st section) */
WebRtc_Word16 *filteredCB, /* (i) The filtered CB memory (2:nd section) */
WebRtc_Word16 lMem, /* (i) Length of the CB memory */
WebRtc_Word16 lTarget, /* (i) Length of the target vector */
WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */
WebRtc_Word16 *energyShifts, /* (o) Shift value of the energy */
WebRtc_Word16 scale, /* (i) The scaling of all energy values */
WebRtc_Word16 base_size /* (i) Index to where the energy values should be stored */
);
#endif

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbMemEnergyAugmentation.c
******************************************************************/
#include "defines.h"
#include "constants.h"
void WebRtcIlbcfix_CbMemEnergyAugmentation(
WebRtc_Word16 *interpSamples, /* (i) The interpolated samples */
WebRtc_Word16 *CBmem, /* (i) The CB memory */
WebRtc_Word16 scale, /* (i) The scaling of all energy values */
WebRtc_Word16 base_size, /* (i) Index to where the energy values should be stored */
WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */
WebRtc_Word16 *energyShifts /* (o) Shift value of the energy */
){
WebRtc_Word32 energy, tmp32;
WebRtc_Word16 *ppe, *pp, *interpSamplesPtr;
WebRtc_Word16 *CBmemPtr, lagcount;
WebRtc_Word16 *enPtr=&energyW16[base_size-20];
WebRtc_Word16 *enShPtr=&energyShifts[base_size-20];
WebRtc_Word32 nrjRecursive;
CBmemPtr = CBmem+147;
interpSamplesPtr = interpSamples;
/* Compute the energy for the first (low-5) noninterpolated samples */
nrjRecursive = WebRtcSpl_DotProductWithScale( CBmemPtr-19, CBmemPtr-19, 15, scale);
ppe = CBmemPtr - 20;
for (lagcount=20; lagcount<=39; lagcount++) {
/* Update the energy recursively to save complexity */
nrjRecursive = nrjRecursive +
WEBRTC_SPL_MUL_16_16_RSFT(*ppe, *ppe, scale);
ppe--;
energy = nrjRecursive;
/* interpolation */
energy += WebRtcSpl_DotProductWithScale(interpSamplesPtr, interpSamplesPtr, 4, scale);
interpSamplesPtr += 4;
/* Compute energy for the remaining samples */
pp = CBmemPtr - lagcount;
energy += WebRtcSpl_DotProductWithScale(pp, pp, SUBL-lagcount, scale);
/* Normalize the energy and store the number of shifts */
(*enShPtr) = (WebRtc_Word16)WebRtcSpl_NormW32(energy);
tmp32 = WEBRTC_SPL_LSHIFT_W32(energy, (*enShPtr));
(*enPtr) = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32, 16);
enShPtr++;
enPtr++;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbMemEnergyAugmentation.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
void WebRtcIlbcfix_CbMemEnergyAugmentation(
WebRtc_Word16 *interpSamples, /* (i) The interpolated samples */
WebRtc_Word16 *CBmem, /* (i) The CB memory */
WebRtc_Word16 scale, /* (i) The scaling of all energy values */
WebRtc_Word16 base_size, /* (i) Index to where the energy values should be stored */
WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */
WebRtc_Word16 *energyShifts /* (o) Shift value of the energy */
);
#endif

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbMemEnergyCalc.c
******************************************************************/
#include "defines.h"
/* Compute the energy of the rest of the cb memory
* by step wise adding and subtracting the next
* sample and the last sample respectively */
void WebRtcIlbcfix_CbMemEnergyCalc(
WebRtc_Word32 energy, /* (i) input start energy */
WebRtc_Word16 range, /* (i) number of iterations */
WebRtc_Word16 *ppi, /* (i) input pointer 1 */
WebRtc_Word16 *ppo, /* (i) input pointer 2 */
WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */
WebRtc_Word16 *energyShifts, /* (o) Shift value of the energy */
WebRtc_Word16 scale, /* (i) The scaling of all energy values */
WebRtc_Word16 base_size /* (i) Index to where the energy values should be stored */
)
{
WebRtc_Word16 j,shft;
WebRtc_Word32 tmp;
WebRtc_Word16 *eSh_ptr;
WebRtc_Word16 *eW16_ptr;
eSh_ptr = &energyShifts[1+base_size];
eW16_ptr = &energyW16[1+base_size];
for(j=0;j<range-1;j++) {
/* Calculate next energy by a +/-
operation on the edge samples */
tmp = WEBRTC_SPL_MUL_16_16(*ppi, *ppi);
tmp -= WEBRTC_SPL_MUL_16_16(*ppo, *ppo);
energy += WEBRTC_SPL_RSHIFT_W32(tmp, scale);
energy = WEBRTC_SPL_MAX(energy, 0);
ppi--;
ppo--;
/* Normalize the energy into a WebRtc_Word16 and store
the number of shifts */
shft = (WebRtc_Word16)WebRtcSpl_NormW32(energy);
*eSh_ptr++ = shft;
tmp = WEBRTC_SPL_LSHIFT_W32(energy, shft);
*eW16_ptr++ = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp, 16);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbMemEnergyCalc.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
void WebRtcIlbcfix_CbMemEnergyCalc(
WebRtc_Word32 energy, /* (i) input start energy */
WebRtc_Word16 range, /* (i) number of iterations */
WebRtc_Word16 *ppi, /* (i) input pointer 1 */
WebRtc_Word16 *ppo, /* (i) input pointer 2 */
WebRtc_Word16 *energyW16, /* (o) Energy in the CB vectors */
WebRtc_Word16 *energyShifts, /* (o) Shift value of the energy */
WebRtc_Word16 scale, /* (i) The scaling of all energy values */
WebRtc_Word16 base_size /* (i) Index to where the energy values should be stored */
);
#endif

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbSearch.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
void WebRtcIlbcfix_CbSearch(
iLBC_Enc_Inst_t *iLBCenc_inst,
/* (i) the encoder state structure */
WebRtc_Word16 *index, /* (o) Codebook indices */
WebRtc_Word16 *gain_index, /* (o) Gain quantization indices */
WebRtc_Word16 *intarget, /* (i) Target vector for encoding */
WebRtc_Word16 *decResidual,/* (i) Decoded residual for codebook construction */
WebRtc_Word16 lMem, /* (i) Length of buffer */
WebRtc_Word16 lTarget, /* (i) Length of vector */
WebRtc_Word16 *weightDenum,/* (i) weighting filter coefficients in Q12 */
WebRtc_Word16 block /* (i) the subblock number */
);
#endif

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbSearchCore.c
******************************************************************/
#include "defines.h"
#include "constants.h"
void WebRtcIlbcfix_CbSearchCore(
WebRtc_Word32 *cDot, /* (i) Cross Correlation */
WebRtc_Word16 range, /* (i) Search range */
WebRtc_Word16 stage, /* (i) Stage of this search */
WebRtc_Word16 *inverseEnergy, /* (i) Inversed energy */
WebRtc_Word16 *inverseEnergyShift, /* (i) Shifts of inversed energy
with the offset 2*16-29 */
WebRtc_Word32 *Crit, /* (o) The criteria */
WebRtc_Word16 *bestIndex, /* (o) Index that corresponds to
maximum criteria (in this
vector) */
WebRtc_Word32 *bestCrit, /* (o) Value of critera for the
chosen index */
WebRtc_Word16 *bestCritSh) /* (o) The domain of the chosen
criteria */
{
WebRtc_Word32 maxW32, tmp32;
WebRtc_Word16 max, sh, tmp16;
int i;
WebRtc_Word32 *cDotPtr;
WebRtc_Word16 cDotSqW16;
WebRtc_Word16 *inverseEnergyPtr;
WebRtc_Word32 *critPtr;
WebRtc_Word16 *inverseEnergyShiftPtr;
/* Don't allow negative values for stage 0 */
if (stage==0) {
cDotPtr=cDot;
for (i=0;i<range;i++) {
*cDotPtr=WEBRTC_SPL_MAX(0, (*cDotPtr));
cDotPtr++;
}
}
/* Normalize cDot to WebRtc_Word16, calculate the square of cDot and store the upper WebRtc_Word16 */
maxW32 = WebRtcSpl_MaxAbsValueW32(cDot, range);
sh = (WebRtc_Word16)WebRtcSpl_NormW32(maxW32);
cDotPtr = cDot;
inverseEnergyPtr = inverseEnergy;
critPtr = Crit;
inverseEnergyShiftPtr=inverseEnergyShift;
max=WEBRTC_SPL_WORD16_MIN;
for (i=0;i<range;i++) {
/* Calculate cDot*cDot and put the result in a WebRtc_Word16 */
tmp32 = WEBRTC_SPL_LSHIFT_W32(*cDotPtr,sh);
tmp16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32,16);
cDotSqW16 = (WebRtc_Word16)(((WebRtc_Word32)(tmp16)*(tmp16))>>16);
/* Calculate the criteria (cDot*cDot/energy) */
*critPtr=WEBRTC_SPL_MUL_16_16(cDotSqW16, (*inverseEnergyPtr));
/* Extract the maximum shift value under the constraint
that the criteria is not zero */
if ((*critPtr)!=0) {
max = WEBRTC_SPL_MAX((*inverseEnergyShiftPtr), max);
}
inverseEnergyPtr++;
inverseEnergyShiftPtr++;
critPtr++;
cDotPtr++;
}
/* If no max shifts still at initialization value, set shift to zero */
if (max==WEBRTC_SPL_WORD16_MIN) {
max = 0;
}
/* Modify the criterias, so that all of them use the same Q domain */
critPtr=Crit;
inverseEnergyShiftPtr=inverseEnergyShift;
for (i=0;i<range;i++) {
/* Guarantee that the shift value is less than 16
in order to simplify for DSP's (and guard against >31) */
tmp16 = WEBRTC_SPL_MIN(16, max-(*inverseEnergyShiftPtr));
(*critPtr)=WEBRTC_SPL_SHIFT_W32((*critPtr),-tmp16);
critPtr++;
inverseEnergyShiftPtr++;
}
/* Find the index of the best value */
*bestIndex = WebRtcSpl_MaxIndexW32(Crit, range);
*bestCrit = Crit[*bestIndex];
/* Calculate total shifts of this criteria */
*bestCritSh = 32 - 2*sh + max;
return;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbSearchCore.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
#include "defines.h"
void WebRtcIlbcfix_CbSearchCore(
WebRtc_Word32 *cDot, /* (i) Cross Correlation */
WebRtc_Word16 range, /* (i) Search range */
WebRtc_Word16 stage, /* (i) Stage of this search */
WebRtc_Word16 *inverseEnergy, /* (i) Inversed energy */
WebRtc_Word16 *inverseEnergyShift, /* (i) Shifts of inversed energy
with the offset 2*16-29 */
WebRtc_Word32 *Crit, /* (o) The criteria */
WebRtc_Word16 *bestIndex, /* (o) Index that corresponds to
maximum criteria (in this
vector) */
WebRtc_Word32 *bestCrit, /* (o) Value of critera for the
chosen index */
WebRtc_Word16 *bestCritSh); /* (o) The domain of the chosen
criteria */
#endif

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbUpdateBestIndex.c
******************************************************************/
#include "defines.h"
#include "cb_update_best_index.h"
#include "constants.h"
void WebRtcIlbcfix_CbUpdateBestIndex(
WebRtc_Word32 CritNew, /* (i) New Potentially best Criteria */
WebRtc_Word16 CritNewSh, /* (i) Shift value of above Criteria */
WebRtc_Word16 IndexNew, /* (i) Index of new Criteria */
WebRtc_Word32 cDotNew, /* (i) Cross dot of new index */
WebRtc_Word16 invEnergyNew, /* (i) Inversed energy new index */
WebRtc_Word16 energyShiftNew, /* (i) Energy shifts of new index */
WebRtc_Word32 *CritMax, /* (i/o) Maximum Criteria (so far) */
WebRtc_Word16 *shTotMax, /* (i/o) Shifts of maximum criteria */
WebRtc_Word16 *bestIndex, /* (i/o) Index that corresponds to
maximum criteria */
WebRtc_Word16 *bestGain) /* (i/o) Gain in Q14 that corresponds
to maximum criteria */
{
WebRtc_Word16 shOld, shNew, tmp16;
WebRtc_Word16 scaleTmp;
WebRtc_Word32 gainW32;
/* Normalize the new and old Criteria to the same domain */
if (CritNewSh>(*shTotMax)) {
shOld=WEBRTC_SPL_MIN(31,CritNewSh-(*shTotMax));
shNew=0;
} else {
shOld=0;
shNew=WEBRTC_SPL_MIN(31,(*shTotMax)-CritNewSh);
}
/* Compare the two criterias. If the new one is better,
calculate the gain and store this index as the new best one
*/
if (WEBRTC_SPL_RSHIFT_W32(CritNew, shNew)>
WEBRTC_SPL_RSHIFT_W32((*CritMax),shOld)) {
tmp16 = (WebRtc_Word16)WebRtcSpl_NormW32(cDotNew);
tmp16 = 16 - tmp16;
/* Calculate the gain in Q14
Compensate for inverseEnergyshift in Q29 and that the energy
value was stored in a WebRtc_Word16 (shifted down 16 steps)
=> 29-14+16 = 31 */
scaleTmp = -energyShiftNew-tmp16+31;
scaleTmp = WEBRTC_SPL_MIN(31, scaleTmp);
gainW32 = WEBRTC_SPL_MUL_16_16_RSFT(
((WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(cDotNew, -tmp16)), invEnergyNew, scaleTmp);
/* Check if criteria satisfies Gain criteria (max 1.3)
if it is larger set the gain to 1.3
(slightly different from FLP version)
*/
if (gainW32>21299) {
*bestGain=21299;
} else if (gainW32<-21299) {
*bestGain=-21299;
} else {
*bestGain=(WebRtc_Word16)gainW32;
}
*CritMax=CritNew;
*shTotMax=CritNewSh;
*bestIndex = IndexNew;
}
return;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbUpdateBestIndex.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
#include "defines.h"
void WebRtcIlbcfix_CbUpdateBestIndex(
WebRtc_Word32 CritNew, /* (i) New Potentially best Criteria */
WebRtc_Word16 CritNewSh, /* (i) Shift value of above Criteria */
WebRtc_Word16 IndexNew, /* (i) Index of new Criteria */
WebRtc_Word32 cDotNew, /* (i) Cross dot of new index */
WebRtc_Word16 invEnergyNew, /* (i) Inversed energy new index */
WebRtc_Word16 energyShiftNew, /* (i) Energy shifts of new index */
WebRtc_Word32 *CritMax, /* (i/o) Maximum Criteria (so far) */
WebRtc_Word16 *shTotMax, /* (i/o) Shifts of maximum criteria */
WebRtc_Word16 *bestIndex, /* (i/o) Index that corresponds to
maximum criteria */
WebRtc_Word16 *bestGain); /* (i/o) Gain in Q14 that corresponds
to maximum criteria */
#endif

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Chebyshev.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*------------------------------------------------------------------*
* Calculate the Chevyshev polynomial series
* F(w) = 2*exp(-j5w)*C(x)
* C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
* T_i(x) is the i:th order Chebyshev polynomial
*------------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_Chebyshev(
/* (o) Result of C(x) */
WebRtc_Word16 x, /* (i) Value to the Chevyshev polynomial */
WebRtc_Word16 *f /* (i) The coefficients in the polynomial */
) {
WebRtc_Word16 b1_high, b1_low; /* Use the high, low format to increase the accuracy */
WebRtc_Word32 b2;
WebRtc_Word32 tmp1W32;
WebRtc_Word32 tmp2W32;
int i;
b2 = (WebRtc_Word32)0x1000000; /* b2 = 1.0 (Q23) */
/* Calculate b1 = 2*x + f[1] */
tmp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)x, 10);
tmp1W32 += WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)f[1], 14);
for (i = 2; i < 5; i++) {
tmp2W32 = tmp1W32;
/* Split b1 (in tmp1W32) into a high and low part */
b1_high = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32, 16);
b1_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32-WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)b1_high),16), 1);
/* Calculate 2*x*b1-b2+f[i] */
tmp1W32 = WEBRTC_SPL_LSHIFT_W32( (WEBRTC_SPL_MUL_16_16(b1_high, x) +
WEBRTC_SPL_MUL_16_16_RSFT(b1_low, x, 15)), 2);
tmp1W32 -= b2;
tmp1W32 += WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)f[i], 14);
/* Update b2 for next round */
b2 = tmp2W32;
}
/* Split b1 (in tmp1W32) into a high and low part */
b1_high = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32, 16);
b1_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32-WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)b1_high),16), 1);
/* tmp1W32 = x*b1 - b2 + f[i]/2 */
tmp1W32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(b1_high, x), 1) +
WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16_RSFT(b1_low, x, 15), 1);
tmp1W32 -= b2;
tmp1W32 += WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)f[i], 13);
/* Handle overflows and set to maximum or minimum WebRtc_Word16 instead */
if (tmp1W32>((WebRtc_Word32)33553408)) {
return(WEBRTC_SPL_WORD16_MAX);
} else if (tmp1W32<((WebRtc_Word32)-33554432)) {
return(WEBRTC_SPL_WORD16_MIN);
} else {
return((WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32, 10));
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Chebyshev.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
#include "defines.h"
/*------------------------------------------------------------------*
* Calculate the Chevyshev polynomial series
* F(w) = 2*exp(-j5w)*C(x)
* C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
* T_i(x) is the i:th order Chebyshev polynomial
*------------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_Chebyshev(
/* (o) Result of C(x) */
WebRtc_Word16 x, /* (i) Value to the Chevyshev polynomial */
WebRtc_Word16 *f /* (i) The coefficients in the polynomial */
);
#endif

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CompCorr.c
******************************************************************/
#include "defines.h"
/*----------------------------------------------------------------*
* Compute cross correlation and pitch gain for pitch prediction
* of last subframe at given lag.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_CompCorr(
WebRtc_Word32 *corr, /* (o) cross correlation */
WebRtc_Word32 *ener, /* (o) energy */
WebRtc_Word16 *buffer, /* (i) signal buffer */
WebRtc_Word16 lag, /* (i) pitch lag */
WebRtc_Word16 bLen, /* (i) length of buffer */
WebRtc_Word16 sRange, /* (i) correlation search length */
WebRtc_Word16 scale /* (i) number of rightshifts to use */
){
WebRtc_Word16 *w16ptr;
w16ptr=&buffer[bLen-sRange-lag];
/* Calculate correlation and energy */
(*corr)=WebRtcSpl_DotProductWithScale(&buffer[bLen-sRange], w16ptr, sRange, scale);
(*ener)=WebRtcSpl_DotProductWithScale(w16ptr, w16ptr, sRange, scale);
/* For zero energy set the energy to 0 in order to avoid potential
problems for coming divisions */
if (*ener == 0) {
*corr = 0;
*ener = 1;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CompCorr.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Compute cross correlation and pitch gain for pitch prediction
* of last subframe at given lag.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_CompCorr(
WebRtc_Word32 *corr, /* (o) cross correlation */
WebRtc_Word32 *ener, /* (o) energy */
WebRtc_Word16 *buffer, /* (i) signal buffer */
WebRtc_Word16 lag, /* (i) pitch lag */
WebRtc_Word16 bLen, /* (i) length of buffer */
WebRtc_Word16 sRange, /* (i) correlation search length */
WebRtc_Word16 scale /* (i) number of rightshifts to use */
);
#endif

View File

@@ -0,0 +1,49 @@
clear;
pack;
%
% Enter the path to YOUR executable and remember to define the perprocessor
% variable PRINT_MIPS te get the instructions printed to the screen.
%
command = '!iLBCtest.exe 30 speechAndBGnoise.pcm out1.bit out1.pcm tlm10_30ms.dat';
cout=' > st.txt'; %saves to matlab variable 'st'
eval(strcat(command,cout));
if(length(cout)>3)
load st.txt
else
disp('No cout file to load')
end
% initialize vector to zero
index = find(st(1:end,1)==-1);
indexnonzero = find(st(1:end,1)>0);
frames = length(index)-indexnonzero(1)+1;
start = indexnonzero(1) - 1;
functionOrder=max(st(:,2));
new=zeros(frames,functionOrder);
for i = 1:frames,
for j = index(start-1+i)+1:(index(start+i)-1),
new(i,st(j,2)) = new(i,st(j,2)) + st(j,1);
end
end
result=zeros(functionOrder,3);
for i=1:functionOrder
nonzeroelements = find(new(1:end,i)>0);
result(i,1)=i;
% Compute each function's mean complexity
% result(i,2)=(sum(new(nonzeroelements,i))/(length(nonzeroelements)*0.03))/1000000;
% Compute each function's maximum complexity in encoding
% and decoding respectively and then add it together:
% result(i,3)=(max(new(1:end,i))/0.03)/1000000;
result(i,3)=(max(new(1:size(new,1)/2,i))/0.03)/1000000 + (max(new(size(new,1)/2+1:end,i))/0.03)/1000000;
end
result
% Compute maximum complexity for a single frame (enc/dec separately and together)
maxEncComplexityInAFrame = (max(sum(new(1:size(new,1)/2,:),2))/0.03)/1000000
maxDecComplexityInAFrame = (max(sum(new(size(new,1)/2+1:end,:),2))/0.03)/1000000
totalComplexity = maxEncComplexityInAFrame + maxDecComplexityInAFrame

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
constants.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
#include "defines.h"
#include "typedefs.h"
/* high pass filters */
extern const WebRtc_Word16 WebRtcIlbcfix_kHpInCoefs[];
extern const WebRtc_Word16 WebRtcIlbcfix_kHpOutCoefs[];
/* Window for start state decision */
extern const WebRtc_Word16 WebRtcIlbcfix_kStartSequenceEnrgWin[];
/* low pass filter used for downsampling */
extern const WebRtc_Word16 WebRtcIlbcfix_kLpFiltCoefs[];
/* LPC analysis and quantization */
extern const WebRtc_Word16 WebRtcIlbcfix_kLpcWin[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLpcAsymWin[];
extern const WebRtc_Word32 WebRtcIlbcfix_kLpcLagWin[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLpcChirpSyntDenum[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLpcChirpWeightDenum[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLsfDimCb[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLsfSizeCb[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLsfCb[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLsfWeight20ms[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLsfWeight30ms[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLsfMean[];
extern const WebRtc_Word16 WebRtcIlbcfix_kLspMean[];
extern const WebRtc_Word16 WebRtcIlbcfix_kCos[];
extern const WebRtc_Word16 WebRtcIlbcfix_kCosDerivative[];
extern const WebRtc_Word16 WebRtcIlbcfix_kCosGrid[];
extern const WebRtc_Word16 WebRtcIlbcfix_kAcosDerivative[];
/* state quantization tables */
extern const WebRtc_Word16 WebRtcIlbcfix_kStateSq3[];
extern const WebRtc_Word32 WebRtcIlbcfix_kChooseFrgQuant[];
extern const WebRtc_Word16 WebRtcIlbcfix_kScale[];
extern const WebRtc_Word16 WebRtcIlbcfix_kFrgQuantMod[];
/* Ranges for search and filters at different subframes */
extern const WebRtc_Word16 WebRtcIlbcfix_kSearchRange[5][CB_NSTAGES];
extern const WebRtc_Word16 WebRtcIlbcfix_kFilterRange[];
/* gain quantization tables */
extern const WebRtc_Word16 WebRtcIlbcfix_kGainSq3[];
extern const WebRtc_Word16 WebRtcIlbcfix_kGainSq4[];
extern const WebRtc_Word16 WebRtcIlbcfix_kGainSq5[];
extern const WebRtc_Word16 WebRtcIlbcfix_kGainSq5Sq[];
extern const WebRtc_Word16* const WebRtcIlbcfix_kGain[];
/* adaptive codebook definitions */
extern const WebRtc_Word16 WebRtcIlbcfix_kCbFiltersRev[];
extern const WebRtc_Word16 WebRtcIlbcfix_kAlpha[];
/* enhancer definitions */
extern const WebRtc_Word16 WebRtcIlbcfix_kEnhPolyPhaser[ENH_UPS0][ENH_FLO_MULT2_PLUS1];
extern const WebRtc_Word16 WebRtcIlbcfix_kEnhWt[];
extern const WebRtc_Word16 WebRtcIlbcfix_kEnhPlocs[];
/* PLC tables */
extern const WebRtc_Word16 WebRtcIlbcfix_kPlcPerSqr[];
extern const WebRtc_Word16 WebRtcIlbcfix_kPlcPitchFact[];
extern const WebRtc_Word16 WebRtcIlbcfix_kPlcPfSlope[];
#endif

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CreateAugmentedVec.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* Recreate a specific codebook vector from the augmented part.
*
*----------------------------------------------------------------*/
void WebRtcIlbcfix_CreateAugmentedVec(
WebRtc_Word16 index, /* (i) Index for the augmented vector to be created */
WebRtc_Word16 *buffer, /* (i) Pointer to the end of the codebook memory that
is used for creation of the augmented codebook */
WebRtc_Word16 *cbVec /* (o) The construced codebook vector */
) {
WebRtc_Word16 ilow;
WebRtc_Word16 *ppo, *ppi;
WebRtc_Word16 cbVecTmp[4];
ilow = index-4;
/* copy the first noninterpolated part */
ppo = buffer-index;
WEBRTC_SPL_MEMCPY_W16(cbVec, ppo, index);
/* interpolation */
ppo = buffer - 4;
ppi = buffer - index - 4;
/* perform cbVec[ilow+k] = ((ppi[k]*alphaTbl[k])>>15) + ((ppo[k]*alphaTbl[3-k])>>15);
for k = 0..3
*/
WebRtcSpl_ElementwiseVectorMult(&cbVec[ilow], ppi, WebRtcIlbcfix_kAlpha, 4, 15);
WebRtcSpl_ReverseOrderMultArrayElements(cbVecTmp, ppo, &WebRtcIlbcfix_kAlpha[3], 4, 15);
WebRtcSpl_AddVectorsAndShift(&cbVec[ilow], &cbVec[ilow], cbVecTmp, 4, 0);
/* copy the second noninterpolated part */
ppo = buffer - index;
WEBRTC_SPL_MEMCPY_W16(cbVec+index,ppo,(SUBL-index));
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CreateAugmentedVec.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Recreate a specific codebook vector from the augmented part.
*
*----------------------------------------------------------------*/
void WebRtcIlbcfix_CreateAugmentedVec(
WebRtc_Word16 index, /* (i) Index for the augmented vector to be created */
WebRtc_Word16 *buffer, /* (i) Pointer to the end of the codebook memory that
is used for creation of the augmented codebook */
WebRtc_Word16 *cbVec /* (o) The construced codebook vector */
);
#endif

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Decode.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
#include "defines.h"
/*----------------------------------------------------------------*
* main decoder function
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DecodeImpl(
WebRtc_Word16 *decblock, /* (o) decoded signal block */
WebRtc_UWord16 *bytes, /* (i) encoded signal bits */
iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state
structure */
WebRtc_Word16 mode /* (i) 0: bad packet, PLC,
1: normal */
);
#endif

View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_DecodeResidual.c
******************************************************************/
#include "defines.h"
#include "state_construct.h"
#include "cb_construct.h"
#include "index_conv_dec.h"
#include "do_plc.h"
#include "constants.h"
#include "enhancer_interface.h"
#include "xcorr_coef.h"
#include "lsf_check.h"
/*----------------------------------------------------------------*
* frame residual decoder function (subrutine to iLBC_decode)
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DecodeResidual(
iLBC_Dec_Inst_t *iLBCdec_inst,
/* (i/o) the decoder state structure */
iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used
for the decoding */
WebRtc_Word16 *decresidual, /* (o) decoded residual frame */
WebRtc_Word16 *syntdenum /* (i) the decoded synthesis filter
coefficients */
) {
WebRtc_Word16 meml_gotten, Nfor, Nback, diff, start_pos;
WebRtc_Word16 subcount, subframe;
WebRtc_Word16 *reverseDecresidual = iLBCdec_inst->enh_buf; /* Reversed decoded data, used for decoding backwards in time (reuse memory in state) */
WebRtc_Word16 *memVec = iLBCdec_inst->prevResidual; /* Memory for codebook and filter state (reuse memory in state) */
WebRtc_Word16 *mem = &memVec[CB_HALFFILTERLEN]; /* Memory for codebook */
diff = STATE_LEN - iLBCdec_inst->state_short_len;
if (iLBC_encbits->state_first == 1) {
start_pos = (iLBC_encbits->startIdx-1)*SUBL;
} else {
start_pos = (iLBC_encbits->startIdx-1)*SUBL + diff;
}
/* decode scalar part of start state */
WebRtcIlbcfix_StateConstruct(iLBC_encbits->idxForMax,
iLBC_encbits->idxVec, &syntdenum[(iLBC_encbits->startIdx-1)*(LPC_FILTERORDER+1)],
&decresidual[start_pos], iLBCdec_inst->state_short_len
);
if (iLBC_encbits->state_first) { /* put adaptive part in the end */
/* setup memory */
WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-iLBCdec_inst->state_short_len));
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCdec_inst->state_short_len, decresidual+start_pos,
iLBCdec_inst->state_short_len);
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(
&decresidual[start_pos+iLBCdec_inst->state_short_len],
iLBC_encbits->cb_index, iLBC_encbits->gain_index,
mem+CB_MEML-ST_MEM_L_TBL,
ST_MEM_L_TBL, (WebRtc_Word16)diff
);
}
else {/* put adaptive part in the beginning */
/* create reversed vectors for prediction */
WebRtcSpl_MemCpyReversedOrder(reverseDecresidual+diff,
&decresidual[(iLBC_encbits->startIdx+1)*SUBL-1-STATE_LEN], diff);
/* setup memory */
meml_gotten = iLBCdec_inst->state_short_len;
WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
decresidual+start_pos, meml_gotten);
WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-meml_gotten));
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(
reverseDecresidual,
iLBC_encbits->cb_index, iLBC_encbits->gain_index,
mem+CB_MEML-ST_MEM_L_TBL,
ST_MEM_L_TBL, diff
);
/* get decoded residual from reversed vector */
WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1],
reverseDecresidual, diff);
}
/* counter for predicted subframes */
subcount=1;
/* forward prediction of subframes */
Nfor = iLBCdec_inst->nsub-iLBC_encbits->startIdx-1;
if( Nfor > 0 ) {
/* setup memory */
WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
decresidual+(iLBC_encbits->startIdx-1)*SUBL, STATE_LEN);
/* loop over subframes to encode */
for (subframe=0; subframe<Nfor; subframe++) {
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(
&decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL],
iLBC_encbits->cb_index+subcount*CB_NSTAGES,
iLBC_encbits->gain_index+subcount*CB_NSTAGES,
mem, MEM_LF_TBL, SUBL
);
/* update memory */
WEBRTC_SPL_MEMMOVE_W16(mem, mem+SUBL, CB_MEML-SUBL);
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
&decresidual[(iLBC_encbits->startIdx+1+subframe)*SUBL], SUBL);
subcount++;
}
}
/* backward prediction of subframes */
Nback = iLBC_encbits->startIdx-1;
if( Nback > 0 ){
/* setup memory */
meml_gotten = SUBL*(iLBCdec_inst->nsub+1-iLBC_encbits->startIdx);
if( meml_gotten > CB_MEML ) {
meml_gotten=CB_MEML;
}
WebRtcSpl_MemCpyReversedOrder(mem+CB_MEML-1,
decresidual+(iLBC_encbits->startIdx-1)*SUBL, meml_gotten);
WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-meml_gotten));
/* loop over subframes to decode */
for (subframe=0; subframe<Nback; subframe++) {
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(
&reverseDecresidual[subframe*SUBL],
iLBC_encbits->cb_index+subcount*CB_NSTAGES,
iLBC_encbits->gain_index+subcount*CB_NSTAGES,
mem, MEM_LF_TBL, SUBL
);
/* update memory */
WEBRTC_SPL_MEMMOVE_W16(mem, mem+SUBL, CB_MEML-SUBL);
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
&reverseDecresidual[subframe*SUBL], SUBL);
subcount++;
}
/* get decoded residual from reversed vector */
WebRtcSpl_MemCpyReversedOrder(decresidual+SUBL*Nback-1,
reverseDecresidual, SUBL*Nback);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_DecodeResidual.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
#include "defines.h"
/*----------------------------------------------------------------*
* frame residual decoder function (subrutine to iLBC_decode)
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DecodeResidual(
iLBC_Dec_Inst_t *iLBCdec_inst,
/* (i/o) the decoder state structure */
iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used
for the decoding */
WebRtc_Word16 *decresidual, /* (o) decoded residual frame */
WebRtc_Word16 *syntdenum /* (i) the decoded synthesis filter
coefficients */
);
#endif

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_DecoderInterpolateLsp.c
******************************************************************/
#include "lsf_interpolate_to_poly_dec.h"
#include "bw_expand.h"
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* obtain synthesis and weighting filters form lsf coefficients
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DecoderInterpolateLsp(
WebRtc_Word16 *syntdenum, /* (o) synthesis filter coefficients */
WebRtc_Word16 *weightdenum, /* (o) weighting denumerator
coefficients */
WebRtc_Word16 *lsfdeq, /* (i) dequantized lsf coefficients */
WebRtc_Word16 length, /* (i) length of lsf coefficient vector */
iLBC_Dec_Inst_t *iLBCdec_inst
/* (i) the decoder state structure */
){
int i, pos, lp_length;
WebRtc_Word16 lp[LPC_FILTERORDER + 1], *lsfdeq2;
lsfdeq2 = lsfdeq + length;
lp_length = length + 1;
if (iLBCdec_inst->mode==30) {
/* subframe 1: Interpolation between old and first LSF */
WebRtcIlbcfix_LspInterpolate2PolyDec(lp, (*iLBCdec_inst).lsfdeqold, lsfdeq,
WebRtcIlbcfix_kLsfWeight30ms[0], length);
WEBRTC_SPL_MEMCPY_W16(syntdenum,lp,lp_length);
WebRtcIlbcfix_BwExpand(weightdenum, lp, (WebRtc_Word16*)WebRtcIlbcfix_kLpcChirpSyntDenum, (WebRtc_Word16)lp_length);
/* subframes 2 to 6: interpolation between first and last LSF */
pos = lp_length;
for (i = 1; i < 6; i++) {
WebRtcIlbcfix_LspInterpolate2PolyDec(lp, lsfdeq, lsfdeq2,
WebRtcIlbcfix_kLsfWeight30ms[i], length);
WEBRTC_SPL_MEMCPY_W16(syntdenum + pos,lp,lp_length);
WebRtcIlbcfix_BwExpand(weightdenum + pos, lp,
(WebRtc_Word16*)WebRtcIlbcfix_kLpcChirpSyntDenum, (WebRtc_Word16)lp_length);
pos += lp_length;
}
} else { /* iLBCdec_inst->mode=20 */
/* subframes 1 to 4: interpolation between old and new LSF */
pos = 0;
for (i = 0; i < iLBCdec_inst->nsub; i++) {
WebRtcIlbcfix_LspInterpolate2PolyDec(lp, iLBCdec_inst->lsfdeqold, lsfdeq,
WebRtcIlbcfix_kLsfWeight20ms[i], length);
WEBRTC_SPL_MEMCPY_W16(syntdenum+pos,lp,lp_length);
WebRtcIlbcfix_BwExpand(weightdenum+pos, lp,
(WebRtc_Word16*)WebRtcIlbcfix_kLpcChirpSyntDenum, (WebRtc_Word16)lp_length);
pos += lp_length;
}
}
/* update memory */
if (iLBCdec_inst->mode==30) {
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, lsfdeq2, length);
} else {
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->lsfdeqold, lsfdeq, length);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_DecoderInterpolateLsp.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
#include "defines.h"
/*----------------------------------------------------------------*
* obtain synthesis and weighting filters form lsf coefficients
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DecoderInterpolateLsp(
WebRtc_Word16 *syntdenum, /* (o) synthesis filter coefficients */
WebRtc_Word16 *weightdenum, /* (o) weighting denumerator
coefficients */
WebRtc_Word16 *lsfdeq, /* (i) dequantized lsf coefficients */
WebRtc_Word16 length, /* (i) length of lsf coefficient vector */
iLBC_Dec_Inst_t *iLBCdec_inst
/* (i) the decoder state structure */
);
#endif

View File

@@ -0,0 +1,219 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
define.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
#include "typedefs.h"
#include "signal_processing_library.h"
#include <string.h>
/* general codec settings */
#define FS 8000
#define BLOCKL_20MS 160
#define BLOCKL_30MS 240
#define BLOCKL_MAX 240
#define NSUB_20MS 4
#define NSUB_30MS 6
#define NSUB_MAX 6
#define NASUB_20MS 2
#define NASUB_30MS 4
#define NASUB_MAX 4
#define SUBL 40
#define STATE_LEN 80
#define STATE_SHORT_LEN_30MS 58
#define STATE_SHORT_LEN_20MS 57
/* LPC settings */
#define LPC_FILTERORDER 10
#define LPC_LOOKBACK 60
#define LPC_N_20MS 1
#define LPC_N_30MS 2
#define LPC_N_MAX 2
#define LPC_ASYMDIFF 20
#define LSF_NSPLIT 3
#define LSF_NUMBER_OF_STEPS 4
#define LPC_HALFORDER 5
#define COS_GRID_POINTS 60
/* cb settings */
#define CB_NSTAGES 3
#define CB_EXPAND 2
#define CB_MEML 147
#define CB_FILTERLEN (2*4)
#define CB_HALFFILTERLEN 4
#define CB_RESRANGE 34
#define CB_MAXGAIN_FIXQ6 83 /* error = -0.24% */
#define CB_MAXGAIN_FIXQ14 21299
/* enhancer */
#define ENH_BLOCKL 80 /* block length */
#define ENH_BLOCKL_HALF (ENH_BLOCKL/2)
#define ENH_HL 3 /* 2*ENH_HL+1 is number blocks
in said second sequence */
#define ENH_SLOP 2 /* max difference estimated and
correct pitch period */
#define ENH_PLOCSL 8 /* pitch-estimates and
pitch-locations buffer length */
#define ENH_OVERHANG 2
#define ENH_UPS0 4 /* upsampling rate */
#define ENH_FL0 3 /* 2*FLO+1 is the length of each filter */
#define ENH_FLO_MULT2_PLUS1 7
#define ENH_VECTL (ENH_BLOCKL+2*ENH_FL0)
#define ENH_CORRDIM (2*ENH_SLOP+1)
#define ENH_NBLOCKS (BLOCKL/ENH_BLOCKL)
#define ENH_NBLOCKS_EXTRA 5
#define ENH_NBLOCKS_TOT 8 /* ENH_NBLOCKS+ENH_NBLOCKS_EXTRA */
#define ENH_BUFL (ENH_NBLOCKS_TOT)*ENH_BLOCKL
#define ENH_BUFL_FILTEROVERHEAD 3
#define ENH_A0 819 /* Q14 */
#define ENH_A0_MINUS_A0A0DIV4 848256041 /* Q34 */
#define ENH_A0DIV2 26843546 /* Q30 */
/* PLC */
/* Down sampling */
#define FILTERORDER_DS_PLUS1 7
#define DELAY_DS 3
#define FACTOR_DS 2
/* bit stream defs */
#define NO_OF_BYTES_20MS 38
#define NO_OF_BYTES_30MS 50
#define NO_OF_WORDS_20MS 19
#define NO_OF_WORDS_30MS 25
#define STATE_BITS 3
#define BYTE_LEN 8
#define ULP_CLASSES 3
/* help parameters */
#define TWO_PI_FIX 25736 /* Q12 */
/* Constants for codebook search and creation */
#define ST_MEM_L_TBL 85
#define MEM_LF_TBL 147
/* Struct for the bits */
typedef struct iLBC_bits_t_ {
WebRtc_Word16 lsf[LSF_NSPLIT*LPC_N_MAX];
WebRtc_Word16 cb_index[CB_NSTAGES*(NASUB_MAX+1)]; /* First CB_NSTAGES values contains extra CB index */
WebRtc_Word16 gain_index[CB_NSTAGES*(NASUB_MAX+1)]; /* First CB_NSTAGES values contains extra CB gain */
WebRtc_Word16 idxForMax;
WebRtc_Word16 state_first;
WebRtc_Word16 idxVec[STATE_SHORT_LEN_30MS];
WebRtc_Word16 firstbits;
WebRtc_Word16 startIdx;
} iLBC_bits;
/* type definition encoder instance */
typedef struct iLBC_Enc_Inst_t_ {
/* flag for frame size mode */
WebRtc_Word16 mode;
/* basic parameters for different frame sizes */
WebRtc_Word16 blockl;
WebRtc_Word16 nsub;
WebRtc_Word16 nasub;
WebRtc_Word16 no_of_bytes, no_of_words;
WebRtc_Word16 lpc_n;
WebRtc_Word16 state_short_len;
/* analysis filter state */
WebRtc_Word16 anaMem[LPC_FILTERORDER];
/* Fix-point old lsf parameters for interpolation */
WebRtc_Word16 lsfold[LPC_FILTERORDER];
WebRtc_Word16 lsfdeqold[LPC_FILTERORDER];
/* signal buffer for LP analysis */
WebRtc_Word16 lpc_buffer[LPC_LOOKBACK + BLOCKL_MAX];
/* state of input HP filter */
WebRtc_Word16 hpimemx[2];
WebRtc_Word16 hpimemy[4];
#ifdef SPLIT_10MS
WebRtc_Word16 weightdenumbuf[66];
WebRtc_Word16 past_samples[160];
WebRtc_UWord16 bytes[25];
WebRtc_Word16 section;
WebRtc_Word16 Nfor_flag;
WebRtc_Word16 Nback_flag;
WebRtc_Word16 start_pos;
WebRtc_Word16 diff;
#endif
} iLBC_Enc_Inst_t;
/* type definition decoder instance */
typedef struct iLBC_Dec_Inst_t_ {
/* flag for frame size mode */
WebRtc_Word16 mode;
/* basic parameters for different frame sizes */
WebRtc_Word16 blockl;
WebRtc_Word16 nsub;
WebRtc_Word16 nasub;
WebRtc_Word16 no_of_bytes, no_of_words;
WebRtc_Word16 lpc_n;
WebRtc_Word16 state_short_len;
/* synthesis filter state */
WebRtc_Word16 syntMem[LPC_FILTERORDER];
/* old LSF for interpolation */
WebRtc_Word16 lsfdeqold[LPC_FILTERORDER];
/* pitch lag estimated in enhancer and used in PLC */
int last_lag;
/* PLC state information */
int consPLICount, prev_enh_pl;
WebRtc_Word16 perSquare;
WebRtc_Word16 prevScale, prevPLI;
WebRtc_Word16 prevLag, prevLpc[LPC_FILTERORDER+1];
WebRtc_Word16 prevResidual[NSUB_MAX*SUBL];
WebRtc_Word16 seed;
/* previous synthesis filter parameters */
WebRtc_Word16 old_syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
/* state of output HP filter */
WebRtc_Word16 hpimemx[2];
WebRtc_Word16 hpimemy[4];
/* enhancer state information */
int use_enhancer;
WebRtc_Word16 enh_buf[ENH_BUFL+ENH_BUFL_FILTEROVERHEAD];
WebRtc_Word16 enh_period[ENH_NBLOCKS_TOT];
} iLBC_Dec_Inst_t;
#endif

View File

@@ -0,0 +1,308 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_DoThePlc.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "comp_corr.h"
#include "bw_expand.h"
/*----------------------------------------------------------------*
* Packet loss concealment routine. Conceals a residual signal
* and LP parameters. If no packet loss, update state.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DoThePlc(
WebRtc_Word16 *PLCresidual, /* (o) concealed residual */
WebRtc_Word16 *PLClpc, /* (o) concealed LP parameters */
WebRtc_Word16 PLI, /* (i) packet loss indicator
0 - no PL, 1 = PL */
WebRtc_Word16 *decresidual, /* (i) decoded residual */
WebRtc_Word16 *lpc, /* (i) decoded LPC (only used for no PL) */
WebRtc_Word16 inlag, /* (i) pitch lag */
iLBC_Dec_Inst_t *iLBCdec_inst
/* (i/o) decoder instance */
){
WebRtc_Word16 i, pick;
WebRtc_Word32 cross, ener, cross_comp, ener_comp = 0;
WebRtc_Word32 measure, maxMeasure, energy;
WebRtc_Word16 max, crossSquareMax, crossSquare;
WebRtc_Word16 j, lag, tmp1, tmp2, randlag;
WebRtc_Word16 shift1, shift2, shift3, shiftMax;
WebRtc_Word16 scale3;
WebRtc_Word16 corrLen;
WebRtc_Word32 tmpW32, tmp2W32;
WebRtc_Word16 use_gain;
WebRtc_Word16 tot_gain;
WebRtc_Word16 max_perSquare;
WebRtc_Word16 scale1, scale2;
WebRtc_Word16 totscale;
WebRtc_Word32 nom;
WebRtc_Word16 denom;
WebRtc_Word16 pitchfact;
WebRtc_Word16 use_lag;
int ind;
WebRtc_Word16 randvec[BLOCKL_MAX];
/* Packet Loss */
if (PLI == 1) {
(*iLBCdec_inst).consPLICount += 1;
/* if previous frame not lost,
determine pitch pred. gain */
if (iLBCdec_inst->prevPLI != 1) {
/* Maximum 60 samples are correlated, preserve as high accuracy
as possible without getting overflow */
max = WebRtcSpl_MaxAbsValueW16((*iLBCdec_inst).prevResidual, (WebRtc_Word16)iLBCdec_inst->blockl);
scale3 = (WebRtcSpl_GetSizeInBits(max)<<1) - 25;
if (scale3 < 0) {
scale3 = 0;
}
/* Store scale for use when interpolating between the
* concealment and the received packet */
iLBCdec_inst->prevScale = scale3;
/* Search around the previous lag +/-3 to find the
best pitch period */
lag = inlag - 3;
/* Guard against getting outside the frame */
corrLen = WEBRTC_SPL_MIN(60, iLBCdec_inst->blockl-(inlag+3));
WebRtcIlbcfix_CompCorr( &cross, &ener,
iLBCdec_inst->prevResidual, lag, iLBCdec_inst->blockl, corrLen, scale3);
/* Normalize and store cross^2 and the number of shifts */
shiftMax = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross))-15;
crossSquareMax = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(WEBRTC_SPL_SHIFT_W32(cross, -shiftMax),
WEBRTC_SPL_SHIFT_W32(cross, -shiftMax), 15);
for (j=inlag-2;j<=inlag+3;j++) {
WebRtcIlbcfix_CompCorr( &cross_comp, &ener_comp,
iLBCdec_inst->prevResidual, j, iLBCdec_inst->blockl, corrLen, scale3);
/* Use the criteria (corr*corr)/energy to compare if
this lag is better or not. To avoid the division,
do a cross multiplication */
shift1 = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_ABS_W32(cross_comp))-15;
crossSquare = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1),
WEBRTC_SPL_SHIFT_W32(cross_comp, -shift1), 15);
shift2 = WebRtcSpl_GetSizeInBits(ener)-15;
measure = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_SHIFT_W32(ener, -shift2),
crossSquare);
shift3 = WebRtcSpl_GetSizeInBits(ener_comp)-15;
maxMeasure = WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_SHIFT_W32(ener_comp, -shift3),
crossSquareMax);
/* Calculate shift value, so that the two measures can
be put in the same Q domain */
if(((shiftMax<<1)+shift3) > ((shift1<<1)+shift2)) {
tmp1 = WEBRTC_SPL_MIN(31, (shiftMax<<1)+shift3-(shift1<<1)-shift2);
tmp2 = 0;
} else {
tmp1 = 0;
tmp2 = WEBRTC_SPL_MIN(31, (shift1<<1)+shift2-(shiftMax<<1)-shift3);
}
if ((measure>>tmp1) > (maxMeasure>>tmp2)) {
/* New lag is better => record lag, measure and domain */
lag = j;
crossSquareMax = crossSquare;
cross = cross_comp;
shiftMax = shift1;
ener = ener_comp;
}
}
/* Calculate the periodicity for the lag with the maximum correlation.
Definition of the periodicity:
abs(corr(vec1, vec2))/(sqrt(energy(vec1))*sqrt(energy(vec2)))
Work in the Square domain to simplify the calculations
max_perSquare is less than 1 (in Q15)
*/
tmp2W32=WebRtcSpl_DotProductWithScale(&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
&iLBCdec_inst->prevResidual[iLBCdec_inst->blockl-corrLen],
corrLen, scale3);
if ((tmp2W32>0)&&(ener_comp>0)) {
/* norm energies to WebRtc_Word16, compute the product of the energies and
use the upper WebRtc_Word16 as the denominator */
scale1=(WebRtc_Word16)WebRtcSpl_NormW32(tmp2W32)-16;
tmp1=(WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(tmp2W32, scale1);
scale2=(WebRtc_Word16)WebRtcSpl_NormW32(ener)-16;
tmp2=(WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(ener, scale2);
denom=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tmp1, tmp2, 16); /* denom in Q(scale1+scale2-16) */
/* Square the cross correlation and norm it such that max_perSquare
will be in Q15 after the division */
totscale = scale1+scale2-1;
tmp1 = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(cross, (totscale>>1));
tmp2 = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(cross, totscale-(totscale>>1));
nom = WEBRTC_SPL_MUL_16_16(tmp1, tmp2);
max_perSquare = (WebRtc_Word16)WebRtcSpl_DivW32W16(nom, denom);
} else {
max_perSquare = 0;
}
}
/* previous frame lost, use recorded lag and gain */
else {
lag = iLBCdec_inst->prevLag;
max_perSquare = iLBCdec_inst->perSquare;
}
/* Attenuate signal and scale down pitch pred gain if
several frames lost consecutively */
use_gain = 32767; /* 1.0 in Q15 */
if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>320) {
use_gain = 29491; /* 0.9 in Q15 */
} else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>640) {
use_gain = 22938; /* 0.7 in Q15 */
} else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>960) {
use_gain = 16384; /* 0.5 in Q15 */
} else if (iLBCdec_inst->consPLICount*iLBCdec_inst->blockl>1280) {
use_gain = 0; /* 0.0 in Q15 */
}
/* Compute mixing factor of picth repeatition and noise:
for max_per>0.7 set periodicity to 1.0
0.4<max_per<0.7 set periodicity to (maxper-0.4)/0.7-0.4)
max_per<0.4 set periodicity to 0.0
*/
if (max_perSquare>7868) { /* periodicity > 0.7 (0.7^4=0.2401 in Q15) */
pitchfact = 32767;
} else if (max_perSquare>839) { /* 0.4 < periodicity < 0.7 (0.4^4=0.0256 in Q15) */
/* find best index and interpolate from that */
ind = 5;
while ((max_perSquare<WebRtcIlbcfix_kPlcPerSqr[ind])&&(ind>0)) {
ind--;
}
/* pitch fact is approximated by first order */
tmpW32 = (WebRtc_Word32)WebRtcIlbcfix_kPlcPitchFact[ind] +
WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIlbcfix_kPlcPfSlope[ind], (max_perSquare-WebRtcIlbcfix_kPlcPerSqr[ind]), 11);
pitchfact = (WebRtc_Word16)WEBRTC_SPL_MIN(tmpW32, 32767); /* guard against overflow */
} else { /* periodicity < 0.4 */
pitchfact = 0;
}
/* avoid repetition of same pitch cycle (buzzyness) */
use_lag = lag;
if (lag<80) {
use_lag = 2*lag;
}
/* compute concealed residual */
energy = 0;
for (i=0; i<iLBCdec_inst->blockl; i++) {
/* noise component - 52 < randlagFIX < 117 */
iLBCdec_inst->seed = (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16(iLBCdec_inst->seed, 31821)+(WebRtc_Word32)13849);
randlag = 53 + (WebRtc_Word16)(iLBCdec_inst->seed & 63);
pick = i - randlag;
if (pick < 0) {
randvec[i] = iLBCdec_inst->prevResidual[iLBCdec_inst->blockl+pick];
} else {
randvec[i] = iLBCdec_inst->prevResidual[pick];
}
/* pitch repeatition component */
pick = i - use_lag;
if (pick < 0) {
PLCresidual[i] = iLBCdec_inst->prevResidual[iLBCdec_inst->blockl+pick];
} else {
PLCresidual[i] = PLCresidual[pick];
}
/* Attinuate total gain for each 10 ms */
if (i<80) {
tot_gain=use_gain;
} else if (i<160) {
tot_gain=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(31130, use_gain, 15); /* 0.95*use_gain */
} else {
tot_gain=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(29491, use_gain, 15); /* 0.9*use_gain */
}
/* mix noise and pitch repeatition */
PLCresidual[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(tot_gain,
(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32( (WEBRTC_SPL_MUL_16_16(pitchfact, PLCresidual[i]) +
WEBRTC_SPL_MUL_16_16((32767-pitchfact), randvec[i]) + 16384),
15),
15);
/* Shifting down the result one step extra to ensure that no overflow
will occur */
energy += WEBRTC_SPL_MUL_16_16_RSFT(PLCresidual[i],
PLCresidual[i], (iLBCdec_inst->prevScale+1));
}
/* less than 30 dB, use only noise */
if (energy < (WEBRTC_SPL_SHIFT_W32(((WebRtc_Word32)iLBCdec_inst->blockl*900),-(iLBCdec_inst->prevScale+1)))) {
energy = 0;
for (i=0; i<iLBCdec_inst->blockl; i++) {
PLCresidual[i] = randvec[i];
}
}
/* use the old LPC */
WEBRTC_SPL_MEMCPY_W16(PLClpc, (*iLBCdec_inst).prevLpc, LPC_FILTERORDER+1);
/* Update state in case there are multiple frame losses */
iLBCdec_inst->prevLag = lag;
iLBCdec_inst->perSquare = max_perSquare;
}
/* no packet loss, copy input */
else {
WEBRTC_SPL_MEMCPY_W16(PLCresidual, decresidual, iLBCdec_inst->blockl);
WEBRTC_SPL_MEMCPY_W16(PLClpc, lpc, (LPC_FILTERORDER+1));
iLBCdec_inst->consPLICount = 0;
}
/* update state */
iLBCdec_inst->prevPLI = PLI;
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevLpc, PLClpc, (LPC_FILTERORDER+1));
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->prevResidual, PLCresidual, iLBCdec_inst->blockl);
return;
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_DoThePlc.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Packet loss concealment routine. Conceals a residual signal
* and LP parameters. If no packet loss, update state.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DoThePlc(
WebRtc_Word16 *PLCresidual, /* (o) concealed residual */
WebRtc_Word16 *PLClpc, /* (o) concealed LP parameters */
WebRtc_Word16 PLI, /* (i) packet loss indicator
0 - no PL, 1 = PL */
WebRtc_Word16 *decresidual, /* (i) decoded residual */
WebRtc_Word16 *lpc, /* (i) decoded LPC (only used for no PL) */
WebRtc_Word16 inlag, /* (i) pitch lag */
iLBC_Dec_Inst_t *iLBCdec_inst
/* (i/o) decoder instance */
);
#endif

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Encode.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
#include "defines.h"
/*----------------------------------------------------------------*
* main encoder function
*---------------------------------------------------------------*/
void WebRtcIlbcfix_EncodeImpl(
WebRtc_UWord16 *bytes, /* (o) encoded data bits iLBC */
WebRtc_Word16 *block, /* (i) speech vector to encode */
iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the general encoder
state */
);
#endif

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_EnergyInverse.c
******************************************************************/
/* Inverses the in vector in into Q29 domain */
#include "energy_inverse.h"
void WebRtcIlbcfix_EnergyInverse(
WebRtc_Word16 *energy, /* (i/o) Energy and inverse
energy (in Q29) */
int noOfEnergies) /* (i) The length of the energy
vector */
{
WebRtc_Word32 Nom=(WebRtc_Word32)0x1FFFFFFF;
WebRtc_Word16 *energyPtr;
int i;
/* Set the minimum energy value to 16384 to avoid overflow */
energyPtr=energy;
for (i=0; i<noOfEnergies; i++) {
(*energyPtr)=WEBRTC_SPL_MAX((*energyPtr),16384);
energyPtr++;
}
/* Calculate inverse energy in Q29 */
energyPtr=energy;
for (i=0; i<noOfEnergies; i++) {
(*energyPtr) = (WebRtc_Word16)WebRtcSpl_DivW32W16(Nom, (*energyPtr));
energyPtr++;
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_EnergyInverse.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
#include "defines.h"
/* Inverses the in vector in into Q29 domain */
void WebRtcIlbcfix_EnergyInverse(
WebRtc_Word16 *energy, /* (i/o) Energy and inverse
energy (in Q29) */
int noOfEnergies); /* (i) The length of the energy
vector */
#endif

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_EnhUpsample.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* upsample finite array assuming zeros outside bounds
*---------------------------------------------------------------*/
void WebRtcIlbcfix_EnhUpsample(
WebRtc_Word32 *useq1, /* (o) upsampled output sequence */
WebRtc_Word16 *seq1 /* (i) unupsampled sequence */
){
int j;
WebRtc_Word32 *pu1, *pu11;
WebRtc_Word16 *ps, *w16tmp;
const WebRtc_Word16 *pp;
/* filtering: filter overhangs left side of sequence */
pu1=useq1;
for (j=0;j<ENH_UPS0; j++) {
pu11=pu1;
/* i = 2 */
pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
ps=seq1+2;
(*pu11) = WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
pu11+=ENH_UPS0;
/* i = 3 */
pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
ps=seq1+3;
(*pu11) = WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
pu11+=ENH_UPS0;
/* i = 4 */
pp=WebRtcIlbcfix_kEnhPolyPhaser[j]+1;
ps=seq1+4;
(*pu11) = WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--,*pp++);
pu1++;
}
/* filtering: simple convolution=inner products
(not needed since the sequence is so short)
*/
/* filtering: filter overhangs right side of sequence */
/* Code with loops, which is equivivalent to the expanded version below
filterlength = 5;
hf1 = 2;
for(j=0;j<ENH_UPS0; j++){
pu = useq1 + (filterlength-hfl)*ENH_UPS0 + j;
for(i=1; i<=hfl; i++){
*pu=0;
pp = polyp[j]+i;
ps = seq1+dim1-1;
for(k=0;k<filterlength-i;k++) {
*pu += WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
}
pu+=ENH_UPS0;
}
}
*/
pu1 = useq1 + 12;
w16tmp = seq1+4;
for (j=0;j<ENH_UPS0; j++) {
pu11 = pu1;
/* i = 1 */
pp = WebRtcIlbcfix_kEnhPolyPhaser[j]+2;
ps = w16tmp;
(*pu11) = WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
pu11+=ENH_UPS0;
/* i = 2 */
pp = WebRtcIlbcfix_kEnhPolyPhaser[j]+3;
ps = w16tmp;
(*pu11) = WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
(*pu11) += WEBRTC_SPL_MUL_16_16(*ps--, *pp++);
pu11+=ENH_UPS0;
pu1++;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_EnhUpsample.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENH_UPSAMPLE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENH_UPSAMPLE_H_
#include "defines.h"
/*----------------------------------------------------------------*
* upsample finite array assuming zeros outside bounds
*---------------------------------------------------------------*/
void WebRtcIlbcfix_EnhUpsample(
WebRtc_Word32 *useq1, /* (o) upsampled output sequence */
WebRtc_Word16 *seq1 /* (i) unupsampled sequence */
);
#endif

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Enhancer.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "get_sync_seq.h"
#include "smooth.h"
/*----------------------------------------------------------------*
* perform enhancement on idata+centerStartPos through
* idata+centerStartPos+ENH_BLOCKL-1
*---------------------------------------------------------------*/
void WebRtcIlbcfix_Enhancer(
iLBC_Dec_Inst_t *iLBCdec_inst,
/* (i) Decoder state */
WebRtc_Word16 *odata, /* (o) smoothed block, dimension blockl */
WebRtc_Word16 *idata, /* (i) data buffer used for enhancing */
WebRtc_Word16 idatal, /* (i) dimension idata */
WebRtc_Word16 centerStartPos, /* (i) first sample current block within idata */
WebRtc_Word16 *period, /* (i) pitch period array (pitch bward-in time) */
WebRtc_Word16 *plocs, /* (i) locations where period array values valid */
WebRtc_Word16 periodl /* (i) dimension of period and plocs */
){
/* Stack based */
WebRtc_Word16 surround[ENH_BLOCKL];
WebRtcSpl_MemSetW16(surround, 0, ENH_BLOCKL);
/* get said second sequence of segments */
WebRtcIlbcfix_GetSyncSeq(iLBCdec_inst, idata,idatal,centerStartPos,period,plocs,periodl,ENH_HL,surround);
/* compute the smoothed output from said second sequence */
WebRtcIlbcfix_Smooth(odata, idata+centerStartPos, surround);
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Enhancer.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
#include "defines.h"
/*----------------------------------------------------------------*
* perform enhancement on idata+centerStartPos through
* idata+centerStartPos+ENH_BLOCKL-1
*---------------------------------------------------------------*/
void WebRtcIlbcfix_Enhancer(
iLBC_Dec_Inst_t *iLBCdec_inst,
/* (i) Decoder state */
WebRtc_Word16 *odata, /* (o) smoothed block, dimension blockl */
WebRtc_Word16 *idata, /* (i) data buffer used for enhancing */
WebRtc_Word16 idatal, /* (i) dimension idata */
WebRtc_Word16 centerStartPos, /* (i) first sample current block within idata */
WebRtc_Word16 *period, /* (i) pitch period array (pitch bward-in time) */
WebRtc_Word16 *plocs, /* (i) locations where period array values valid */
WebRtc_Word16 periodl /* (i) dimension of period and plocs */
);
#endif

View File

@@ -0,0 +1,343 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_EnhancerInterface.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "xcorr_coef.h"
#include "enhancer.h"
#include "hp_output.h"
/*----------------------------------------------------------------*
* interface for enhancer
*---------------------------------------------------------------*/
int WebRtcIlbcfix_EnhancerInterface( /* (o) Estimated lag in end of in[] */
WebRtc_Word16 *out, /* (o) enhanced signal */
WebRtc_Word16 *in, /* (i) unenhanced signal */
iLBC_Dec_Inst_t *iLBCdec_inst /* (i) buffers etc */
){
int iblock;
int lag=20, tlag=20;
int inLen=iLBCdec_inst->blockl+120;
WebRtc_Word16 scale, scale1, plc_blockl;
WebRtc_Word16 *enh_buf, *enh_period;
WebRtc_Word32 tmp1, tmp2, max, new_blocks;
WebRtc_Word16 *enh_bufPtr1;
int i, k;
WebRtc_Word16 EnChange;
WebRtc_Word16 SqrtEnChange;
WebRtc_Word16 inc;
WebRtc_Word16 win;
WebRtc_Word16 *tmpW16ptr;
WebRtc_Word16 startPos;
WebRtc_Word16 *plc_pred;
WebRtc_Word16 *target, *regressor;
WebRtc_Word16 max16;
int shifts;
WebRtc_Word32 ener;
WebRtc_Word16 enerSh;
WebRtc_Word16 corrSh;
WebRtc_Word16 ind, sh;
WebRtc_Word16 start, stop;
/* Stack based */
WebRtc_Word16 totsh[3];
WebRtc_Word16 downsampled[(BLOCKL_MAX+120)>>1]; /* length 180 */
WebRtc_Word32 corr32[50];
WebRtc_Word32 corrmax[3];
WebRtc_Word16 corr16[3];
WebRtc_Word16 en16[3];
WebRtc_Word16 lagmax[3];
plc_pred = downsampled; /* Reuse memory since plc_pred[ENH_BLOCKL] and downsampled are non overlapping */
enh_buf=iLBCdec_inst->enh_buf;
enh_period=iLBCdec_inst->enh_period;
/* Copy in the new data into the enhancer buffer */
WEBRTC_SPL_MEMMOVE_W16(enh_buf, &enh_buf[iLBCdec_inst->blockl],
ENH_BUFL-iLBCdec_inst->blockl);
WEBRTC_SPL_MEMCPY_W16(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in,
iLBCdec_inst->blockl);
/* Set variables that are dependent on frame size */
if (iLBCdec_inst->mode==30) {
plc_blockl=ENH_BLOCKL;
new_blocks=3;
startPos=320; /* Start position for enhancement (640-new_blocks*ENH_BLOCKL-80) */
} else {
plc_blockl=40;
new_blocks=2;
startPos=440; /* Start position for enhancement (640-new_blocks*ENH_BLOCKL-40) */
}
/* Update the pitch prediction for each enhancer block, move the old ones */
WEBRTC_SPL_MEMMOVE_W16(enh_period, &enh_period[new_blocks], (ENH_NBLOCKS_TOT-new_blocks));
k=WebRtcSpl_DownsampleFast(
enh_buf+ENH_BUFL-inLen, /* Input samples */
(WebRtc_Word16)(inLen+ENH_BUFL_FILTEROVERHEAD),
downsampled,
(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(inLen, 1),
(WebRtc_Word16*)WebRtcIlbcfix_kLpFiltCoefs, /* Coefficients in Q12 */
FILTERORDER_DS_PLUS1, /* Length of filter (order-1) */
FACTOR_DS,
DELAY_DS);
/* Estimate the pitch in the down sampled domain. */
for(iblock = 0; iblock<new_blocks; iblock++){
/* references */
i=60+WEBRTC_SPL_MUL_16_16(iblock,ENH_BLOCKL_HALF);
target=downsampled+i;
regressor=downsampled+i-10;
/* scaling */
max16=WebRtcSpl_MaxAbsValueW16(&regressor[-50], (WebRtc_Word16)(ENH_BLOCKL_HALF+50-1));
shifts = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(max16, max16)) - 25;
shifts = WEBRTC_SPL_MAX(0, shifts);
/* compute cross correlation */
WebRtcSpl_CrossCorrelation(corr32, target, regressor,
ENH_BLOCKL_HALF, 50, (WebRtc_Word16)shifts, -1);
/* Find 3 highest correlations that should be compared for the
highest (corr*corr)/ener */
for (i=0;i<2;i++) {
lagmax[i] = WebRtcSpl_MaxIndexW32(corr32, 50);
corrmax[i] = corr32[lagmax[i]];
start = lagmax[i] - 2;
stop = lagmax[i] + 2;
start = WEBRTC_SPL_MAX(0, start);
stop = WEBRTC_SPL_MIN(49, stop);
for (k=start; k<=stop; k++) {
corr32[k] = 0;
}
}
lagmax[2] = WebRtcSpl_MaxIndexW32(corr32, 50);
corrmax[2] = corr32[lagmax[2]];
/* Calculate normalized corr^2 and ener */
for (i=0;i<3;i++) {
corrSh = 15-WebRtcSpl_GetSizeInBits(corrmax[i]);
ener = WebRtcSpl_DotProductWithScale(&regressor[-lagmax[i]], &regressor[-lagmax[i]], ENH_BLOCKL_HALF, shifts);
enerSh = 15-WebRtcSpl_GetSizeInBits(ener);
corr16[i] = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(corrmax[i], corrSh);
corr16[i] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(corr16[i], corr16[i], 16);
en16[i] = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(ener, enerSh);
totsh[i] = enerSh - WEBRTC_SPL_LSHIFT_W32(corrSh, 1);
}
/* Compare lagmax[0..3] for the (corr^2)/ener criteria */
ind = 0;
for (i=1; i<3; i++) {
if (totsh[ind] > totsh[i]) {
sh = WEBRTC_SPL_MIN(31, totsh[ind]-totsh[i]);
if ( WEBRTC_SPL_MUL_16_16(corr16[ind], en16[i]) < WEBRTC_SPL_MUL_16_16_RSFT(corr16[i], en16[ind], sh)) {
ind = i;
}
} else {
sh = WEBRTC_SPL_MIN(31, totsh[i]-totsh[ind]);
if (WEBRTC_SPL_MUL_16_16_RSFT(corr16[ind], en16[i], sh) < WEBRTC_SPL_MUL_16_16(corr16[i], en16[ind])) {
ind = i;
}
}
}
lag = lagmax[ind] + 10;
/* Store the estimated lag in the non-downsampled domain */
enh_period[ENH_NBLOCKS_TOT-new_blocks+iblock] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(lag, 8);
/* Store the estimated lag for backward PLC */
if (iLBCdec_inst->prev_enh_pl==1) {
if (!iblock) {
tlag = WEBRTC_SPL_MUL_16_16(lag, 2);
}
} else {
if (iblock==1) {
tlag = WEBRTC_SPL_MUL_16_16(lag, 2);
}
}
lag = WEBRTC_SPL_MUL_16_16(lag, 2);
}
if ((iLBCdec_inst->prev_enh_pl==1)||(iLBCdec_inst->prev_enh_pl==2)) {
/* Calculate the best lag of the new frame
This is used to interpolate backwards and mix with the PLC'd data
*/
/* references */
target=in;
regressor=in+tlag-1;
/* scaling */
max16=WebRtcSpl_MaxAbsValueW16(regressor, (WebRtc_Word16)(plc_blockl+3-1));
if (max16>5000)
shifts=2;
else
shifts=0;
/* compute cross correlation */
WebRtcSpl_CrossCorrelation(corr32, target, regressor,
plc_blockl, 3, (WebRtc_Word16)shifts, 1);
/* find lag */
lag=WebRtcSpl_MaxIndexW32(corr32, 3);
lag+=tlag-1;
/* Copy the backward PLC to plc_pred */
if (iLBCdec_inst->prev_enh_pl==1) {
if (lag>plc_blockl) {
WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-plc_blockl], plc_blockl);
} else {
WEBRTC_SPL_MEMCPY_W16(&plc_pred[plc_blockl-lag], in, lag);
WEBRTC_SPL_MEMCPY_W16(plc_pred, &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl+lag], (plc_blockl-lag));
}
} else {
int pos;
pos = plc_blockl;
while (lag<pos) {
WEBRTC_SPL_MEMCPY_W16(&plc_pred[pos-lag], in, lag);
pos = pos - lag;
}
WEBRTC_SPL_MEMCPY_W16(plc_pred, &in[lag-pos], pos);
}
if (iLBCdec_inst->prev_enh_pl==1) {
/* limit energy change
if energy in backward PLC is more than 4 times higher than the forward PLC,
then reduce the energy in the backward PLC vector:
sample 1...len-16 set energy of the to 4 times forward PLC
sample len-15..len interpolate between 4 times fw PLC and bw PLC energy
Note: Compared to floating point code there is a slight change,
the window is 16 samples long instead of 10 samples to simplify the calculations
*/
max=WebRtcSpl_MaxAbsValueW16(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], plc_blockl);
max16=WebRtcSpl_MaxAbsValueW16(plc_pred, plc_blockl);
max = WEBRTC_SPL_MAX(max, max16);
scale=22-(WebRtc_Word16)WebRtcSpl_NormW32(max);
scale=WEBRTC_SPL_MAX(scale,0);
tmp2 = WebRtcSpl_DotProductWithScale(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], &enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl], plc_blockl, scale);
tmp1 = WebRtcSpl_DotProductWithScale(plc_pred, plc_pred, plc_blockl, scale);
/* Check the energy difference */
if ((tmp1>0)&&((tmp1>>2)>tmp2)) {
/* EnChange is now guaranteed to be <0.5
Calculate EnChange=tmp2/tmp1 in Q16
*/
scale1=(WebRtc_Word16)WebRtcSpl_NormW32(tmp1);
tmp1=WEBRTC_SPL_SHIFT_W32(tmp1, (scale1-16)); /* using 15 bits */
tmp2=WEBRTC_SPL_SHIFT_W32(tmp2, (scale1));
EnChange = (WebRtc_Word16)WebRtcSpl_DivW32W16(tmp2, (WebRtc_Word16)tmp1);
/* Calculate the Sqrt of the energy in Q15 ((14+16)/2) */
SqrtEnChange = (WebRtc_Word16)WebRtcSpl_Sqrt(WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)EnChange, 14));
/* Multiply first part of vector with 2*SqrtEnChange */
WebRtcSpl_ScaleVector(plc_pred, plc_pred, SqrtEnChange, (WebRtc_Word16)(plc_blockl-16), 14);
/* Calculate increase parameter for window part (16 last samples) */
inc=(2048-WEBRTC_SPL_RSHIFT_W16(SqrtEnChange, 3)); /* (1-2*SqrtEnChange)/16 in Q15 */
win=0;
tmpW16ptr=&plc_pred[plc_blockl-16];
for (i=16;i>0;i--) {
(*tmpW16ptr)=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((*tmpW16ptr),
(SqrtEnChange+(win>>1)), 14); /* multiply by (2.0*SqrtEnChange+win) */
win += inc;
tmpW16ptr++;
}
}
/* Make the linear interpolation between the forward PLC'd data
and the backward PLC'd data (from the new frame)
*/
if (plc_blockl==40) {
inc=400; /* 1/41 in Q14 */
} else { /* plc_blockl==80 */
inc=202; /* 1/81 in Q14 */
}
win=0;
enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl];
for (i=0; i<plc_blockl; i++) {
win+=inc;
*enh_bufPtr1 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((*enh_bufPtr1), win, 14);
*enh_bufPtr1 += (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((16384-win), plc_pred[plc_blockl-1-i], 14);
enh_bufPtr1--;
}
} else {
WebRtc_Word16 *synt = &downsampled[LPC_FILTERORDER];
enh_bufPtr1=&enh_buf[ENH_BUFL-iLBCdec_inst->blockl-plc_blockl];
WEBRTC_SPL_MEMCPY_W16(enh_bufPtr1, plc_pred, plc_blockl);
/* Clear fileter memory */
WebRtcSpl_MemSetW16(iLBCdec_inst->syntMem, 0, LPC_FILTERORDER);
WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemy, 0, 4);
WebRtcSpl_MemSetW16(iLBCdec_inst->hpimemx, 0, 2);
/* Initialize filter memory by filtering through 2 lags */
WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
WebRtcSpl_FilterARFastQ12(
enh_bufPtr1, synt,
&iLBCdec_inst->old_syntdenum[(iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)], LPC_FILTERORDER+1, (WebRtc_Word16)lag);
WEBRTC_SPL_MEMCPY_W16(&synt[-LPC_FILTERORDER], &synt[lag-LPC_FILTERORDER], LPC_FILTERORDER);
WebRtcIlbcfix_HpOutput(synt, (WebRtc_Word16*)WebRtcIlbcfix_kHpOutCoefs,
iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
(WebRtc_Word16)lag);
WebRtcSpl_FilterARFastQ12(
enh_bufPtr1, synt,
&iLBCdec_inst->old_syntdenum[(iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1)], LPC_FILTERORDER+1, (WebRtc_Word16)lag);
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &synt[lag-LPC_FILTERORDER], LPC_FILTERORDER);
WebRtcIlbcfix_HpOutput(synt, (WebRtc_Word16*)WebRtcIlbcfix_kHpOutCoefs,
iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
(WebRtc_Word16)lag);
}
}
/* Perform enhancement block by block */
for (iblock = 0; iblock<new_blocks; iblock++) {
WebRtcIlbcfix_Enhancer(iLBCdec_inst, out+WEBRTC_SPL_MUL_16_16(iblock, ENH_BLOCKL), enh_buf,
ENH_BUFL, (WebRtc_Word16)(WEBRTC_SPL_MUL_16_16(iblock, ENH_BLOCKL)+startPos),
enh_period, (WebRtc_Word16*)WebRtcIlbcfix_kEnhPlocs, ENH_NBLOCKS_TOT);
}
return (lag);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_EnhancerInterface.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
#include "defines.h"
/*----------------------------------------------------------------*
* interface for enhancer
*---------------------------------------------------------------*/
int WebRtcIlbcfix_EnhancerInterface( /* (o) Estimated lag in end of in[] */
WebRtc_Word16 *out, /* (o) enhanced signal */
WebRtc_Word16 *in, /* (i) unenhanced signal */
iLBC_Dec_Inst_t *iLBCdec_inst /* (i) buffers etc */
);
#endif

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_FilteredCbVecs.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* Construct an additional codebook vector by filtering the
* initial codebook buffer. This vector is then used to expand
* the codebook with an additional section.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_FilteredCbVecs(
WebRtc_Word16 *cbvectors, /* (o) Codebook vector for the higher section */
WebRtc_Word16 *CBmem, /* (i) Codebook memory that is filtered to create a
second CB section */
int lMem, /* (i) Length of codebook memory */
WebRtc_Word16 samples /* (i) Number of samples to filter */
) {
/* Set up the memory, start with zero state */
WebRtcSpl_MemSetW16(CBmem+lMem, 0, CB_HALFFILTERLEN);
WebRtcSpl_MemSetW16(CBmem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN);
WebRtcSpl_MemSetW16(cbvectors, 0, lMem-samples);
/* Filter to obtain the filtered CB memory */
WebRtcSpl_FilterMAFastQ12(
CBmem+CB_HALFFILTERLEN+lMem-samples, cbvectors+lMem-samples,
(WebRtc_Word16*)WebRtcIlbcfix_kCbFiltersRev, CB_FILTERLEN, samples);
return;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_FilteredCbVecs.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Construct an additional codebook vector by filtering the
* initial codebook buffer. This vector is then used to expand
* the codebook with an additional section.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_FilteredCbVecs(
WebRtc_Word16 *cbvectors, /* (o) Codebook vector for the higher section */
WebRtc_Word16 *CBmem, /* (i) Codebook memory that is filtered to create a
second CB section */
int lMem, /* (i) Length of codebook memory */
WebRtc_Word16 samples /* (i) Number of samples to filter */
);
#endif

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_FrameClassify.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* Classification of subframes to localize start state
*---------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_FrameClassify(
/* (o) Index to the max-energy sub frame */
iLBC_Enc_Inst_t *iLBCenc_inst,
/* (i/o) the encoder state structure */
WebRtc_Word16 *residualFIX /* (i) lpc residual signal */
){
WebRtc_Word16 max, scale;
WebRtc_Word32 ssqEn[NSUB_MAX-1];
WebRtc_Word16 *ssqPtr;
WebRtc_Word32 *seqEnPtr;
WebRtc_Word32 maxW32;
WebRtc_Word16 scale1;
WebRtc_Word16 pos;
int n;
/*
Calculate the energy of each of the 80 sample blocks
in the draft the 4 first and last samples are windowed with 1/5...4/5
and 4/5...1/5 respectively. To simplify for the fixpoint we have changed
this to 0 0 1 1 and 1 1 0 0
*/
max = WebRtcSpl_MaxAbsValueW16(residualFIX, iLBCenc_inst->blockl);
scale=WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(max,max));
/* Scale to maximum 24 bits so that it won't overflow for 76 samples */
scale = scale-24;
scale1 = WEBRTC_SPL_MAX(0, scale);
/* Calculate energies */
ssqPtr=residualFIX + 2;
seqEnPtr=ssqEn;
for (n=(iLBCenc_inst->nsub-1); n>0; n--) {
(*seqEnPtr) = WebRtcSpl_DotProductWithScale(ssqPtr, ssqPtr, 76, scale1);
ssqPtr += 40;
seqEnPtr++;
}
/* Scale to maximum 20 bits in order to allow for the 11 bit window */
maxW32 = WebRtcSpl_MaxValueW32(ssqEn, (WebRtc_Word16)(iLBCenc_inst->nsub-1));
scale = WebRtcSpl_GetSizeInBits(maxW32) - 20;
scale1 = WEBRTC_SPL_MAX(0, scale);
/* Window each 80 block with the ssqEn_winTbl window to give higher probability for
the blocks in the middle
*/
seqEnPtr=ssqEn;
if (iLBCenc_inst->mode==20) {
ssqPtr=(WebRtc_Word16*)WebRtcIlbcfix_kStartSequenceEnrgWin+1;
} else {
ssqPtr=(WebRtc_Word16*)WebRtcIlbcfix_kStartSequenceEnrgWin;
}
for (n=(iLBCenc_inst->nsub-1); n>0; n--) {
(*seqEnPtr)=WEBRTC_SPL_MUL(((*seqEnPtr)>>scale1), (*ssqPtr));
seqEnPtr++;
ssqPtr++;
}
/* Extract the best choise of start state */
pos = WebRtcSpl_MaxIndexW32(ssqEn, (WebRtc_Word16)(iLBCenc_inst->nsub-1)) + 1;
return(pos);
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_FrameClassify.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
WebRtc_Word16 WebRtcIlbcfix_FrameClassify(
/* (o) Index to the max-energy sub frame */
iLBC_Enc_Inst_t *iLBCenc_inst,
/* (i/o) the encoder state structure */
WebRtc_Word16 *residualFIX /* (i) lpc residual signal */
);
#endif

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GainDequant.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* decoder for quantized gains in the gain-shape coding of
* residual
*---------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_GainDequant(
/* (o) quantized gain value (Q14) */
WebRtc_Word16 index, /* (i) quantization index */
WebRtc_Word16 maxIn, /* (i) maximum of unquantized gain (Q14) */
WebRtc_Word16 stage /* (i) The stage of the search */
){
WebRtc_Word16 scale;
const WebRtc_Word16 *gain;
/* obtain correct scale factor */
scale=WEBRTC_SPL_ABS_W16(maxIn);
scale = WEBRTC_SPL_MAX(1638, scale); /* if lower than 0.1, set it to 0.1 */
/* select the quantization table and return the decoded value */
gain = WebRtcIlbcfix_kGain[stage];
return((WebRtc_Word16)((WEBRTC_SPL_MUL_16_16(scale, gain[index])+8192)>>14));
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GainDequant.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
#include "defines.h"
/*----------------------------------------------------------------*
* decoder for quantized gains in the gain-shape coding of
* residual
*---------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_GainDequant(
/* (o) quantized gain value (Q14) */
WebRtc_Word16 index, /* (i) quantization index */
WebRtc_Word16 maxIn, /* (i) maximum of unquantized gain (Q14) */
WebRtc_Word16 stage /* (i) The stage of the search */
);
#endif

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GainQuant.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/*----------------------------------------------------------------*
* quantizer for the gain in the gain-shape coding of residual
*---------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_GainQuant( /* (o) quantized gain value */
WebRtc_Word16 gain, /* (i) gain value Q14 */
WebRtc_Word16 maxIn, /* (i) maximum of gain value Q14 */
WebRtc_Word16 stage, /* (i) The stage of the search */
WebRtc_Word16 *index /* (o) quantization index */
) {
WebRtc_Word16 scale, returnVal, cblen;
WebRtc_Word32 gainW32, measure1, measure2;
const WebRtc_Word16 *cbPtr, *cb;
int loc, noMoves, noChecks, i;
/* ensure a lower bound (0.1) on the scaling factor */
scale = WEBRTC_SPL_MAX(1638, maxIn);
/* select the quantization table and calculate
the length of the table and the number of
steps in the binary search that are needed */
cb = WebRtcIlbcfix_kGain[stage];
cblen = 32>>stage;
noChecks = 4-stage;
/* Multiply the gain with 2^14 to make the comparison
easier and with higher precision */
gainW32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)gain, 14);
/* Do a binary search, starting in the middle of the CB
loc - defines the current position in the table
noMoves - defines the number of steps to move in the CB in order
to get next CB location
*/
loc = cblen>>1;
noMoves = loc;
cbPtr = cb + loc; /* Centre of CB */
for (i=noChecks;i>0;i--) {
noMoves>>=1;
measure1=WEBRTC_SPL_MUL_16_16(scale, (*cbPtr));
/* Move up if gain is larger, otherwise move down in table */
measure1 = measure1 - gainW32;
if (0>measure1) {
cbPtr+=noMoves;
loc+=noMoves;
} else {
cbPtr-=noMoves;
loc-=noMoves;
}
}
/* Check which value is the closest one: loc-1, loc or loc+1 */
measure1=WEBRTC_SPL_MUL_16_16(scale, (*cbPtr));
if (gainW32>measure1) {
/* Check against value above loc */
measure2=WEBRTC_SPL_MUL_16_16(scale, (*(cbPtr+1)));
if ((measure2-gainW32)<(gainW32-measure1)) {
loc+=1;
}
} else {
/* Check against value below loc */
measure2=WEBRTC_SPL_MUL_16_16(scale, (*(cbPtr-1)));
if ((gainW32-measure2)<=(measure1-gainW32)) {
loc-=1;
}
}
/* Guard against getting outside the table. The calculation above can give a location
which is one above the maximum value (in very rare cases) */
loc=WEBRTC_SPL_MIN(loc, (cblen-1));
*index=loc;
/* Calculate the quantized gain value (in Q14) */
returnVal=(WebRtc_Word16)((WEBRTC_SPL_MUL_16_16(scale, cb[loc])+8192)>>14);
/* return the quantized value */
return(returnVal);
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GainQuant.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
#include "defines.h"
/*----------------------------------------------------------------*
* quantizer for the gain in the gain-shape coding of residual
*---------------------------------------------------------------*/
WebRtc_Word16 WebRtcIlbcfix_GainQuant( /* (o) quantized gain value */
WebRtc_Word16 gain, /* (i) gain value Q14 */
WebRtc_Word16 maxIn, /* (i) maximum of gain value Q14 */
WebRtc_Word16 stage, /* (i) The stage of the search */
WebRtc_Word16 *index /* (o) quantization index */
);
#endif

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GetCbVec.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "create_augmented_vec.h"
/*----------------------------------------------------------------*
* Construct codebook vector for given index.
*---------------------------------------------------------------*/
void WebRtcIlbcfix_GetCbVec(
WebRtc_Word16 *cbvec, /* (o) Constructed codebook vector */
WebRtc_Word16 *mem, /* (i) Codebook buffer */
WebRtc_Word16 index, /* (i) Codebook index */
WebRtc_Word16 lMem, /* (i) Length of codebook buffer */
WebRtc_Word16 cbveclen /* (i) Codebook vector length */
){
WebRtc_Word16 k, base_size;
WebRtc_Word16 lag;
/* Stack based */
WebRtc_Word16 tempbuff2[SUBL+5];
/* Determine size of codebook sections */
base_size=lMem-cbveclen+1;
if (cbveclen==SUBL) {
base_size+=WEBRTC_SPL_RSHIFT_W16(cbveclen,1);
}
/* No filter -> First codebook section */
if (index<lMem-cbveclen+1) {
/* first non-interpolated vectors */
k=index+cbveclen;
/* get vector */
WEBRTC_SPL_MEMCPY_W16(cbvec, mem+lMem-k, cbveclen);
} else if (index < base_size) {
/* Calculate lag */
k=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(2, (index-(lMem-cbveclen+1)))+cbveclen;
lag=WEBRTC_SPL_RSHIFT_W16(k, 1);
WebRtcIlbcfix_CreateAugmentedVec(lag, mem+lMem, cbvec);
}
/* Higher codebbok section based on filtering */
else {
WebRtc_Word16 memIndTest;
/* first non-interpolated vectors */
if (index-base_size<lMem-cbveclen+1) {
/* Set up filter memory, stuff zeros outside memory buffer */
memIndTest = lMem-(index-base_size+cbveclen);
WebRtcSpl_MemSetW16(mem-CB_HALFFILTERLEN, 0, CB_HALFFILTERLEN);
WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN);
/* do filtering to get the codebook vector */
WebRtcSpl_FilterMAFastQ12(
&mem[memIndTest+4], cbvec, (WebRtc_Word16*)WebRtcIlbcfix_kCbFiltersRev,
CB_FILTERLEN, cbveclen);
}
/* interpolated vectors */
else {
/* Stuff zeros outside memory buffer */
memIndTest = lMem-cbveclen-CB_FILTERLEN;
WebRtcSpl_MemSetW16(mem+lMem, 0, CB_HALFFILTERLEN);
/* do filtering */
WebRtcSpl_FilterMAFastQ12(
&mem[memIndTest+7], tempbuff2, (WebRtc_Word16*)WebRtcIlbcfix_kCbFiltersRev,
CB_FILTERLEN, (WebRtc_Word16)(cbveclen+5));
/* Calculate lag index */
lag = (cbveclen<<1)-20+index-base_size-lMem-1;
WebRtcIlbcfix_CreateAugmentedVec(lag, tempbuff2+SUBL+5, cbvec);
}
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GetCbVec.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
void WebRtcIlbcfix_GetCbVec(
WebRtc_Word16 *cbvec, /* (o) Constructed codebook vector */
WebRtc_Word16 *mem, /* (i) Codebook buffer */
WebRtc_Word16 index, /* (i) Codebook index */
WebRtc_Word16 lMem, /* (i) Length of codebook buffer */
WebRtc_Word16 cbveclen /* (i) Codebook vector length */
);
#endif

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GetLspPoly.c
******************************************************************/
#include "defines.h"
/*----------------------------------------------------------------*
* Construct the polynomials F1(z) and F2(z) from the LSP
* (Computations are done in Q24)
*
* The expansion is performed using the following recursion:
*
* f[0] = 1;
* tmp = -2.0 * lsp[0];
* f[1] = tmp;
* for (i=2; i<=5; i++) {
* b = -2.0 * lsp[2*i-2];
* f[i] = tmp*f[i-1] + 2.0*f[i-2];
* for (j=i; j>=2; j--) {
* f[j] = f[j] + tmp*f[j-1] + f[j-2];
* }
* f[i] = f[i] + tmp;
* }
*---------------------------------------------------------------*/
void WebRtcIlbcfix_GetLspPoly(
WebRtc_Word16 *lsp, /* (i) LSP in Q15 */
WebRtc_Word32 *f) /* (o) polonymial in Q24 */
{
WebRtc_Word32 tmpW32;
int i, j;
WebRtc_Word16 high, low;
WebRtc_Word16 *lspPtr;
WebRtc_Word32 *fPtr;
lspPtr = lsp;
fPtr = f;
/* f[0] = 1.0 (Q24) */
(*fPtr) = (WebRtc_Word32)16777216;
fPtr++;
(*fPtr) = WEBRTC_SPL_MUL((*lspPtr), -1024);
fPtr++;
lspPtr+=2;
for(i=2; i<=5; i++)
{
(*fPtr) = fPtr[-2];
for(j=i; j>1; j--)
{
/* Compute f[j] = f[j] + tmp*f[j-1] + f[j-2]; */
high = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(fPtr[-1], 16);
low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(fPtr[-1]-WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)high),16), 1);
tmpW32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(high, (*lspPtr)), 2) +
WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16_RSFT(low, (*lspPtr), 15), 2);
(*fPtr) += fPtr[-2];
(*fPtr) -= tmpW32;
fPtr--;
}
(*fPtr) -= (WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)(*lspPtr), 10);
fPtr+=i;
lspPtr+=2;
}
return;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GetLspPoly.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
#include "defines.h"
/*----------------------------------------------------------------*
* Construct the polynomials F1(z) and F2(z) from the LSP
* (Computations are done in Q24)
*
* The expansion is performed using the following recursion:
*
* f[0] = 1;
* tmp = -2.0 * lsp[0];
* f[1] = tmp;
* for (i=2; i<=5; i++) {
* b = -2.0 * lsp[2*i-2];
* f[i] = tmp*f[i-1] + 2.0*f[i-2];
* for (j=i; j>=2; j--) {
* f[j] = f[j] + tmp*f[j-1] + f[j-2];
* }
* f[i] = f[i] + tmp;
* }
*---------------------------------------------------------------*/
void WebRtcIlbcfix_GetLspPoly(
WebRtc_Word16 *lsp, /* (i) LSP in Q15 */
WebRtc_Word32 *f); /* (o) polonymial in Q24 */
#endif

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GetSyncSeq.c
******************************************************************/
#include "defines.h"
#include "constants.h"
#include "refiner.h"
#include "nearest_neighbor.h"
/*----------------------------------------------------------------*
* get the pitch-synchronous sample sequence
*---------------------------------------------------------------*/
void WebRtcIlbcfix_GetSyncSeq(
iLBC_Dec_Inst_t *iLBCdec_inst,
/* (i) Decoder state */
WebRtc_Word16 *idata, /* (i) original data */
WebRtc_Word16 idatal, /* (i) dimension of data */
WebRtc_Word16 centerStartPos, /* (i) where current block starts */
WebRtc_Word16 *period, /* (i) rough-pitch-period array (Q-2) */
WebRtc_Word16 *plocs, /* (i) where periods of period array are taken (Q-2) */
WebRtc_Word16 periodl, /* (i) dimension period array */
WebRtc_Word16 hl, /* (i) 2*hl+1 is the number of sequences */
WebRtc_Word16 *surround /* (i/o) The contribution from this sequence
summed with earlier contributions */
){
WebRtc_Word16 i,centerEndPos,q;
/* Stack based */
WebRtc_Word16 lagBlock[2*ENH_HL+1];
WebRtc_Word16 blockStartPos[2*ENH_HL+1]; /* Defines the position to search around (Q2) */
WebRtc_Word16 plocs2[ENH_PLOCSL];
centerEndPos=centerStartPos+ENH_BLOCKL-1;
/* present (find predicted lag from this position) */
WebRtcIlbcfix_NearestNeighbor(iLBCdec_inst, lagBlock+hl,plocs,
(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(2, (centerStartPos+centerEndPos)),
periodl);
blockStartPos[hl]=(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(4, centerStartPos);
/* past (find predicted position and perform a refined
search to find the best sequence) */
for(q=hl-1;q>=0;q--) {
blockStartPos[q]=blockStartPos[q+1]-period[lagBlock[q+1]];
WebRtcIlbcfix_NearestNeighbor(iLBCdec_inst, lagBlock+q, plocs,
(WebRtc_Word16)(blockStartPos[q] + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(4, ENH_BLOCKL_HALF)-period[lagBlock[q+1]]),
periodl);
if((blockStartPos[q]-(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(4, ENH_OVERHANG))>=0) {
/* Find the best possible sequence in the 4 times upsampled
domain around blockStartPos+q */
WebRtcIlbcfix_Refiner(iLBCdec_inst, blockStartPos+q,idata,idatal,
centerStartPos,blockStartPos[q],surround,WebRtcIlbcfix_kEnhWt[q]);
} else {
/* Don't add anything since this sequence would
be outside the buffer */
}
}
/* future (find predicted position and perform a refined
search to find the best sequence) */
for(i=0;i<periodl;i++) {
plocs2[i]=(plocs[i]-period[i]);
}
for(q=hl+1;q<=WEBRTC_SPL_MUL_16_16(2, hl);q++) {
WebRtcIlbcfix_NearestNeighbor(iLBCdec_inst, lagBlock+q,plocs2,
(WebRtc_Word16)(blockStartPos[q-1]+
(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(4, ENH_BLOCKL_HALF)),periodl);
blockStartPos[q]=blockStartPos[q-1]+period[lagBlock[q]];
if( (blockStartPos[q]+(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(4, (ENH_BLOCKL+ENH_OVERHANG)))
<
(WebRtc_Word16)WEBRTC_SPL_MUL_16_16(4, idatal)) {
/* Find the best possible sequence in the 4 times upsampled
domain around blockStartPos+q */
WebRtcIlbcfix_Refiner(iLBCdec_inst, blockStartPos+q, idata, idatal,
centerStartPos,blockStartPos[q],surround,WebRtcIlbcfix_kEnhWt[2*hl-q]);
}
else {
/* Don't add anything since this sequence would
be outside the buffer */
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_GetSyncSeq.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
#include "defines.h"
/*----------------------------------------------------------------*
* get the pitch-synchronous sample sequence
*---------------------------------------------------------------*/
void WebRtcIlbcfix_GetSyncSeq(
iLBC_Dec_Inst_t *iLBCdec_inst,
/* (i) Decoder state */
WebRtc_Word16 *idata, /* (i) original data */
WebRtc_Word16 idatal, /* (i) dimension of data */
WebRtc_Word16 centerStartPos, /* (i) where current block starts */
WebRtc_Word16 *period, /* (i) rough-pitch-period array (Q-2) */
WebRtc_Word16 *plocs, /* (i) where periods of period array are taken (Q-2) */
WebRtc_Word16 periodl, /* (i) dimension period array */
WebRtc_Word16 hl, /* (i) 2*hl+1 is the number of sequences */
WebRtc_Word16 *surround /* (i/o) The contribution from this sequence
summed with earlier contributions */
);
#endif

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_HpInput.c
******************************************************************/
#include "defines.h"
/*----------------------------------------------------------------*
* high-pass filter of input with *0.5 and saturation
*---------------------------------------------------------------*/
void WebRtcIlbcfix_HpInput(
WebRtc_Word16 *signal, /* (i/o) signal vector */
WebRtc_Word16 *ba, /* (i) B- and A-coefficients (2:nd order)
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
is assumed to be 1.0 */
WebRtc_Word16 *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
yhi[n-2] ylow[n-2] */
WebRtc_Word16 *x, /* (i/o) Filter state x[n-1] x[n-2] */
WebRtc_Word16 len) /* (i) Number of samples to filter */
{
int i;
WebRtc_Word32 tmpW32;
WebRtc_Word32 tmpW32b;
for (i=0; i<len; i++) {
/*
y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
+ (-a[1])*y[i-1] + (-a[2])*y[i-2];
*/
tmpW32 = WEBRTC_SPL_MUL_16_16(y[1], ba[3]); /* (-a[1])*y[i-1] (low part) */
tmpW32 += WEBRTC_SPL_MUL_16_16(y[3], ba[4]); /* (-a[2])*y[i-2] (low part) */
tmpW32 = (tmpW32>>15);
tmpW32 += WEBRTC_SPL_MUL_16_16(y[0], ba[3]); /* (-a[1])*y[i-1] (high part) */
tmpW32 += WEBRTC_SPL_MUL_16_16(y[2], ba[4]); /* (-a[2])*y[i-2] (high part) */
tmpW32 = (tmpW32<<1);
tmpW32 += WEBRTC_SPL_MUL_16_16(signal[i], ba[0]); /* b[0]*x[0] */
tmpW32 += WEBRTC_SPL_MUL_16_16(x[0], ba[1]); /* b[1]*x[i-1] */
tmpW32 += WEBRTC_SPL_MUL_16_16(x[1], ba[2]); /* b[2]*x[i-2] */
/* Update state (input part) */
x[1] = x[0];
x[0] = signal[i];
/* Rounding in Q(12+1), i.e. add 2^12 */
tmpW32b = tmpW32 + 4096;
/* Saturate (to 2^28) so that the HP filtered signal does not overflow */
tmpW32b = WEBRTC_SPL_SAT((WebRtc_Word32)268435455, tmpW32b, (WebRtc_Word32)-268435456);
/* Convert back to Q0 and multiply with 0.5 */
signal[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32b, 13);
/* Update state (filtered part) */
y[2] = y[0];
y[3] = y[1];
/* upshift tmpW32 by 3 with saturation */
if (tmpW32>268435455) {
tmpW32 = WEBRTC_SPL_WORD32_MAX;
} else if (tmpW32<-268435456) {
tmpW32 = WEBRTC_SPL_WORD32_MIN;
} else {
tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
}
y[0] = (WebRtc_Word16)(tmpW32 >> 16);
y[1] = (WebRtc_Word16)((tmpW32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)y[0], 16))>>1);
}
return;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_HpInput.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
#include "defines.h"
void WebRtcIlbcfix_HpInput(
WebRtc_Word16 *signal, /* (i/o) signal vector */
WebRtc_Word16 *ba, /* (i) B- and A-coefficients (2:nd order)
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
is assumed to be 1.0 */
WebRtc_Word16 *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
yhi[n-2] ylow[n-2] */
WebRtc_Word16 *x, /* (i/o) Filter state x[n-1] x[n-2] */
WebRtc_Word16 len); /* (i) Number of samples to filter */
#endif

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_HpOutput.c
******************************************************************/
#include "defines.h"
/*----------------------------------------------------------------*
* high-pass filter of output and *2 with saturation
*---------------------------------------------------------------*/
void WebRtcIlbcfix_HpOutput(
WebRtc_Word16 *signal, /* (i/o) signal vector */
WebRtc_Word16 *ba, /* (i) B- and A-coefficients (2:nd order)
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
is assumed to be 1.0 */
WebRtc_Word16 *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
yhi[n-2] ylow[n-2] */
WebRtc_Word16 *x, /* (i/o) Filter state x[n-1] x[n-2] */
WebRtc_Word16 len) /* (i) Number of samples to filter */
{
int i;
WebRtc_Word32 tmpW32;
WebRtc_Word32 tmpW32b;
for (i=0; i<len; i++) {
/*
y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]
+ (-a[1])*y[i-1] + (-a[2])*y[i-2];
*/
tmpW32 = WEBRTC_SPL_MUL_16_16(y[1], ba[3]); /* (-a[1])*y[i-1] (low part) */
tmpW32 += WEBRTC_SPL_MUL_16_16(y[3], ba[4]); /* (-a[2])*y[i-2] (low part) */
tmpW32 = (tmpW32>>15);
tmpW32 += WEBRTC_SPL_MUL_16_16(y[0], ba[3]); /* (-a[1])*y[i-1] (high part) */
tmpW32 += WEBRTC_SPL_MUL_16_16(y[2], ba[4]); /* (-a[2])*y[i-2] (high part) */
tmpW32 = (tmpW32<<1);
tmpW32 += WEBRTC_SPL_MUL_16_16(signal[i], ba[0]); /* b[0]*x[0] */
tmpW32 += WEBRTC_SPL_MUL_16_16(x[0], ba[1]); /* b[1]*x[i-1] */
tmpW32 += WEBRTC_SPL_MUL_16_16(x[1], ba[2]); /* b[2]*x[i-2] */
/* Update state (input part) */
x[1] = x[0];
x[0] = signal[i];
/* Rounding in Q(12-1), i.e. add 2^10 */
tmpW32b = tmpW32 + 1024;
/* Saturate (to 2^26) so that the HP filtered signal does not overflow */
tmpW32b = WEBRTC_SPL_SAT((WebRtc_Word32)67108863, tmpW32b, (WebRtc_Word32)-67108864);
/* Convert back to Q0 and multiply with 2 */
signal[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32b, 11);
/* Update state (filtered part) */
y[2] = y[0];
y[3] = y[1];
/* upshift tmpW32 by 3 with saturation */
if (tmpW32>268435455) {
tmpW32 = WEBRTC_SPL_WORD32_MAX;
} else if (tmpW32<-268435456) {
tmpW32 = WEBRTC_SPL_WORD32_MIN;
} else {
tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
}
y[0] = (WebRtc_Word16)(tmpW32 >> 16);
y[1] = (WebRtc_Word16)((tmpW32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)y[0], 16))>>1);
}
return;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_HpOutput.h
******************************************************************/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
#include "defines.h"
void WebRtcIlbcfix_HpOutput(
WebRtc_Word16 *signal, /* (i/o) signal vector */
WebRtc_Word16 *ba, /* (i) B- and A-coefficients (2:nd order)
{b[0] b[1] b[2] -a[1] -a[2]} a[0]
is assumed to be 1.0 */
WebRtc_Word16 *y, /* (i/o) Filter state yhi[n-1] ylow[n-1]
yhi[n-2] ylow[n-2] */
WebRtc_Word16 *x, /* (i/o) Filter state x[n-1] x[n-2] */
WebRtc_Word16 len); /* (i) Number of samples to filter */
#endif

View File

@@ -0,0 +1,255 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
iLBCInterface.c
******************************************************************/
#include "ilbc.h"
#include "defines.h"
#include "init_encode.h"
#include "encode.h"
#include "init_decode.h"
#include "decode.h"
#include <stdlib.h>
WebRtc_Word16 WebRtcIlbcfix_EncoderAssign(iLBC_encinst_t **iLBC_encinst, WebRtc_Word16 *ILBCENC_inst_Addr, WebRtc_Word16 *size) {
*iLBC_encinst=(iLBC_encinst_t*)ILBCENC_inst_Addr;
*size=sizeof(iLBC_Enc_Inst_t)/sizeof(WebRtc_Word16);
if (*iLBC_encinst!=NULL) {
return(0);
} else {
return(-1);
}
}
WebRtc_Word16 WebRtcIlbcfix_DecoderAssign(iLBC_decinst_t **iLBC_decinst, WebRtc_Word16 *ILBCDEC_inst_Addr, WebRtc_Word16 *size) {
*iLBC_decinst=(iLBC_decinst_t*)ILBCDEC_inst_Addr;
*size=sizeof(iLBC_Dec_Inst_t)/sizeof(WebRtc_Word16);
if (*iLBC_decinst!=NULL) {
return(0);
} else {
return(-1);
}
}
WebRtc_Word16 WebRtcIlbcfix_EncoderCreate(iLBC_encinst_t **iLBC_encinst) {
*iLBC_encinst=(iLBC_encinst_t*)malloc(sizeof(iLBC_Enc_Inst_t));
if (*iLBC_encinst!=NULL) {
return(0);
} else {
return(-1);
}
}
WebRtc_Word16 WebRtcIlbcfix_DecoderCreate(iLBC_decinst_t **iLBC_decinst) {
*iLBC_decinst=(iLBC_decinst_t*)malloc(sizeof(iLBC_Dec_Inst_t));
if (*iLBC_decinst!=NULL) {
return(0);
} else {
return(-1);
}
}
WebRtc_Word16 WebRtcIlbcfix_EncoderFree(iLBC_encinst_t *iLBC_encinst) {
free(iLBC_encinst);
return(0);
}
WebRtc_Word16 WebRtcIlbcfix_DecoderFree(iLBC_decinst_t *iLBC_decinst) {
free(iLBC_decinst);
return(0);
}
WebRtc_Word16 WebRtcIlbcfix_EncoderInit(iLBC_encinst_t *iLBCenc_inst, WebRtc_Word16 mode)
{
if ((mode==20)||(mode==30)) {
WebRtcIlbcfix_InitEncode((iLBC_Enc_Inst_t*) iLBCenc_inst, mode);
return(0);
} else {
return(-1);
}
}
WebRtc_Word16 WebRtcIlbcfix_Encode(iLBC_encinst_t *iLBCenc_inst, WebRtc_Word16 *speechIn, WebRtc_Word16 len, WebRtc_Word16 *encoded) {
WebRtc_Word16 pos = 0;
WebRtc_Word16 encpos = 0;
if ((len != ((iLBC_Enc_Inst_t*)iLBCenc_inst)->blockl) &&
#ifdef SPLIT_10MS
(len != 80) &&
#endif
(len != 2*((iLBC_Enc_Inst_t*)iLBCenc_inst)->blockl) &&
(len != 3*((iLBC_Enc_Inst_t*)iLBCenc_inst)->blockl))
{
/* A maximum of 3 frames/packet is allowed */
return(-1);
} else {
/* call encoder */
while (pos<len) {
WebRtcIlbcfix_EncodeImpl((WebRtc_UWord16*) &encoded[encpos], &speechIn[pos], (iLBC_Enc_Inst_t*) iLBCenc_inst);
#ifdef SPLIT_10MS
pos += 80;
if(((iLBC_Enc_Inst_t*)iLBCenc_inst)->section == 0)
#else
pos += ((iLBC_Enc_Inst_t*)iLBCenc_inst)->blockl;
#endif
encpos += ((iLBC_Enc_Inst_t*)iLBCenc_inst)->no_of_words;
}
return (encpos*2);
}
}
WebRtc_Word16 WebRtcIlbcfix_DecoderInit(iLBC_decinst_t *iLBCdec_inst, WebRtc_Word16 mode) {
if ((mode==20)||(mode==30)) {
WebRtcIlbcfix_InitDecode((iLBC_Dec_Inst_t*) iLBCdec_inst, mode, 1);
return(0);
} else {
return(-1);
}
}
WebRtc_Word16 WebRtcIlbcfix_DecoderInit20Ms(iLBC_decinst_t *iLBCdec_inst) {
WebRtcIlbcfix_InitDecode((iLBC_Dec_Inst_t*) iLBCdec_inst, 20, 1);
return(0);
}
WebRtc_Word16 WebRtcIlbcfix_Decoderinit30Ms(iLBC_decinst_t *iLBCdec_inst) {
WebRtcIlbcfix_InitDecode((iLBC_Dec_Inst_t*) iLBCdec_inst, 30, 1);
return(0);
}
WebRtc_Word16 WebRtcIlbcfix_Decode(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType)
{
int i=0;
/* Allow for automatic switching between the frame sizes
(although you do get some discontinuity) */
if ((len==((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)||
(len==2*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)||
(len==3*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)) {
/* ok, do nothing */
} else {
/* Test if the mode has changed */
if (((iLBC_Dec_Inst_t*)iLBCdec_inst)->mode==20) {
if ((len==NO_OF_BYTES_30MS)||
(len==2*NO_OF_BYTES_30MS)||
(len==3*NO_OF_BYTES_30MS)) {
WebRtcIlbcfix_InitDecode(((iLBC_Dec_Inst_t*)iLBCdec_inst), 30, ((iLBC_Dec_Inst_t*)iLBCdec_inst)->use_enhancer);
} else {
/* Unsupported frame length */
return(-1);
}
} else {
if ((len==NO_OF_BYTES_20MS)||
(len==2*NO_OF_BYTES_20MS)||
(len==3*NO_OF_BYTES_20MS)) {
WebRtcIlbcfix_InitDecode(((iLBC_Dec_Inst_t*)iLBCdec_inst), 20, ((iLBC_Dec_Inst_t*)iLBCdec_inst)->use_enhancer);
} else {
/* Unsupported frame length */
return(-1);
}
}
}
while ((i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)<len) {
WebRtcIlbcfix_DecodeImpl(&decoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl], (WebRtc_UWord16*) &encoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_words], (iLBC_Dec_Inst_t*) iLBCdec_inst, 1);
i++;
}
/* iLBC does not support VAD/CNG yet */
*speechType=1;
return(i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl);
}
WebRtc_Word16 WebRtcIlbcfix_Decode20Ms(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType)
{
int i=0;
if ((len==((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)||
(len==2*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)||
(len==3*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)) {
/* ok, do nothing */
} else {
return(-1);
}
while ((i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)<len) {
WebRtcIlbcfix_DecodeImpl(&decoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl], (WebRtc_UWord16*) &encoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_words], (iLBC_Dec_Inst_t*) iLBCdec_inst, 1);
i++;
}
/* iLBC does not support VAD/CNG yet */
*speechType=1;
return(i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl);
}
WebRtc_Word16 WebRtcIlbcfix_Decode30Ms(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType)
{
int i=0;
if ((len==((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)||
(len==2*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)||
(len==3*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)) {
/* ok, do nothing */
} else {
return(-1);
}
while ((i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_bytes)<len) {
WebRtcIlbcfix_DecodeImpl(&decoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl], (WebRtc_UWord16*) &encoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->no_of_words], (iLBC_Dec_Inst_t*) iLBCdec_inst, 1);
i++;
}
/* iLBC does not support VAD/CNG yet */
*speechType=1;
return(i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl);
}
WebRtc_Word16 WebRtcIlbcfix_DecodePlc(iLBC_decinst_t *iLBCdec_inst, WebRtc_Word16 *decoded, WebRtc_Word16 noOfLostFrames) {
int i;
WebRtc_UWord16 dummy;
for (i=0;i<noOfLostFrames;i++) {
/* call decoder */
WebRtcIlbcfix_DecodeImpl(&decoded[i*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl], &dummy, (iLBC_Dec_Inst_t*) iLBCdec_inst, 0);
}
return (noOfLostFrames*((iLBC_Dec_Inst_t*)iLBCdec_inst)->blockl);
}
WebRtc_Word16 WebRtcIlbcfix_NetEqPlc(iLBC_decinst_t *iLBCdec_inst, WebRtc_Word16 *decoded, WebRtc_Word16 noOfLostFrames) {
/* Two input parameters not used, but needed for function pointers in NetEQ */
decoded = decoded;
noOfLostFrames = noOfLostFrames;
WebRtcSpl_MemSetW16(((iLBC_Dec_Inst_t*)iLBCdec_inst)->enh_buf, 0, ENH_BUFL);
((iLBC_Dec_Inst_t*)iLBCdec_inst)->prev_enh_pl = 2;
return (0);
}
void WebRtcIlbcfix_version(WebRtc_Word8 *version)
{
strcpy((char*)version, "1.1.0");
}

View File

@@ -0,0 +1,177 @@
# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
{
'includes': [
'../../../../../../common_settings.gypi', # Common settings
],
'targets': [
{
'target_name': 'iLBC',
'type': '<(library)',
'dependencies': [
'../../../../../../common_audio/signal_processing_library/main/source/spl.gyp:spl',
],
'include_dirs': [
'../interface',
],
'direct_dependent_settings': {
'include_dirs': [
'../interface',
],
},
'sources': [
'../interface/ilbc.h',
'abs_quant.c',
'abs_quant_loop.c',
'augmented_cb_corr.c',
'bw_expand.c',
'cb_construct.c',
'cb_mem_energy.c',
'cb_mem_energy_augmentation.c',
'cb_mem_energy_calc.c',
'cb_search.c',
'cb_search_core.c',
'cb_update_best_index.c',
'chebyshev.c',
'comp_corr.c',
'constants.c',
'create_augmented_vec.c',
'decode.c',
'decode_residual.c',
'decoder_interpolate_lsf.c',
'do_plc.c',
'encode.c',
'energy_inverse.c',
'enh_upsample.c',
'enhancer.c',
'enhancer_interface.c',
'filtered_cb_vecs.c',
'frame_classify.c',
'gain_dequant.c',
'gain_quant.c',
'get_cd_vec.c',
'get_lsp_poly.c',
'get_sync_seq.c',
'hp_input.c',
'hp_output.c',
'ilbc.c',
'index_conv_dec.c',
'index_conv_enc.c',
'init_decode.c',
'init_encode.c',
'interpolate.c',
'interpolate_samples.c',
'lpc_encode.c',
'lsf_check.c',
'lsf_interpolate_to_poly_dec.c',
'lsf_interpolate_to_poly_enc.c',
'lsf_to_lsp.c',
'lsf_to_poly.c',
'lsp_to_lsf.c',
'my_corr.c',
'nearest_neighbor.c',
'pack_bits.c',
'poly_to_lsf.c',
'poly_to_lsp.c',
'refiner.c',
'simple_interpolate_lsf.c',
'simple_lpc_analysis.c',
'simple_lsf_dequant.c',
'simple_lsf_quant.c',
'smooth.c',
'smooth_out_data.c',
'sort_sq.c',
'split_vq.c',
'state_construct.c',
'state_search.c',
'swap_bytes.c',
'unpack_bits.c',
'vq3.c',
'vq4.c',
'window32_w32.c',
'xcorr_coef.c',
'abs_quant.h',
'abs_quant_loop.h',
'augmented_cb_corr.h',
'bw_expand.h',
'cb_construct.h',
'cb_mem_energy.h',
'cb_mem_energy_augmentation.h',
'cb_mem_energy_calc.h',
'cb_search.h',
'cb_search_core.h',
'cb_update_best_index.h',
'chebyshev.h',
'comp_corr.h',
'constants.h',
'create_augmented_vec.h',
'decode.h',
'decode_residual.h',
'decoder_interpolate_lsf.h',
'do_plc.h',
'encode.h',
'energy_inverse.h',
'enh_upsample.h',
'enhancer.h',
'enhancer_interface.h',
'filtered_cb_vecs.h',
'frame_classify.h',
'gain_dequant.h',
'gain_quant.h',
'get_cd_vec.h',
'get_lsp_poly.h',
'get_sync_seq.h',
'hp_input.h',
'hp_output.h',
'defines.h',
'index_conv_dec.h',
'index_conv_enc.h',
'init_decode.h',
'init_encode.h',
'interpolate.h',
'interpolate_samples.h',
'lpc_encode.h',
'lsf_check.h',
'lsf_interpolate_to_poly_dec.h',
'lsf_interpolate_to_poly_enc.h',
'lsf_to_lsp.h',
'lsf_to_poly.h',
'lsp_to_lsf.h',
'my_corr.h',
'nearest_neighbor.h',
'pack_bits.h',
'poly_to_lsf.h',
'poly_to_lsp.h',
'refiner.h',
'simple_interpolate_lsf.h',
'simple_lpc_analysis.h',
'simple_lsf_dequant.h',
'simple_lsf_quant.h',
'smooth.h',
'smooth_out_data.h',
'sort_sq.h',
'split_vq.h',
'state_construct.h',
'state_search.h',
'swap_bytes.h',
'unpack_bits.h',
'vq3.h',
'vq4.h',
'window32_w32.h',
'xcorr_coef.h',
],
},
],
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* ilbc.h
*
* This header file contains all of the API's for iLBC.
*
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_INTERFACE_ILBC_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_INTERFACE_ILBC_H_
/*
* Define the fixpoint numeric formats
*/
#include "typedefs.h"
/*
* Solution to support multiple instances
* Customer has to cast instance to proper type
*/
typedef struct iLBC_encinst_t_ iLBC_encinst_t;
typedef struct iLBC_decinst_t_ iLBC_decinst_t;
/*
* Comfort noise constants
*/
#define ILBC_SPEECH 1
#define ILBC_CNG 2
#ifdef __cplusplus
extern "C" {
#endif
/****************************************************************************
* WebRtcIlbcfix_XxxAssign(...)
*
* These functions assigns the encoder/decoder instance to the specified
* memory location
*
* Input:
* - XXX_xxxinst : Pointer to created instance that should be
* assigned
* - ILBCXXX_inst_Addr : Pointer to the desired memory space
* - size : The size that this structure occupies (in Word16)
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_EncoderAssign(iLBC_encinst_t **iLBC_encinst,
WebRtc_Word16 *ILBCENC_inst_Addr,
WebRtc_Word16 *size);
WebRtc_Word16 WebRtcIlbcfix_DecoderAssign(iLBC_decinst_t **iLBC_decinst,
WebRtc_Word16 *ILBCDEC_inst_Addr,
WebRtc_Word16 *size);
/****************************************************************************
* WebRtcIlbcfix_XxxAssign(...)
*
* These functions create a instance to the specified structure
*
* Input:
* - XXX_inst : Pointer to created instance that should be created
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_EncoderCreate(iLBC_encinst_t **iLBC_encinst);
WebRtc_Word16 WebRtcIlbcfix_DecoderCreate(iLBC_decinst_t **iLBC_decinst);
/****************************************************************************
* WebRtcIlbcfix_XxxFree(...)
*
* These functions frees the dynamic memory of a specified instance
*
* Input:
* - XXX_inst : Pointer to created instance that should be freed
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_EncoderFree(iLBC_encinst_t *iLBC_encinst);
WebRtc_Word16 WebRtcIlbcfix_DecoderFree(iLBC_decinst_t *iLBC_decinst);
/****************************************************************************
* WebRtcIlbcfix_EncoderInit(...)
*
* This function initializes a iLBC instance
*
* Input:
* - iLBCenc_inst : iLBC instance, i.e. the user that should receive
* be initialized
* - frameLen : The frame length of the codec 20/30 (ms)
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_EncoderInit(iLBC_encinst_t *iLBCenc_inst,
WebRtc_Word16 frameLen);
/****************************************************************************
* WebRtcIlbcfix_Encode(...)
*
* This function encodes one iLBC frame. Input speech length has be a
* multiple of the frame length.
*
* Input:
* - iLBCenc_inst : iLBC instance, i.e. the user that should encode
* a package
* - speechIn : Input speech vector
* - len : Samples in speechIn (160, 240, 320 or 480)
*
* Output:
* - encoded : The encoded data vector
*
* Return value : >0 - Length (in bytes) of coded data
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_Encode(iLBC_encinst_t *iLBCenc_inst,
WebRtc_Word16 *speechIn,
WebRtc_Word16 len,
WebRtc_Word16 *encoded);
/****************************************************************************
* WebRtcIlbcfix_DecoderInit(...)
*
* This function initializes a iLBC instance with either 20 or 30 ms frames
* Alternatively the WebRtcIlbcfix_DecoderInit_XXms can be used. Then it's
* not needed to specify the frame length with a variable.
*
* Input:
* - iLBC_decinst_t : iLBC instance, i.e. the user that should receive
* be initialized
* - frameLen : The frame length of the codec 20/30 (ms)
*
* Return value : 0 - Ok
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_DecoderInit(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 frameLen);
WebRtc_Word16 WebRtcIlbcfix_DecoderInit20Ms(iLBC_decinst_t *iLBCdec_inst);
WebRtc_Word16 WebRtcIlbcfix_Decoderinit30Ms(iLBC_decinst_t *iLBCdec_inst);
/****************************************************************************
* WebRtcIlbcfix_Decode(...)
*
* This function decodes a packet with iLBC frame(s). Output speech length
* will be a multiple of 160 or 240 samples ((160 or 240)*frames/packet).
*
* Input:
* - iLBCdec_inst : iLBC instance, i.e. the user that should decode
* a packet
* - encoded : Encoded iLBC frame(s)
* - len : Bytes in encoded vector
*
* Output:
* - decoded : The decoded vector
* - speechType : 1 normal, 2 CNG
*
* Return value : >0 - Samples in decoded vector
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_Decode(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16* encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType);
WebRtc_Word16 WebRtcIlbcfix_Decode20Ms(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType);
WebRtc_Word16 WebRtcIlbcfix_Decode30Ms(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *encoded,
WebRtc_Word16 len,
WebRtc_Word16 *decoded,
WebRtc_Word16 *speechType);
/****************************************************************************
* WebRtcIlbcfix_DecodePlc(...)
*
* This function conducts PLC for iLBC frame(s). Output speech length
* will be a multiple of 160 or 240 samples.
*
* Input:
* - iLBCdec_inst : iLBC instance, i.e. the user that should perform
* a PLC
* - noOfLostFrames : Number of PLC frames to produce
*
* Output:
* - decoded : The "decoded" vector
*
* Return value : >0 - Samples in decoded PLC vector
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_DecodePlc(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *decoded,
WebRtc_Word16 noOfLostFrames);
/****************************************************************************
* WebRtcIlbcfix_NetEqPlc(...)
*
* This function updates the decoder when a packet loss has occured, but it
* does not produce any PLC data. Function can be used if another PLC method
* is used (i.e NetEq).
*
* Input:
* - iLBCdec_inst : iLBC instance that should be updated
* - noOfLostFrames : Number of lost frames
*
* Output:
* - decoded : The "decoded" vector (nothing in this case)
*
* Return value : >0 - Samples in decoded PLC vector
* -1 - Error
*/
WebRtc_Word16 WebRtcIlbcfix_NetEqPlc(iLBC_decinst_t *iLBCdec_inst,
WebRtc_Word16 *decoded,
WebRtc_Word16 noOfLostFrames);
/****************************************************************************
* WebRtcIlbcfix_version(...)
*
* This function returns the version number of iLBC
*
* Output:
* - version : Version number of iLBC (maximum 20 char)
*/
void WebRtcIlbcfix_version(WebRtc_Word8 *version);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,396 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_CbSearch.c
******************************************************************/
#include "defines.h"
#include "gain_quant.h"
#include "filtered_cb_vecs.h"
#include "constants.h"
#include "cb_mem_energy.h"
#include "interpolate_samples.h"
#include "cb_mem_energy_augmentation.h"
#include "cb_search_core.h"
#include "energy_inverse.h"
#include "augmented_cb_corr.h"
#include "cb_update_best_index.h"
#include "create_augmented_vec.h"
/*----------------------------------------------------------------*
* Search routine for codebook encoding and gain quantization.
*----------------------------------------------------------------*/
void WebRtcIlbcfix_CbSearch(
iLBC_Enc_Inst_t *iLBCenc_inst,
/* (i) the encoder state structure */
WebRtc_Word16 *index, /* (o) Codebook indices */
WebRtc_Word16 *gain_index, /* (o) Gain quantization indices */
WebRtc_Word16 *intarget, /* (i) Target vector for encoding */
WebRtc_Word16 *decResidual,/* (i) Decoded residual for codebook construction */
WebRtc_Word16 lMem, /* (i) Length of buffer */
WebRtc_Word16 lTarget, /* (i) Length of vector */
WebRtc_Word16 *weightDenum,/* (i) weighting filter coefficients in Q12 */
WebRtc_Word16 block /* (i) the subblock number */
) {
WebRtc_Word16 i, j, stage, range;
WebRtc_Word16 *pp, scale, tmp;
WebRtc_Word16 bits, temp1, temp2;
WebRtc_Word16 base_size;
WebRtc_Word32 codedEner, targetEner;
WebRtc_Word16 gains[CB_NSTAGES+1];
WebRtc_Word16 *cb_vecPtr;
WebRtc_Word16 indexOffset, sInd, eInd;
WebRtc_Word32 CritMax=0;
WebRtc_Word16 shTotMax=WEBRTC_SPL_WORD16_MIN;
WebRtc_Word16 bestIndex=0;
WebRtc_Word16 bestGain=0;
WebRtc_Word16 indexNew, CritNewSh;
WebRtc_Word32 CritNew;
WebRtc_Word32 *cDotPtr;
WebRtc_Word16 noOfZeros;
WebRtc_Word16 *gainPtr;
WebRtc_Word32 t32, tmpW32;
WebRtc_Word16 *WebRtcIlbcfix_kGainSq5_ptr;
/* Stack based */
WebRtc_Word16 CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN];
WebRtc_Word32 cDot[128];
WebRtc_Word32 Crit[128];
WebRtc_Word16 targetVec[SUBL+LPC_FILTERORDER];
WebRtc_Word16 cbvectors[CB_MEML];
WebRtc_Word16 codedVec[SUBL];
WebRtc_Word16 interpSamples[20*4];
WebRtc_Word16 interpSamplesFilt[20*4];
WebRtc_Word16 energyW16[CB_EXPAND*128];
WebRtc_Word16 energyShifts[CB_EXPAND*128];
WebRtc_Word16 *inverseEnergy=energyW16; /* Reuse memory */
WebRtc_Word16 *inverseEnergyShifts=energyShifts; /* Reuse memory */
WebRtc_Word16 *buf = &CBbuf[LPC_FILTERORDER];
WebRtc_Word16 *target = &targetVec[LPC_FILTERORDER];
WebRtc_Word16 *aug_vec = (WebRtc_Word16*)cDot; /* length [SUBL], reuse memory */
/* Determine size of codebook sections */
base_size=lMem-lTarget+1;
if (lTarget==SUBL) {
base_size=lMem-19;
}
/* weighting of the CB memory */
noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block];
WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER);
WebRtcSpl_FilterARFastQ12(
decResidual+noOfZeros, buf+noOfZeros,
weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]);
/* weighting of the target vector */
WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER);
WebRtcSpl_FilterARFastQ12(
intarget, target,
weightDenum, LPC_FILTERORDER+1, lTarget);
/* Store target, towards the end codedVec is calculated as
the initial target minus the remaining target */
WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget);
/* Find the highest absolute value to calculate proper
vector scale factor (so that it uses 12 bits) */
temp1 = WebRtcSpl_MaxAbsValueW16(buf, (WebRtc_Word16)lMem);
temp2 = WebRtcSpl_MaxAbsValueW16(target, (WebRtc_Word16)lTarget);
if ((temp1>0)&&(temp2>0)) {
temp1 = WEBRTC_SPL_MAX(temp1, temp2);
scale = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(temp1, temp1));
} else {
/* temp1 or temp2 is negative (maximum was -32768) */
scale = 30;
}
/* Scale to so that a mul-add 40 times does not overflow */
scale = scale - 25;
scale = WEBRTC_SPL_MAX(0, scale);
/* Compute energy of the original target */
targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale);
/* Prepare search over one more codebook section. This section
is created by filtering the original buffer with a filter. */
WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]);
range = WebRtcIlbcfix_kSearchRange[block][0];
if(lTarget == SUBL) {
/* Create the interpolated samples and store them for use in all stages */
/* First section, non-filtered half of the cb */
WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem);
/* Second section, filtered half of the cb */
WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem);
/* Compute the CB vectors' energies for the first cb section (non-filtered) */
WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf,
scale, 20, energyW16, energyShifts);
/* Compute the CB vectors' energies for the second cb section (filtered cb) */
WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors,
scale, (WebRtc_Word16)(base_size+20), energyW16, energyShifts);
/* Compute the CB vectors' energies and store them in the vector
* energyW16. Also the corresponding shift values are stored. The
* energy values are used in all three stages. */
WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
lTarget, energyW16+20, energyShifts+20, scale, base_size);
} else {
/* Compute the CB vectors' energies and store them in the vector
* energyW16. Also the corresponding shift values are stored. The
* energy values are used in all three stages. */
WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
lTarget, energyW16, energyShifts, scale, base_size);
/* Set the energy positions 58-63 and 122-127 to zero
(otherwise they are uninitialized) */
WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range));
WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range));
}
/* Calculate Inverse Energy (energyW16 is already normalized
and will contain the inverse energy in Q29 after this call */
WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND);
/* The gain value computed in the previous stage is used
* as an upper limit to what the next stage gain value
* is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as
* the upper limit. */
gains[0] = 16384;
for (stage=0; stage<CB_NSTAGES; stage++) {
/* Set up memories */
range = WebRtcIlbcfix_kSearchRange[block][stage];
/* initialize search measures */
CritMax=0;
shTotMax=-100;
bestIndex=0;
bestGain=0;
/* loop over lags 40+ in the first codebook section, full search */
cb_vecPtr = buf+lMem-lTarget;
/* Calculate all the cross correlations (augmented part of CB) */
if (lTarget==SUBL) {
WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem,
interpSamples, cDot,
20, 39, scale);
cDotPtr=&cDot[20];
} else {
cDotPtr=cDot;
}
/* Calculate all the cross correlations (main part of CB) */
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1);
/* Adjust the search range for the augmented vectors */
if (lTarget==SUBL) {
range=WebRtcIlbcfix_kSearchRange[block][stage]+20;
} else {
range=WebRtcIlbcfix_kSearchRange[block][stage];
}
indexOffset=0;
/* Search for best index in this part of the vector */
WebRtcIlbcfix_CbSearchCore(
cDot, range, stage, inverseEnergy,
inverseEnergyShifts, Crit,
&indexNew, &CritNew, &CritNewSh);
/* Update the global best index and the corresponding gain */
WebRtcIlbcfix_CbUpdateBestIndex(
CritNew, CritNewSh, (WebRtc_Word16)(indexNew+indexOffset), cDot[indexNew+indexOffset],
inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
&CritMax, &shTotMax, &bestIndex, &bestGain);
sInd=bestIndex-(WebRtc_Word16)(CB_RESRANGE>>1);
eInd=sInd+CB_RESRANGE;
if (sInd<0) {
eInd-=sInd;
sInd=0;
}
if (eInd>=range) {
eInd=range-1;
sInd=eInd-CB_RESRANGE;
}
range = WebRtcIlbcfix_kSearchRange[block][stage];
if (lTarget==SUBL) {
i=sInd;
if (sInd<20) {
WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors+lMem,
interpSamplesFilt, cDot,
(WebRtc_Word16)(sInd+20), (WebRtc_Word16)(WEBRTC_SPL_MIN(39, (eInd+20))), scale);
i=20;
}
cDotPtr=&cDot[WEBRTC_SPL_MAX(0,(20-sInd))];
cb_vecPtr = cbvectors+lMem-20-i;
/* Calculate the cross correlations (main part of the filtered CB) */
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (WebRtc_Word16)(eInd-i+1), scale, -1);
} else {
cDotPtr = cDot;
cb_vecPtr = cbvectors+lMem-lTarget-sInd;
/* Calculate the cross correlations (main part of the filtered CB) */
WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (WebRtc_Word16)(eInd-sInd+1), scale, -1);
}
/* Adjust the search range for the augmented vectors */
indexOffset=base_size+sInd;
/* Search for best index in this part of the vector */
WebRtcIlbcfix_CbSearchCore(
cDot, (WebRtc_Word16)(eInd-sInd+1), stage, inverseEnergy+indexOffset,
inverseEnergyShifts+indexOffset, Crit,
&indexNew, &CritNew, &CritNewSh);
/* Update the global best index and the corresponding gain */
WebRtcIlbcfix_CbUpdateBestIndex(
CritNew, CritNewSh, (WebRtc_Word16)(indexNew+indexOffset), cDot[indexNew],
inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
&CritMax, &shTotMax, &bestIndex, &bestGain);
index[stage] = bestIndex;
bestGain = WebRtcIlbcfix_GainQuant(bestGain,
(WebRtc_Word16)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]);
/* Extract the best (according to measure) codebook vector
Also adjust the index, so that the augmented vectors are last.
Above these vectors were first...
*/
if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {
if(index[stage]<base_size) {
pp=buf+lMem-lTarget-index[stage];
} else {
pp=cbvectors+lMem-lTarget-
index[stage]+base_size;
}
} else {
if (index[stage]<base_size) {
if (index[stage]>=20) {
/* Adjust index and extract vector */
index[stage]-=20;
pp=buf+lMem-lTarget-index[stage];
} else {
/* Adjust index and extract vector */
index[stage]+=(base_size-20);
WebRtcIlbcfix_CreateAugmentedVec((WebRtc_Word16)(index[stage]-base_size+40),
buf+lMem, aug_vec);
pp = aug_vec;
}
} else {
if ((index[stage] - base_size) >= 20) {
/* Adjust index and extract vector */
index[stage]-=20;
pp=cbvectors+lMem-lTarget-
index[stage]+base_size;
} else {
/* Adjust index and extract vector */
index[stage]+=(base_size-20);
WebRtcIlbcfix_CreateAugmentedVec((WebRtc_Word16)(index[stage]-2*base_size+40),
cbvectors+lMem, aug_vec);
pp = aug_vec;
}
}
}
/* Subtract the best codebook vector, according
to measure, from the target vector */
WebRtcSpl_AddAffineVectorToVector(target, pp, (WebRtc_Word16)(-bestGain), (WebRtc_Word32)8192, (WebRtc_Word16)14, (int)lTarget);
/* record quantized gain */
gains[stage+1] = bestGain;
} /* end of Main Loop. for (stage=0;... */
/* Calculte the coded vector (original target - what's left) */
for (i=0;i<lTarget;i++) {
codedVec[i]-=target[i];
}
/* Gain adjustment for energy matching */
codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale);
j=gain_index[0];
temp1 = (WebRtc_Word16)WebRtcSpl_NormW32(codedEner);
temp2 = (WebRtc_Word16)WebRtcSpl_NormW32(targetEner);
if(temp1 < temp2) {
bits = 16 - temp1;
} else {
bits = 16 - temp2;
}
tmp = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(gains[1],gains[1], 14);
targetEner = WEBRTC_SPL_MUL_16_16(
WEBRTC_SPL_SHIFT_W32(targetEner, -bits), tmp);
tmpW32 = ((WebRtc_Word32)(gains[1]-1))<<1;
/* Pointer to the table that contains
gain_sq5TblFIX * gain_sq5TblFIX in Q14 */
gainPtr=(WebRtc_Word16*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0];
temp1 = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(codedEner, -bits);
WebRtcIlbcfix_kGainSq5_ptr = (WebRtc_Word16*)&WebRtcIlbcfix_kGainSq5[j];
/* targetEner and codedEner are in Q(-2*scale) */
for (i=gain_index[0];i<32;i++) {
/* Change the index if
(codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND
gainTbl[i] < 2*gain[0]
*/
t32 = WEBRTC_SPL_MUL_16_16(temp1, (*gainPtr));
t32 = t32 - targetEner;
if (t32 < 0) {
if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) {
j=i;
WebRtcIlbcfix_kGainSq5_ptr = (WebRtc_Word16*)&WebRtcIlbcfix_kGainSq5[i];
}
}
gainPtr++;
}
gain_index[0]=j;
return;
}

View File

@@ -0,0 +1,666 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
constants.c
******************************************************************/
#include "defines.h"
#include "constants.h"
/* HP Filters {b[0] b[1] b[2] -a[1] -a[2]} */
const WebRtc_Word16 WebRtcIlbcfix_kHpInCoefs[5] = {3798, -7596, 3798, 7807, -3733};
const WebRtc_Word16 WebRtcIlbcfix_kHpOutCoefs[5] = {3849, -7699, 3849, 7918, -3833};
/* Window in Q11 to window the energies of the 5 choises (3 for 20ms) in the choise for
the 80 sample start state
*/
const WebRtc_Word16 WebRtcIlbcfix_kStartSequenceEnrgWin[NSUB_MAX-1]= {
1638, 1843, 2048, 1843, 1638
};
/* LP Filter coeffs used for downsampling */
const WebRtc_Word16 WebRtcIlbcfix_kLpFiltCoefs[FILTERORDER_DS_PLUS1]= {
-273, 512, 1297, 1696, 1297, 512, -273
};
/* Constants used in the LPC calculations */
/* Hanning LPC window (in Q15) */
const WebRtc_Word16 WebRtcIlbcfix_kLpcWin[BLOCKL_MAX] = {
6, 22, 50, 89, 139, 200, 272, 355, 449, 554, 669, 795,
932, 1079, 1237, 1405, 1583, 1771, 1969, 2177, 2395, 2622, 2858, 3104,
3359, 3622, 3894, 4175, 4464, 4761, 5066, 5379, 5699, 6026, 6361, 6702,
7050, 7404, 7764, 8130, 8502, 8879, 9262, 9649, 10040, 10436, 10836, 11240,
11647, 12058, 12471, 12887, 13306, 13726, 14148, 14572, 14997, 15423, 15850, 16277,
16704, 17131, 17558, 17983, 18408, 18831, 19252, 19672, 20089, 20504, 20916, 21325,
21730, 22132, 22530, 22924, 23314, 23698, 24078, 24452, 24821, 25185, 25542, 25893,
26238, 26575, 26906, 27230, 27547, 27855, 28156, 28450, 28734, 29011, 29279, 29538,
29788, 30029, 30261, 30483, 30696, 30899, 31092, 31275, 31448, 31611, 31764, 31906,
32037, 32158, 32268, 32367, 32456, 32533, 32600, 32655, 32700, 32733, 32755, 32767,
32767, 32755, 32733, 32700, 32655, 32600, 32533, 32456, 32367, 32268, 32158, 32037,
31906, 31764, 31611, 31448, 31275, 31092, 30899, 30696, 30483, 30261, 30029, 29788,
29538, 29279, 29011, 28734, 28450, 28156, 27855, 27547, 27230, 26906, 26575, 26238,
25893, 25542, 25185, 24821, 24452, 24078, 23698, 23314, 22924, 22530, 22132, 21730,
21325, 20916, 20504, 20089, 19672, 19252, 18831, 18408, 17983, 17558, 17131, 16704,
16277, 15850, 15423, 14997, 14572, 14148, 13726, 13306, 12887, 12471, 12058, 11647,
11240, 10836, 10436, 10040, 9649, 9262, 8879, 8502, 8130, 7764, 7404, 7050,
6702, 6361, 6026, 5699, 5379, 5066, 4761, 4464, 4175, 3894, 3622, 3359,
3104, 2858, 2622, 2395, 2177, 1969, 1771, 1583, 1405, 1237, 1079, 932,
795, 669, 554, 449, 355, 272, 200, 139, 89, 50, 22, 6
};
/* Asymmetric LPC window (in Q15)*/
const WebRtc_Word16 WebRtcIlbcfix_kLpcAsymWin[BLOCKL_MAX] = {
2, 7, 15, 27, 42, 60, 81, 106, 135, 166, 201, 239,
280, 325, 373, 424, 478, 536, 597, 661, 728, 798, 872, 949,
1028, 1111, 1197, 1287, 1379, 1474, 1572, 1674, 1778, 1885, 1995, 2108,
2224, 2343, 2465, 2589, 2717, 2847, 2980, 3115, 3254, 3395, 3538, 3684,
3833, 3984, 4138, 4295, 4453, 4615, 4778, 4944, 5112, 5283, 5456, 5631,
5808, 5987, 6169, 6352, 6538, 6725, 6915, 7106, 7300, 7495, 7692, 7891,
8091, 8293, 8497, 8702, 8909, 9118, 9328, 9539, 9752, 9966, 10182, 10398,
10616, 10835, 11055, 11277, 11499, 11722, 11947, 12172, 12398, 12625, 12852, 13080,
13309, 13539, 13769, 14000, 14231, 14463, 14695, 14927, 15160, 15393, 15626, 15859,
16092, 16326, 16559, 16792, 17026, 17259, 17492, 17725, 17957, 18189, 18421, 18653,
18884, 19114, 19344, 19573, 19802, 20030, 20257, 20483, 20709, 20934, 21157, 21380,
21602, 21823, 22042, 22261, 22478, 22694, 22909, 23123, 23335, 23545, 23755, 23962,
24168, 24373, 24576, 24777, 24977, 25175, 25371, 25565, 25758, 25948, 26137, 26323,
26508, 26690, 26871, 27049, 27225, 27399, 27571, 27740, 27907, 28072, 28234, 28394,
28552, 28707, 28860, 29010, 29157, 29302, 29444, 29584, 29721, 29855, 29987, 30115,
30241, 30364, 30485, 30602, 30717, 30828, 30937, 31043, 31145, 31245, 31342, 31436,
31526, 31614, 31699, 31780, 31858, 31933, 32005, 32074, 32140, 32202, 32261, 32317,
32370, 32420, 32466, 32509, 32549, 32585, 32618, 32648, 32675, 32698, 32718, 32734,
32748, 32758, 32764, 32767, 32767, 32667, 32365, 31863, 31164, 30274, 29197, 27939,
26510, 24917, 23170, 21281, 19261, 17121, 14876, 12540, 10126, 7650, 5126, 2571
};
/* Lag window for LPC (Q31) */
const WebRtc_Word32 WebRtcIlbcfix_kLpcLagWin[LPC_FILTERORDER + 1]={
2147483647, 2144885453, 2137754373, 2125918626, 2109459810,
2088483140, 2063130336, 2033564590, 1999977009, 1962580174,
1921610283};
/* WebRtcIlbcfix_kLpcChirpSyntDenum vector in Q15 corresponding
* floating point vector {1 0.9025 0.9025^2 0.9025^3 ...}
*/
const WebRtc_Word16 WebRtcIlbcfix_kLpcChirpSyntDenum[LPC_FILTERORDER + 1] = {
32767, 29573, 26690, 24087,
21739, 19619, 17707, 15980,
14422, 13016, 11747};
/* WebRtcIlbcfix_kLpcChirpWeightDenum in Q15 corresponding to
* floating point vector {1 0.4222 0.4222^2... }
*/
const WebRtc_Word16 WebRtcIlbcfix_kLpcChirpWeightDenum[LPC_FILTERORDER + 1] = {
32767, 13835, 5841, 2466, 1041, 440,
186, 78, 33, 14, 6};
/* LSF quantization Q13 domain */
const WebRtc_Word16 WebRtcIlbcfix_kLsfCb[64 * 3 + 128 * 3 + 128 * 4] = {
1273, 2238, 3696,
3199, 5309, 8209,
3606, 5671, 7829,
2815, 5262, 8778,
2608, 4027, 5493,
1582, 3076, 5945,
2983, 4181, 5396,
2437, 4322, 6902,
1861, 2998, 4613,
2007, 3250, 5214,
1388, 2459, 4262,
2563, 3805, 5269,
2036, 3522, 5129,
1935, 4025, 6694,
2744, 5121, 7338,
2810, 4248, 5723,
3054, 5405, 7745,
1449, 2593, 4763,
3411, 5128, 6596,
2484, 4659, 7496,
1668, 2879, 4818,
1812, 3072, 5036,
1638, 2649, 3900,
2464, 3550, 4644,
1853, 2900, 4158,
2458, 4163, 5830,
2556, 4036, 6254,
2703, 4432, 6519,
3062, 4953, 7609,
1725, 3703, 6187,
2221, 3877, 5427,
2339, 3579, 5197,
2021, 4633, 7037,
2216, 3328, 4535,
2961, 4739, 6667,
2807, 3955, 5099,
2788, 4501, 6088,
1642, 2755, 4431,
3341, 5282, 7333,
2414, 3726, 5727,
1582, 2822, 5269,
2259, 3447, 4905,
3117, 4986, 7054,
1825, 3491, 5542,
3338, 5736, 8627,
1789, 3090, 5488,
2566, 3720, 4923,
2846, 4682, 7161,
1950, 3321, 5976,
1834, 3383, 6734,
3238, 4769, 6094,
2031, 3978, 5903,
1877, 4068, 7436,
2131, 4644, 8296,
2764, 5010, 8013,
2194, 3667, 6302,
2053, 3127, 4342,
3523, 6595, 10010,
3134, 4457, 5748,
3142, 5819, 9414,
2223, 4334, 6353,
2022, 3224, 4822,
2186, 3458, 5544,
2552, 4757, 6870,
10905, 12917, 14578,
9503, 11485, 14485,
9518, 12494, 14052,
6222, 7487, 9174,
7759, 9186, 10506,
8315, 12755, 14786,
9609, 11486, 13866,
8909, 12077, 13643,
7369, 9054, 11520,
9408, 12163, 14715,
6436, 9911, 12843,
7109, 9556, 11884,
7557, 10075, 11640,
6482, 9202, 11547,
6463, 7914, 10980,
8611, 10427, 12752,
7101, 9676, 12606,
7428, 11252, 13172,
10197, 12955, 15842,
7487, 10955, 12613,
5575, 7858, 13621,
7268, 11719, 14752,
7476, 11744, 13795,
7049, 8686, 11922,
8234, 11314, 13983,
6560, 11173, 14984,
6405, 9211, 12337,
8222, 12054, 13801,
8039, 10728, 13255,
10066, 12733, 14389,
6016, 7338, 10040,
6896, 8648, 10234,
7538, 9170, 12175,
7327, 12608, 14983,
10516, 12643, 15223,
5538, 7644, 12213,
6728, 12221, 14253,
7563, 9377, 12948,
8661, 11023, 13401,
7280, 8806, 11085,
7723, 9793, 12333,
12225, 14648, 16709,
8768, 13389, 15245,
10267, 12197, 13812,
5301, 7078, 11484,
7100, 10280, 11906,
8716, 12555, 14183,
9567, 12464, 15434,
7832, 12305, 14300,
7608, 10556, 12121,
8913, 11311, 12868,
7414, 9722, 11239,
8666, 11641, 13250,
9079, 10752, 12300,
8024, 11608, 13306,
10453, 13607, 16449,
8135, 9573, 10909,
6375, 7741, 10125,
10025, 12217, 14874,
6985, 11063, 14109,
9296, 13051, 14642,
8613, 10975, 12542,
6583, 10414, 13534,
6191, 9368, 13430,
5742, 6859, 9260,
7723, 9813, 13679,
8137, 11291, 12833,
6562, 8973, 10641,
6062, 8462, 11335,
6928, 8784, 12647,
7501, 8784, 10031,
8372, 10045, 12135,
8191, 9864, 12746,
5917, 7487, 10979,
5516, 6848, 10318,
6819, 9899, 11421,
7882, 12912, 15670,
9558, 11230, 12753,
7752, 9327, 11472,
8479, 9980, 11358,
11418, 14072, 16386,
7968, 10330, 14423,
8423, 10555, 12162,
6337, 10306, 14391,
8850, 10879, 14276,
6750, 11885, 15710,
7037, 8328, 9764,
6914, 9266, 13476,
9746, 13949, 15519,
11032, 14444, 16925,
8032, 10271, 11810,
10962, 13451, 15833,
10021, 11667, 13324,
6273, 8226, 12936,
8543, 10397, 13496,
7936, 10302, 12745,
6769, 8138, 10446,
6081, 7786, 11719,
8637, 11795, 14975,
8790, 10336, 11812,
7040, 8490, 10771,
7338, 10381, 13153,
6598, 7888, 9358,
6518, 8237, 12030,
9055, 10763, 12983,
6490, 10009, 12007,
9589, 12023, 13632,
6867, 9447, 10995,
7930, 9816, 11397,
10241, 13300, 14939,
5830, 8670, 12387,
9870, 11915, 14247,
9318, 11647, 13272,
6721, 10836, 12929,
6543, 8233, 9944,
8034, 10854, 12394,
9112, 11787, 14218,
9302, 11114, 13400,
9022, 11366, 13816,
6962, 10461, 12480,
11288, 13333, 15222,
7249, 8974, 10547,
10566, 12336, 14390,
6697, 11339, 13521,
11851, 13944, 15826,
6847, 8381, 11349,
7509, 9331, 10939,
8029, 9618, 11909,
13973, 17644, 19647, 22474,
14722, 16522, 20035, 22134,
16305, 18179, 21106, 23048,
15150, 17948, 21394, 23225,
13582, 15191, 17687, 22333,
11778, 15546, 18458, 21753,
16619, 18410, 20827, 23559,
14229, 15746, 17907, 22474,
12465, 15327, 20700, 22831,
15085, 16799, 20182, 23410,
13026, 16935, 19890, 22892,
14310, 16854, 19007, 22944,
14210, 15897, 18891, 23154,
14633, 18059, 20132, 22899,
15246, 17781, 19780, 22640,
16396, 18904, 20912, 23035,
14618, 17401, 19510, 21672,
15473, 17497, 19813, 23439,
18851, 20736, 22323, 23864,
15055, 16804, 18530, 20916,
16490, 18196, 19990, 21939,
11711, 15223, 21154, 23312,
13294, 15546, 19393, 21472,
12956, 16060, 20610, 22417,
11628, 15843, 19617, 22501,
14106, 16872, 19839, 22689,
15655, 18192, 20161, 22452,
12953, 15244, 20619, 23549,
15322, 17193, 19926, 21762,
16873, 18676, 20444, 22359,
14874, 17871, 20083, 21959,
11534, 14486, 19194, 21857,
17766, 19617, 21338, 23178,
13404, 15284, 19080, 23136,
15392, 17527, 19470, 21953,
14462, 16153, 17985, 21192,
17734, 19750, 21903, 23783,
16973, 19096, 21675, 23815,
16597, 18936, 21257, 23461,
15966, 17865, 20602, 22920,
15416, 17456, 20301, 22972,
18335, 20093, 21732, 23497,
15548, 17217, 20679, 23594,
15208, 16995, 20816, 22870,
13890, 18015, 20531, 22468,
13211, 15377, 19951, 22388,
12852, 14635, 17978, 22680,
16002, 17732, 20373, 23544,
11373, 14134, 19534, 22707,
17329, 19151, 21241, 23462,
15612, 17296, 19362, 22850,
15422, 19104, 21285, 23164,
13792, 17111, 19349, 21370,
15352, 17876, 20776, 22667,
15253, 16961, 18921, 22123,
14108, 17264, 20294, 23246,
15785, 17897, 20010, 21822,
17399, 19147, 20915, 22753,
13010, 15659, 18127, 20840,
16826, 19422, 22218, 24084,
18108, 20641, 22695, 24237,
18018, 20273, 22268, 23920,
16057, 17821, 21365, 23665,
16005, 17901, 19892, 23016,
13232, 16683, 21107, 23221,
13280, 16615, 19915, 21829,
14950, 18575, 20599, 22511,
16337, 18261, 20277, 23216,
14306, 16477, 21203, 23158,
12803, 17498, 20248, 22014,
14327, 17068, 20160, 22006,
14402, 17461, 21599, 23688,
16968, 18834, 20896, 23055,
15070, 17157, 20451, 22315,
15419, 17107, 21601, 23946,
16039, 17639, 19533, 21424,
16326, 19261, 21745, 23673,
16489, 18534, 21658, 23782,
16594, 18471, 20549, 22807,
18973, 21212, 22890, 24278,
14264, 18674, 21123, 23071,
15117, 16841, 19239, 23118,
13762, 15782, 20478, 23230,
14111, 15949, 20058, 22354,
14990, 16738, 21139, 23492,
13735, 16971, 19026, 22158,
14676, 17314, 20232, 22807,
16196, 18146, 20459, 22339,
14747, 17258, 19315, 22437,
14973, 17778, 20692, 23367,
15715, 17472, 20385, 22349,
15702, 18228, 20829, 23410,
14428, 16188, 20541, 23630,
16824, 19394, 21365, 23246,
13069, 16392, 18900, 21121,
12047, 16640, 19463, 21689,
14757, 17433, 19659, 23125,
15185, 16930, 19900, 22540,
16026, 17725, 19618, 22399,
16086, 18643, 21179, 23472,
15462, 17248, 19102, 21196,
17368, 20016, 22396, 24096,
12340, 14475, 19665, 23362,
13636, 16229, 19462, 22728,
14096, 16211, 19591, 21635,
12152, 14867, 19943, 22301,
14492, 17503, 21002, 22728,
14834, 16788, 19447, 21411,
14650, 16433, 19326, 22308,
14624, 16328, 19659, 23204,
13888, 16572, 20665, 22488,
12977, 16102, 18841, 22246,
15523, 18431, 21757, 23738,
14095, 16349, 18837, 20947,
13266, 17809, 21088, 22839,
15427, 18190, 20270, 23143,
11859, 16753, 20935, 22486,
12310, 17667, 21736, 23319,
14021, 15926, 18702, 22002,
12286, 15299, 19178, 21126,
15703, 17491, 21039, 23151,
12272, 14018, 18213, 22570,
14817, 16364, 18485, 22598,
17109, 19683, 21851, 23677,
12657, 14903, 19039, 22061,
14713, 16487, 20527, 22814,
14635, 16726, 18763, 21715,
15878, 18550, 20718, 22906
};
const WebRtc_Word16 WebRtcIlbcfix_kLsfDimCb[LSF_NSPLIT] = {3, 3, 4};
const WebRtc_Word16 WebRtcIlbcfix_kLsfSizeCb[LSF_NSPLIT] = {64,128,128};
const WebRtc_Word16 WebRtcIlbcfix_kLsfMean[LPC_FILTERORDER] = {
2308, 3652, 5434, 7885,
10255, 12559, 15160, 17513,
20328, 22752};
const WebRtc_Word16 WebRtcIlbcfix_kLspMean[LPC_FILTERORDER] = {
31476, 29565, 25819, 18725, 10276,
1236, -9049, -17600, -25884, -30618
};
/* Q14 */
const WebRtc_Word16 WebRtcIlbcfix_kLsfWeight20ms[4] = {12288, 8192, 4096, 0};
const WebRtc_Word16 WebRtcIlbcfix_kLsfWeight30ms[6] = {8192, 16384, 10923, 5461, 0, 0};
/*
cos(x) in Q15
WebRtcIlbcfix_kCos[i] = cos(pi*i/64.0)
used in WebRtcIlbcfix_Lsp2Lsf()
*/
const WebRtc_Word16 WebRtcIlbcfix_kCos[64] = {
32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
-12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
-23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
-30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729
};
/*
Derivative in Q19, used to interpolate between the
WebRtcIlbcfix_kCos[] values to get a more exact y = cos(x)
*/
const WebRtc_Word16 WebRtcIlbcfix_kCosDerivative[64] = {
-632, -1893, -3150, -4399, -5638, -6863, -8072, -9261,
-10428, -11570, -12684, -13767, -14817, -15832, -16808, -17744,
-18637, -19486, -20287, -21039, -21741, -22390, -22986, -23526,
-24009, -24435, -24801, -25108, -25354, -25540, -25664, -25726,
-25726, -25664, -25540, -25354, -25108, -24801, -24435, -24009,
-23526, -22986, -22390, -21741, -21039, -20287, -19486, -18637,
-17744, -16808, -15832, -14817, -13767, -12684, -11570, -10428,
-9261, -8072, -6863, -5638, -4399, -3150, -1893, -632};
/*
Table in Q15, used for a2lsf conversion
WebRtcIlbcfix_kCosGrid[i] = cos((2*pi*i)/(float)(2*COS_GRID_POINTS));
*/
const WebRtc_Word16 WebRtcIlbcfix_kCosGrid[COS_GRID_POINTS + 1] = {
32760, 32723, 32588, 32364, 32051, 31651, 31164, 30591,
29935, 29196, 28377, 27481, 26509, 25465, 24351, 23170,
21926, 20621, 19260, 17846, 16384, 14876, 13327, 11743,
10125, 8480, 6812, 5126, 3425, 1714, 0, -1714, -3425,
-5126, -6812, -8480, -10125, -11743, -13327, -14876,
-16384, -17846, -19260, -20621, -21926, -23170, -24351,
-25465, -26509, -27481, -28377, -29196, -29935, -30591,
-31164, -31651, -32051, -32364, -32588, -32723, -32760
};
/*
Derivative of y = acos(x) in Q12
used in WebRtcIlbcfix_Lsp2Lsf()
*/
const WebRtc_Word16 WebRtcIlbcfix_kAcosDerivative[64] = {
-26887, -8812, -5323, -3813, -2979, -2444, -2081, -1811,
-1608, -1450, -1322, -1219, -1132, -1059, -998, -946,
-901, -861, -827, -797, -772, -750, -730, -713,
-699, -687, -677, -668, -662, -657, -654, -652,
-652, -654, -657, -662, -668, -677, -687, -699,
-713, -730, -750, -772, -797, -827, -861, -901,
-946, -998, -1059, -1132, -1219, -1322, -1450, -1608,
-1811, -2081, -2444, -2979, -3813, -5323, -8812, -26887
};
/* Tables for quantization of start state */
/* State quantization tables */
const WebRtc_Word16 WebRtcIlbcfix_kStateSq3[8] = { /* Values in Q13 */
-30473, -17838, -9257, -2537,
3639, 10893, 19958, 32636
};
/* This table defines the limits for the selection of the freqg
less or equal than value 0 => index = 0
less or equal than value k => index = k
*/
const WebRtc_Word32 WebRtcIlbcfix_kChooseFrgQuant[64] = {
118, 163, 222, 305, 425, 604,
851, 1174, 1617, 2222, 3080, 4191,
5525, 7215, 9193, 11540, 14397, 17604,
21204, 25209, 29863, 35720, 42531, 50375,
59162, 68845, 80108, 93754, 110326, 129488,
150654, 174328, 201962, 233195, 267843, 308239,
354503, 405988, 464251, 531550, 608652, 697516,
802526, 928793, 1080145, 1258120, 1481106, 1760881,
2111111, 2546619, 3078825, 3748642, 4563142, 5573115,
6887601, 8582108, 10797296, 14014513, 18625760, 25529599,
37302935, 58819185, 109782723, WEBRTC_SPL_WORD32_MAX
};
const WebRtc_Word16 WebRtcIlbcfix_kScale[64] = {
/* Values in Q16 */
29485, 25003, 21345, 18316, 15578, 13128, 10973, 9310, 7955,
6762, 5789, 4877, 4255, 3699, 3258, 2904, 2595, 2328,
2123, 1932, 1785, 1631, 1493, 1370, 1260, 1167, 1083,
/* Values in Q21 */
32081, 29611, 27262, 25229, 23432, 21803, 20226, 18883, 17609,
16408, 15311, 14327, 13390, 12513, 11693, 10919, 10163, 9435,
8739, 8100, 7424, 6813, 6192, 5648, 5122, 4639, 4207, 3798,
3404, 3048, 2706, 2348, 2036, 1713, 1393, 1087, 747
};
/*frgq in fixpoint, but already computed like this:
for(i=0; i<64; i++){
a = (pow(10,frgq[i])/4.5);
WebRtcIlbcfix_kFrgQuantMod[i] = round(a);
}
Value 0 :36 in Q8
37:58 in Q5
59:63 in Q3
*/
const WebRtc_Word16 WebRtcIlbcfix_kFrgQuantMod[64] = {
/* First 37 values in Q8 */
569, 671, 786, 916, 1077, 1278,
1529, 1802, 2109, 2481, 2898, 3440,
3943, 4535, 5149, 5778, 6464, 7208,
7904, 8682, 9397, 10285, 11240, 12246,
13313, 14382, 15492, 16735, 18131, 19693,
21280, 22912, 24624, 26544, 28432, 30488,
32720,
/* 22 values in Q5 */
4383, 4684, 5012, 5363, 5739, 6146,
6603, 7113, 7679, 8285, 9040, 9850,
10838, 11882, 13103, 14467, 15950, 17669,
19712, 22016, 24800, 28576,
/* 5 values in Q3 */
8240, 9792, 12040, 15440, 22472
};
/* Constants for codebook search and creation */
/* Expansion filter to get additional cb section.
* Q12 and reversed compared to flp
*/
const WebRtc_Word16 WebRtcIlbcfix_kCbFiltersRev[CB_FILTERLEN]={
-140, 446, -755, 3302, 2922, -590, 343, -138};
/* Weighting coefficients for short lags.
* [0.2 0.4 0.6 0.8] in Q15 */
const WebRtc_Word16 WebRtcIlbcfix_kAlpha[4]={
6554, 13107, 19661, 26214};
/* Ranges for search and filters at different subframes */
const WebRtc_Word16 WebRtcIlbcfix_kSearchRange[5][CB_NSTAGES]={
{58,58,58}, {108,44,44}, {108,108,108}, {108,108,108}, {108,108,108}};
const WebRtc_Word16 WebRtcIlbcfix_kFilterRange[5]={63, 85, 125, 147, 147};
/* Gain Quantization for the codebook gains of the 3 stages */
/* Q14 (one extra value (max WebRtc_Word16) to simplify for the search) */
const WebRtc_Word16 WebRtcIlbcfix_kGainSq3[9]={
-16384, -10813, -5407, 0, 4096, 8192,
12288, 16384, 32767};
/* Q14 (one extra value (max WebRtc_Word16) to simplify for the search) */
const WebRtc_Word16 WebRtcIlbcfix_kGainSq4[17]={
-17203, -14746, -12288, -9830, -7373, -4915,
-2458, 0, 2458, 4915, 7373, 9830,
12288, 14746, 17203, 19661, 32767};
/* Q14 (one extra value (max WebRtc_Word16) to simplify for the search) */
const WebRtc_Word16 WebRtcIlbcfix_kGainSq5[33]={
614, 1229, 1843, 2458, 3072, 3686,
4301, 4915, 5530, 6144, 6758, 7373,
7987, 8602, 9216, 9830, 10445, 11059,
11674, 12288, 12902, 13517, 14131, 14746,
15360, 15974, 16589, 17203, 17818, 18432,
19046, 19661, 32767};
/* Q14 gain_sq5Tbl squared in Q14 */
const WebRtc_Word16 WebRtcIlbcfix_kGainSq5Sq[32] = {
23, 92, 207, 368, 576, 829,
1129, 1474, 1866, 2304, 2787, 3317,
3893, 4516, 5184, 5897, 6658, 7464,
8318, 9216, 10160, 11151, 12187, 13271,
14400, 15574, 16796, 18062, 19377, 20736,
22140, 23593
};
const WebRtc_Word16* const WebRtcIlbcfix_kGain[3] =
{WebRtcIlbcfix_kGainSq5, WebRtcIlbcfix_kGainSq4, WebRtcIlbcfix_kGainSq3};
/* Tables for the Enhancer, using upsamling factor 4 (ENH_UPS0 = 4) */
const WebRtc_Word16 WebRtcIlbcfix_kEnhPolyPhaser[ENH_UPS0][ENH_FLO_MULT2_PLUS1]={
{0, 0, 0, 4096, 0, 0, 0},
{64, -315, 1181, 3531, -436, 77, -64},
{97, -509, 2464, 2464, -509, 97, -97},
{77, -436, 3531, 1181, -315, 64, -77}
};
const WebRtc_Word16 WebRtcIlbcfix_kEnhWt[3] = {
4800, 16384, 27968 /* Q16 */
};
const WebRtc_Word16 WebRtcIlbcfix_kEnhPlocs[ENH_NBLOCKS_TOT] = {
160, 480, 800, 1120, 1440, 1760, 2080, 2400 /* Q(-2) */
};
/* PLC table */
const WebRtc_Word16 WebRtcIlbcfix_kPlcPerSqr[6] = { /* Grid points for square of periodiciy in Q15 */
839, 1343, 2048, 2998, 4247, 5849
};
const WebRtc_Word16 WebRtcIlbcfix_kPlcPitchFact[6] = { /* Value of y=(x^4-0.4)/(0.7-0.4) in grid points in Q15 */
0, 5462, 10922, 16384, 21846, 27306
};
const WebRtc_Word16 WebRtcIlbcfix_kPlcPfSlope[6] = { /* Slope of y=(x^4-0.4)/(0.7-0.4) in Q11 */
26667, 18729, 13653, 10258, 7901, 6214
};

View File

@@ -0,0 +1,244 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Decode.c
******************************************************************/
#include "defines.h"
#include "simple_lsf_dequant.h"
#include "decoder_interpolate_lsf.h"
#include "index_conv_dec.h"
#include "do_plc.h"
#include "constants.h"
#include "enhancer_interface.h"
#include "xcorr_coef.h"
#include "lsf_check.h"
#include "decode_residual.h"
#include "unpack_bits.h"
#include "hp_output.h"
#ifndef WEBRTC_BIG_ENDIAN
#include "swap_bytes.h"
#endif
/*----------------------------------------------------------------*
* main decoder function
*---------------------------------------------------------------*/
void WebRtcIlbcfix_DecodeImpl(
WebRtc_Word16 *decblock, /* (o) decoded signal block */
WebRtc_UWord16 *bytes, /* (i) encoded signal bits */
iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state
structure */
WebRtc_Word16 mode /* (i) 0: bad packet, PLC,
1: normal */
) {
int i;
WebRtc_Word16 order_plus_one;
WebRtc_Word16 last_bit;
WebRtc_Word16 *data;
/* Stack based */
WebRtc_Word16 decresidual[BLOCKL_MAX];
WebRtc_Word16 PLCresidual[BLOCKL_MAX + LPC_FILTERORDER];
WebRtc_Word16 syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)];
WebRtc_Word16 PLClpc[LPC_FILTERORDER + 1];
iLBC_bits *iLBCbits_inst = (iLBC_bits*)PLCresidual;
/* Reuse some buffers that are non overlapping in order to save stack memory */
data = &PLCresidual[LPC_FILTERORDER];
if (mode>0) { /* the data are good */
/* decode data */
#ifndef WEBRTC_BIG_ENDIAN
WebRtcIlbcfix_SwapBytes((WebRtc_UWord16*)bytes, iLBCdec_inst->no_of_words);
#endif
/* Unpacketize bits into parameters */
last_bit = WebRtcIlbcfix_UnpackBits(bytes, iLBCbits_inst, iLBCdec_inst->mode);
#ifndef WEBRTC_BIG_ENDIAN
/* Swap back so that the the input vector "bytes" is unchanged */
WebRtcIlbcfix_SwapBytes((WebRtc_UWord16*)bytes, iLBCdec_inst->no_of_words);
#endif
/* Check for bit errors */
if (iLBCbits_inst->startIdx<1)
mode = 0;
if ((iLBCdec_inst->mode==20) && (iLBCbits_inst->startIdx>3))
mode = 0;
if ((iLBCdec_inst->mode==30) && (iLBCbits_inst->startIdx>5))
mode = 0;
if (last_bit==1)
mode = 0;
if (mode==1) { /* No bit errors was detected, continue decoding */
/* Stack based */
WebRtc_Word16 lsfdeq[LPC_FILTERORDER*LPC_N_MAX];
WebRtc_Word16 weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
/* adjust index */
WebRtcIlbcfix_IndexConvDec(iLBCbits_inst->cb_index);
/* decode the lsf */
WebRtcIlbcfix_SimpleLsfDeQ(lsfdeq, (WebRtc_Word16*)(iLBCbits_inst->lsf), iLBCdec_inst->lpc_n);
WebRtcIlbcfix_LsfCheck(lsfdeq, LPC_FILTERORDER, iLBCdec_inst->lpc_n);
WebRtcIlbcfix_DecoderInterpolateLsp(syntdenum, weightdenum,
lsfdeq, LPC_FILTERORDER, iLBCdec_inst);
/* Decode the residual using the cb and gain indexes */
WebRtcIlbcfix_DecodeResidual(iLBCdec_inst, iLBCbits_inst, decresidual, syntdenum);
/* preparing the plc for a future loss! */
WebRtcIlbcfix_DoThePlc( PLCresidual, PLClpc, 0,
decresidual, syntdenum + (LPC_FILTERORDER + 1)*(iLBCdec_inst->nsub - 1),
(WebRtc_Word16)(iLBCdec_inst->last_lag), iLBCdec_inst);
/* Use the output from doThePLC */
WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
}
}
if (mode == 0) {
/* the data is bad (either a PLC call
* was made or a bit error was detected)
*/
/* packet loss conceal */
WebRtcIlbcfix_DoThePlc( PLCresidual, PLClpc, 1,
decresidual, syntdenum, (WebRtc_Word16)(iLBCdec_inst->last_lag), iLBCdec_inst);
WEBRTC_SPL_MEMCPY_W16(decresidual, PLCresidual, iLBCdec_inst->blockl);
order_plus_one = LPC_FILTERORDER + 1;
for (i = 0; i < iLBCdec_inst->nsub; i++) {
WEBRTC_SPL_MEMCPY_W16(syntdenum+(i*order_plus_one),
PLClpc, order_plus_one);
}
}
if ((*iLBCdec_inst).use_enhancer == 1) { /* Enhancer activated */
/* Update the filter and filter coefficients if there was a packet loss */
if (iLBCdec_inst->prev_enh_pl==2) {
for (i=0;i<iLBCdec_inst->nsub;i++) {
WEBRTC_SPL_MEMCPY_W16(&(iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)]),
syntdenum, (LPC_FILTERORDER+1));
}
}
/* post filtering */
(*iLBCdec_inst).last_lag =
WebRtcIlbcfix_EnhancerInterface(data, decresidual, iLBCdec_inst);
/* synthesis filtering */
/* Set up the filter state */
WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
if (iLBCdec_inst->mode==20) {
/* Enhancer has 40 samples delay */
i=0;
WebRtcSpl_FilterARFastQ12(
data, data,
iLBCdec_inst->old_syntdenum + (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1),
LPC_FILTERORDER+1, SUBL);
for (i=1; i < iLBCdec_inst->nsub; i++) {
WebRtcSpl_FilterARFastQ12(
data+i*SUBL, data+i*SUBL,
syntdenum+(i-1)*(LPC_FILTERORDER+1),
LPC_FILTERORDER+1, SUBL);
}
} else if (iLBCdec_inst->mode==30) {
/* Enhancer has 80 samples delay */
for (i=0; i < 2; i++) {
WebRtcSpl_FilterARFastQ12(
data+i*SUBL, data+i*SUBL,
iLBCdec_inst->old_syntdenum + (i+4)*(LPC_FILTERORDER+1),
LPC_FILTERORDER+1, SUBL);
}
for (i=2; i < iLBCdec_inst->nsub; i++) {
WebRtcSpl_FilterARFastQ12(
data+i*SUBL, data+i*SUBL,
syntdenum+(i-2)*(LPC_FILTERORDER+1),
LPC_FILTERORDER+1, SUBL);
}
}
/* Save the filter state */
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
} else { /* Enhancer not activated */
WebRtc_Word16 lag;
/* Find last lag (since the enhancer is not called to give this info) */
lag = 20;
if (iLBCdec_inst->mode==20) {
lag = (WebRtc_Word16)WebRtcIlbcfix_XcorrCoef(
&decresidual[iLBCdec_inst->blockl-60],
&decresidual[iLBCdec_inst->blockl-60-lag],
60,
80, lag, -1);
} else {
lag = (WebRtc_Word16)WebRtcIlbcfix_XcorrCoef(
&decresidual[iLBCdec_inst->blockl-ENH_BLOCKL],
&decresidual[iLBCdec_inst->blockl-ENH_BLOCKL-lag],
ENH_BLOCKL,
100, lag, -1);
}
/* Store lag (it is needed if next packet is lost) */
(*iLBCdec_inst).last_lag = (int)lag;
/* copy data and run synthesis filter */
WEBRTC_SPL_MEMCPY_W16(data, decresidual, iLBCdec_inst->blockl);
/* Set up the filter state */
WEBRTC_SPL_MEMCPY_W16(&data[-LPC_FILTERORDER], iLBCdec_inst->syntMem, LPC_FILTERORDER);
for (i=0; i < iLBCdec_inst->nsub; i++) {
WebRtcSpl_FilterARFastQ12(
data+i*SUBL, data+i*SUBL,
syntdenum + i*(LPC_FILTERORDER+1),
LPC_FILTERORDER+1, SUBL);
}
/* Save the filter state */
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->syntMem, &data[iLBCdec_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
}
WEBRTC_SPL_MEMCPY_W16(decblock,data,iLBCdec_inst->blockl);
/* High pass filter the signal (with upscaling a factor 2 and saturation) */
WebRtcIlbcfix_HpOutput(decblock, (WebRtc_Word16*)WebRtcIlbcfix_kHpOutCoefs,
iLBCdec_inst->hpimemy, iLBCdec_inst->hpimemx,
iLBCdec_inst->blockl);
WEBRTC_SPL_MEMCPY_W16(iLBCdec_inst->old_syntdenum,
syntdenum, iLBCdec_inst->nsub*(LPC_FILTERORDER+1));
iLBCdec_inst->prev_enh_pl=0;
if (mode==0) { /* PLC was used */
iLBCdec_inst->prev_enh_pl=1;
}
}

View File

@@ -0,0 +1,518 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_Encode.c
******************************************************************/
#include "defines.h"
#include "lpc_encode.h"
#include "frame_classify.h"
#include "state_search.h"
#include "state_construct.h"
#include "constants.h"
#include "cb_search.h"
#include "cb_construct.h"
#include "index_conv_enc.h"
#include "pack_bits.h"
#include "hp_input.h"
#ifdef SPLIT_10MS
#include "unpack_bits.h"
#include "index_conv_dec.h"
#endif
#ifndef WEBRTC_BIG_ENDIAN
#include "swap_bytes.h"
#endif
/*----------------------------------------------------------------*
* main encoder function
*---------------------------------------------------------------*/
void WebRtcIlbcfix_EncodeImpl(
WebRtc_UWord16 *bytes, /* (o) encoded data bits iLBC */
WebRtc_Word16 *block, /* (i) speech vector to encode */
iLBC_Enc_Inst_t *iLBCenc_inst /* (i/o) the general encoder
state */
){
int n, meml_gotten, Nfor, Nback;
WebRtc_Word16 diff, start_pos;
int index;
int subcount, subframe;
WebRtc_Word16 start_count, end_count;
WebRtc_Word16 *residual;
WebRtc_Word32 en1, en2;
WebRtc_Word16 scale, max;
WebRtc_Word16 *syntdenum;
WebRtc_Word16 *decresidual;
WebRtc_Word16 *reverseResidual;
WebRtc_Word16 *reverseDecresidual;
/* Stack based */
WebRtc_Word16 weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX];
WebRtc_Word16 dataVec[BLOCKL_MAX + LPC_FILTERORDER];
WebRtc_Word16 memVec[CB_MEML+CB_FILTERLEN];
WebRtc_Word16 bitsMemory[sizeof(iLBC_bits)/sizeof(WebRtc_Word16)];
iLBC_bits *iLBCbits_inst = (iLBC_bits*)bitsMemory;
#ifdef SPLIT_10MS
WebRtc_Word16 *weightdenumbuf = iLBCenc_inst->weightdenumbuf;
WebRtc_Word16 last_bit;
#endif
WebRtc_Word16 *data = &dataVec[LPC_FILTERORDER];
WebRtc_Word16 *mem = &memVec[CB_HALFFILTERLEN];
/* Reuse som buffers to save stack memory */
residual = &iLBCenc_inst->lpc_buffer[LPC_LOOKBACK+BLOCKL_MAX-iLBCenc_inst->blockl];
syntdenum = mem; /* syntdenum[(LPC_FILTERORDER + 1)*NSUB_MAX] and mem are used non overlapping in the code */
decresidual = residual; /* Already encoded residual is overwritten by the decoded version */
reverseResidual = data; /* data and reverseResidual are used non overlapping in the code */
reverseDecresidual = reverseResidual; /* Already encoded residual is overwritten by the decoded version */
#ifdef SPLIT_10MS
WebRtcSpl_MemSetW16 ( (WebRtc_Word16 *) iLBCbits_inst, 0,
(WebRtc_Word16) (sizeof(iLBC_bits) / sizeof(WebRtc_Word16)) );
start_pos = iLBCenc_inst->start_pos;
diff = iLBCenc_inst->diff;
if (iLBCenc_inst->section != 0){
WEBRTC_SPL_MEMCPY_W16 (weightdenum, weightdenumbuf,
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
/* Un-Packetize the frame into parameters */
last_bit = WebRtcIlbcfix_UnpackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
if (last_bit)
return;
/* adjust index */
WebRtcIlbcfix_IndexConvDec (iLBCbits_inst->cb_index);
if (iLBCenc_inst->section == 1){
/* Save first 80 samples of a 160/240 sample frame for 20/30msec */
WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples, block, 80);
}
else{ // iLBCenc_inst->section == 2 AND mode = 30ms
/* Save second 80 samples of a 240 sample frame for 30msec */
WEBRTC_SPL_MEMCPY_W16 (iLBCenc_inst->past_samples + 80, block, 80);
}
}
else{ // iLBCenc_inst->section == 0
/* form a complete frame of 160/240 for 20msec/30msec mode */
WEBRTC_SPL_MEMCPY_W16 (data + (iLBCenc_inst->mode * 8) - 80, block, 80);
WEBRTC_SPL_MEMCPY_W16 (data, iLBCenc_inst->past_samples,
(iLBCenc_inst->mode * 8) - 80);
iLBCenc_inst->Nfor_flag = 0;
iLBCenc_inst->Nback_flag = 0;
#else
/* copy input block to data*/
WEBRTC_SPL_MEMCPY_W16(data,block,iLBCenc_inst->blockl);
#endif
/* high pass filtering of input signal and scale down the residual (*0.5) */
WebRtcIlbcfix_HpInput(data, (WebRtc_Word16*)WebRtcIlbcfix_kHpInCoefs,
iLBCenc_inst->hpimemy, iLBCenc_inst->hpimemx,
iLBCenc_inst->blockl);
/* LPC of hp filtered input data */
WebRtcIlbcfix_LpcEncode(syntdenum, weightdenum, iLBCbits_inst->lsf, data,
iLBCenc_inst);
/* Set up state */
WEBRTC_SPL_MEMCPY_W16(dataVec, iLBCenc_inst->anaMem, LPC_FILTERORDER);
/* inverse filter to get residual */
for (n=0; n<iLBCenc_inst->nsub; n++ ) {
WebRtcSpl_FilterMAFastQ12(
&data[n*SUBL], &residual[n*SUBL],
&syntdenum[n*(LPC_FILTERORDER+1)],
LPC_FILTERORDER+1, SUBL);
}
/* Copy the state for next frame */
WEBRTC_SPL_MEMCPY_W16(iLBCenc_inst->anaMem, &data[iLBCenc_inst->blockl-LPC_FILTERORDER], LPC_FILTERORDER);
/* find state location */
iLBCbits_inst->startIdx = WebRtcIlbcfix_FrameClassify(iLBCenc_inst,residual);
/* check if state should be in first or last part of the
two subframes */
index = (iLBCbits_inst->startIdx-1)*SUBL;
max=WebRtcSpl_MaxAbsValueW16(&residual[index], 2*SUBL);
scale=WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(max,max));
/* Scale to maximum 25 bits so that the MAC won't cause overflow */
scale = scale - 25;
if(scale < 0) {
scale = 0;
}
diff = STATE_LEN - iLBCenc_inst->state_short_len;
en1=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
iLBCenc_inst->state_short_len, scale);
index += diff;
en2=WebRtcSpl_DotProductWithScale(&residual[index], &residual[index],
iLBCenc_inst->state_short_len, scale);
if (en1 > en2) {
iLBCbits_inst->state_first = 1;
start_pos = (iLBCbits_inst->startIdx-1)*SUBL;
} else {
iLBCbits_inst->state_first = 0;
start_pos = (iLBCbits_inst->startIdx-1)*SUBL + diff;
}
/* scalar quantization of state */
WebRtcIlbcfix_StateSearch(iLBCenc_inst, iLBCbits_inst, &residual[start_pos],
&syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
&weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)]);
WebRtcIlbcfix_StateConstruct(iLBCbits_inst->idxForMax, iLBCbits_inst->idxVec,
&syntdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
&decresidual[start_pos], iLBCenc_inst->state_short_len
);
/* predictive quantization in state */
if (iLBCbits_inst->state_first) { /* put adaptive part in the end */
/* setup memory */
WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-iLBCenc_inst->state_short_len));
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-iLBCenc_inst->state_short_len,
decresidual+start_pos, iLBCenc_inst->state_short_len);
/* encode subframes */
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
&residual[start_pos+iLBCenc_inst->state_short_len],
mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
&weightdenum[iLBCbits_inst->startIdx*(LPC_FILTERORDER+1)], 0);
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(&decresidual[start_pos+iLBCenc_inst->state_short_len],
iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL,
diff
);
}
else { /* put adaptive part in the beginning */
/* create reversed vectors for prediction */
WebRtcSpl_MemCpyReversedOrder(&reverseResidual[diff-1],
&residual[(iLBCbits_inst->startIdx+1)*SUBL-STATE_LEN], diff);
/* setup memory */
meml_gotten = iLBCenc_inst->state_short_len;
WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[start_pos], meml_gotten);
WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-iLBCenc_inst->state_short_len));
/* encode subframes */
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
reverseResidual, mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL, diff,
&weightdenum[(iLBCbits_inst->startIdx-1)*(LPC_FILTERORDER+1)],
0);
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(reverseDecresidual,
iLBCbits_inst->cb_index, iLBCbits_inst->gain_index,
mem+CB_MEML-ST_MEM_L_TBL, ST_MEM_L_TBL,
diff
);
/* get decoded residual from reversed vector */
WebRtcSpl_MemCpyReversedOrder(&decresidual[start_pos-1], reverseDecresidual, diff);
}
#ifdef SPLIT_10MS
iLBCenc_inst->start_pos = start_pos;
iLBCenc_inst->diff = diff;
iLBCenc_inst->section++;
/* adjust index */
WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
/* Packetize the parameters into the frame */
WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
return;
}
#endif
/* forward prediction of subframes */
Nfor = iLBCenc_inst->nsub-iLBCbits_inst->startIdx-1;
/* counter for predicted subframes */
#ifdef SPLIT_10MS
if (iLBCenc_inst->mode == 20)
{
subcount = 1;
}
if (iLBCenc_inst->mode == 30)
{
if (iLBCenc_inst->section == 1)
{
subcount = 1;
}
if (iLBCenc_inst->section == 2)
{
subcount = 3;
}
}
#else
subcount=1;
#endif
if( Nfor > 0 ){
/* setup memory */
WebRtcSpl_MemSetW16(mem, 0, CB_MEML-STATE_LEN);
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-STATE_LEN,
decresidual+(iLBCbits_inst->startIdx-1)*SUBL, STATE_LEN);
#ifdef SPLIT_10MS
if (iLBCenc_inst->Nfor_flag > 0)
{
for (subframe = 0; subframe < WEBRTC_SPL_MIN (Nfor, 2); subframe++)
{
/* update memory */
WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
&decresidual[(iLBCbits_inst->startIdx + 1 +
subframe) * SUBL], SUBL);
}
}
iLBCenc_inst->Nfor_flag++;
if (iLBCenc_inst->mode == 20)
{
start_count = 0;
end_count = Nfor;
}
if (iLBCenc_inst->mode == 30)
{
if (iLBCenc_inst->section == 1)
{
start_count = 0;
end_count = WEBRTC_SPL_MIN (Nfor, 2);
}
if (iLBCenc_inst->section == 2)
{
start_count = WEBRTC_SPL_MIN (Nfor, 2);
end_count = Nfor;
}
}
#else
start_count = 0;
end_count = (WebRtc_Word16)Nfor;
#endif
/* loop over subframes to encode */
for (subframe = start_count; subframe < end_count; subframe++){
/* encode subframe */
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
&residual[(iLBCbits_inst->startIdx+1+subframe)*SUBL],
mem, MEM_LF_TBL, SUBL,
&weightdenum[(iLBCbits_inst->startIdx+1+subframe)*(LPC_FILTERORDER+1)],
(WebRtc_Word16)subcount);
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(&decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL],
iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
mem, MEM_LF_TBL,
SUBL
);
/* update memory */
WEBRTC_SPL_MEMMOVE_W16(mem, mem+SUBL, (CB_MEML-SUBL));
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
&decresidual[(iLBCbits_inst->startIdx+1+subframe)*SUBL], SUBL);
subcount++;
}
}
#ifdef SPLIT_10MS
if ((iLBCenc_inst->section == 1) &&
(iLBCenc_inst->mode == 30) && (Nfor > 0) && (end_count == 2))
{
iLBCenc_inst->section++;
/* adjust index */
WebRtcIlbcfix_IndexConvEnc (iLBCbits_inst->cb_index);
/* Packetize the parameters into the frame */
WebRtcIlbcfix_PackBits (iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
return;
}
#endif
/* backward prediction of subframes */
Nback = iLBCbits_inst->startIdx-1;
if( Nback > 0 ){
/* create reverse order vectors
(The decresidual does not need to be copied since it is
contained in the same vector as the residual)
*/
WebRtcSpl_MemCpyReversedOrder(&reverseResidual[Nback*SUBL-1], residual, Nback*SUBL);
/* setup memory */
meml_gotten = SUBL*(iLBCenc_inst->nsub+1-iLBCbits_inst->startIdx);
if( meml_gotten > CB_MEML ) {
meml_gotten=CB_MEML;
}
WebRtcSpl_MemCpyReversedOrder(&mem[CB_MEML-1], &decresidual[Nback*SUBL], meml_gotten);
WebRtcSpl_MemSetW16(mem, 0, (WebRtc_Word16)(CB_MEML-meml_gotten));
#ifdef SPLIT_10MS
if (iLBCenc_inst->Nback_flag > 0)
{
for (subframe = 0; subframe < WEBRTC_SPL_MAX (2 - Nfor, 0); subframe++)
{
/* update memory */
WEBRTC_SPL_MEMCPY_W16 (mem, mem + SUBL, (CB_MEML - SUBL));
WEBRTC_SPL_MEMCPY_W16 (mem + CB_MEML - SUBL,
&reverseDecresidual[subframe * SUBL], SUBL);
}
}
iLBCenc_inst->Nback_flag++;
if (iLBCenc_inst->mode == 20)
{
start_count = 0;
end_count = Nback;
}
if (iLBCenc_inst->mode == 30)
{
if (iLBCenc_inst->section == 1)
{
start_count = 0;
end_count = WEBRTC_SPL_MAX (2 - Nfor, 0);
}
if (iLBCenc_inst->section == 2)
{
start_count = WEBRTC_SPL_MAX (2 - Nfor, 0);
end_count = Nback;
}
}
#else
start_count = 0;
end_count = (WebRtc_Word16)Nback;
#endif
/* loop over subframes to encode */
for (subframe = start_count; subframe < end_count; subframe++){
/* encode subframe */
WebRtcIlbcfix_CbSearch(iLBCenc_inst, iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
iLBCbits_inst->gain_index+subcount*CB_NSTAGES, &reverseResidual[subframe*SUBL],
mem, MEM_LF_TBL, SUBL,
&weightdenum[(iLBCbits_inst->startIdx-2-subframe)*(LPC_FILTERORDER+1)],
(WebRtc_Word16)subcount);
/* construct decoded vector */
WebRtcIlbcfix_CbConstruct(&reverseDecresidual[subframe*SUBL],
iLBCbits_inst->cb_index+subcount*CB_NSTAGES,
iLBCbits_inst->gain_index+subcount*CB_NSTAGES,
mem, MEM_LF_TBL, SUBL
);
/* update memory */
WEBRTC_SPL_MEMMOVE_W16(mem, mem+SUBL, (CB_MEML-SUBL));
WEBRTC_SPL_MEMCPY_W16(mem+CB_MEML-SUBL,
&reverseDecresidual[subframe*SUBL], SUBL);
subcount++;
}
/* get decoded residual from reversed vector */
WebRtcSpl_MemCpyReversedOrder(&decresidual[SUBL*Nback-1], reverseDecresidual, SUBL*Nback);
}
/* end encoding part */
/* adjust index */
WebRtcIlbcfix_IndexConvEnc(iLBCbits_inst->cb_index);
/* Packetize the parameters into the frame */
#ifdef SPLIT_10MS
if( (iLBCenc_inst->mode==30) && (iLBCenc_inst->section==1) ){
WebRtcIlbcfix_PackBits(iLBCenc_inst->bytes, iLBCbits_inst, iLBCenc_inst->mode);
}
else{
WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
}
#else
WebRtcIlbcfix_PackBits(bytes, iLBCbits_inst, iLBCenc_inst->mode);
#endif
#ifndef WEBRTC_BIG_ENDIAN
/* Swap bytes for LITTLE ENDIAN since the packbits()
function assumes BIG_ENDIAN machine */
#ifdef SPLIT_10MS
if (( (iLBCenc_inst->section == 1) && (iLBCenc_inst->mode == 20) ) ||
( (iLBCenc_inst->section == 2) && (iLBCenc_inst->mode == 30) )){
WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words);
}
#else
WebRtcIlbcfix_SwapBytes(bytes, iLBCenc_inst->no_of_words);
#endif
#endif
#ifdef SPLIT_10MS
if (subcount == (iLBCenc_inst->nsub - 1))
{
iLBCenc_inst->section = 0;
}
else
{
iLBCenc_inst->section++;
WEBRTC_SPL_MEMCPY_W16 (weightdenumbuf, weightdenum,
SCRATCH_ENCODE_DATAVEC - SCRATCH_ENCODE_WEIGHTDENUM);
}
#endif
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/******************************************************************
iLBC Speech Coder ANSI-C Source Code
WebRtcIlbcfix_IndexConvDec.c
******************************************************************/
#include "defines.h"
void WebRtcIlbcfix_IndexConvDec(
WebRtc_Word16 *index /* (i/o) Codebook indexes */
){
int k;
for (k=4;k<6;k++) {
/* Readjust the second and third codebook index for the first 40 sample
so that they look the same as the first (in terms of lag)
*/
if ((index[k]>=44)&&(index[k]<108)) {
index[k]+=64;
} else if ((index[k]>=108)&&(index[k]<128)) {
index[k]+=128;
} else {
/* ERROR */
}
}
}

Some files were not shown because too many files have changed in this diff Show More