- initial import
This commit is contained in:
173
src/libs/webrtc/CMakeLists.txt
Normal file
173
src/libs/webrtc/CMakeLists.txt
Normal 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})
|
||||
1460
src/libs/webrtc/aec/aec_core.c
Normal file
1460
src/libs/webrtc/aec/aec_core.c
Normal file
File diff suppressed because it is too large
Load Diff
198
src/libs/webrtc/aec/aec_core.h
Normal file
198
src/libs/webrtc/aec/aec_core.h
Normal 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_
|
||||
|
||||
511
src/libs/webrtc/aec/aec_core_rdft.c
Normal file
511
src/libs/webrtc/aec/aec_core_rdft.c
Normal 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);
|
||||
}
|
||||
}
|
||||
435
src/libs/webrtc/aec/aec_core_sse2.c
Normal file
435
src/libs/webrtc/aec/aec_core_sse2.c
Normal 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__
|
||||
821
src/libs/webrtc/aec/echo_cancellation.c
Normal file
821
src/libs/webrtc/aec/echo_cancellation.c
Normal 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;
|
||||
}
|
||||
260
src/libs/webrtc/aec/echo_cancellation.h
Normal file
260
src/libs/webrtc/aec/echo_cancellation.h
Normal 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_ */
|
||||
235
src/libs/webrtc/aec/resampler.c
Normal file
235
src/libs/webrtc/aec/resampler.c
Normal 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;
|
||||
}
|
||||
32
src/libs/webrtc/aec/resampler.h
Normal file
32
src/libs/webrtc/aec/resampler.h
Normal 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_
|
||||
2452
src/libs/webrtc/aecm/aecm_core.c
Normal file
2452
src/libs/webrtc/aecm/aecm_core.c
Normal file
File diff suppressed because it is too large
Load Diff
313
src/libs/webrtc/aecm/aecm_core.h
Normal file
313
src/libs/webrtc/aecm/aecm_core.h
Normal 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
|
||||
733
src/libs/webrtc/aecm/echo_control_mobile.c
Normal file
733
src/libs/webrtc/aecm/echo_control_mobile.c
Normal 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;
|
||||
}
|
||||
206
src/libs/webrtc/aecm/echo_control_mobile.h
Normal file
206
src/libs/webrtc/aecm/echo_control_mobile.h
Normal 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_ */
|
||||
1700
src/libs/webrtc/agc/analog_agc.c
Normal file
1700
src/libs/webrtc/agc/analog_agc.c
Normal file
File diff suppressed because it is too large
Load Diff
133
src/libs/webrtc/agc/analog_agc.h
Normal file
133
src/libs/webrtc/agc/analog_agc.h
Normal 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_
|
||||
780
src/libs/webrtc/agc/digital_agc.c
Normal file
780
src/libs/webrtc/agc/digital_agc.c
Normal 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
|
||||
}
|
||||
76
src/libs/webrtc/agc/digital_agc.h
Normal file
76
src/libs/webrtc/agc/digital_agc.h
Normal 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_
|
||||
273
src/libs/webrtc/agc/gain_control.h
Normal file
273
src/libs/webrtc/agc/gain_control.h
Normal 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_
|
||||
64
src/libs/webrtc/cng/cng_helpfuns.c
Normal file
64
src/libs/webrtc/cng/cng_helpfuns.c
Normal 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
|
||||
|
||||
28
src/libs/webrtc/cng/cng_helpfuns.h
Normal file
28
src/libs/webrtc/cng/cng_helpfuns.h
Normal 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_
|
||||
735
src/libs/webrtc/cng/webrtc_cng.c
Normal file
735
src/libs/webrtc/cng/webrtc_cng.c
Normal 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;
|
||||
}
|
||||
236
src/libs/webrtc/cng/webrtc_cng.h
Normal file
236
src/libs/webrtc/cng/webrtc_cng.h
Normal 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_
|
||||
595
src/libs/webrtc/common_types.h
Normal file
595
src/libs/webrtc/common_types.h
Normal 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
|
||||
131
src/libs/webrtc/engine_configurations.h
Normal file
131
src/libs/webrtc/engine_configurations.h
Normal 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_
|
||||
83
src/libs/webrtc/g711/g711.c
Normal file
83
src/libs/webrtc/g711/g711.c
Normal 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
382
src/libs/webrtc/g711/g711.h
Normal 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 ------------------------------------------------------------*/
|
||||
171
src/libs/webrtc/g711/g711_interface.c
Normal file
171
src/libs/webrtc/g711/g711_interface.c
Normal 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;
|
||||
}
|
||||
148
src/libs/webrtc/g711/g711_interface.h
Normal file
148
src/libs/webrtc/g711/g711_interface.h
Normal 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_ */
|
||||
80
src/libs/webrtc/ilbcfix/abs_quant.c
Normal file
80
src/libs/webrtc/ilbcfix/abs_quant.c
Normal 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);
|
||||
|
||||
}
|
||||
39
src/libs/webrtc/ilbcfix/abs_quant.h
Normal file
39
src/libs/webrtc/ilbcfix/abs_quant.h
Normal 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
|
||||
95
src/libs/webrtc/ilbcfix/abs_quant_loop.c
Normal file
95
src/libs/webrtc/ilbcfix/abs_quant_loop.c
Normal 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;
|
||||
}
|
||||
}
|
||||
37
src/libs/webrtc/ilbcfix/abs_quant_loop.h
Normal file
37
src/libs/webrtc/ilbcfix/abs_quant_loop.h
Normal 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
|
||||
63
src/libs/webrtc/ilbcfix/augmented_cb_corr.c
Normal file
63
src/libs/webrtc/ilbcfix/augmented_cb_corr.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
42
src/libs/webrtc/ilbcfix/augmented_cb_corr.h
Normal file
42
src/libs/webrtc/ilbcfix/augmented_cb_corr.h
Normal 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
|
||||
42
src/libs/webrtc/ilbcfix/bw_expand.c
Normal file
42
src/libs/webrtc/ilbcfix/bw_expand.c
Normal 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);
|
||||
}
|
||||
}
|
||||
36
src/libs/webrtc/ilbcfix/bw_expand.h
Normal file
36
src/libs/webrtc/ilbcfix/bw_expand.h
Normal 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
|
||||
67
src/libs/webrtc/ilbcfix/cb_construct.c
Normal file
67
src/libs/webrtc/ilbcfix/cb_construct.c
Normal 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;
|
||||
}
|
||||
38
src/libs/webrtc/ilbcfix/cb_construct.h
Normal file
38
src/libs/webrtc/ilbcfix/cb_construct.h
Normal 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
|
||||
79
src/libs/webrtc/ilbcfix/cb_mem_energy.c
Normal file
79
src/libs/webrtc/ilbcfix/cb_mem_energy.c
Normal 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);
|
||||
}
|
||||
34
src/libs/webrtc/ilbcfix/cb_mem_energy.h
Normal file
34
src/libs/webrtc/ilbcfix/cb_mem_energy.h
Normal 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
|
||||
67
src/libs/webrtc/ilbcfix/cb_mem_energy_augmentation.c
Normal file
67
src/libs/webrtc/ilbcfix/cb_mem_energy_augmentation.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
31
src/libs/webrtc/ilbcfix/cb_mem_energy_augmentation.h
Normal file
31
src/libs/webrtc/ilbcfix/cb_mem_energy_augmentation.h
Normal 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
|
||||
65
src/libs/webrtc/ilbcfix/cb_mem_energy_calc.c
Normal file
65
src/libs/webrtc/ilbcfix/cb_mem_energy_calc.c
Normal 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);
|
||||
}
|
||||
}
|
||||
33
src/libs/webrtc/ilbcfix/cb_mem_energy_calc.h
Normal file
33
src/libs/webrtc/ilbcfix/cb_mem_energy_calc.h
Normal 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
|
||||
35
src/libs/webrtc/ilbcfix/cb_search.h
Normal file
35
src/libs/webrtc/ilbcfix/cb_search.h
Normal 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
|
||||
113
src/libs/webrtc/ilbcfix/cb_search_core.c
Normal file
113
src/libs/webrtc/ilbcfix/cb_search_core.c
Normal 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;
|
||||
}
|
||||
40
src/libs/webrtc/ilbcfix/cb_search_core.h
Normal file
40
src/libs/webrtc/ilbcfix/cb_search_core.h
Normal 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
|
||||
89
src/libs/webrtc/ilbcfix/cb_update_best_index.c
Normal file
89
src/libs/webrtc/ilbcfix/cb_update_best_index.c
Normal 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;
|
||||
}
|
||||
38
src/libs/webrtc/ilbcfix/cb_update_best_index.h
Normal file
38
src/libs/webrtc/ilbcfix/cb_update_best_index.h
Normal 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
|
||||
82
src/libs/webrtc/ilbcfix/chebyshev.c
Normal file
82
src/libs/webrtc/ilbcfix/chebyshev.c
Normal 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));
|
||||
}
|
||||
}
|
||||
37
src/libs/webrtc/ilbcfix/chebyshev.h
Normal file
37
src/libs/webrtc/ilbcfix/chebyshev.h
Normal 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
|
||||
49
src/libs/webrtc/ilbcfix/comp_corr.c
Normal file
49
src/libs/webrtc/ilbcfix/comp_corr.c
Normal 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;
|
||||
}
|
||||
}
|
||||
39
src/libs/webrtc/ilbcfix/comp_corr.h
Normal file
39
src/libs/webrtc/ilbcfix/comp_corr.h
Normal 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
|
||||
49
src/libs/webrtc/ilbcfix/complexityMeasures.m
Normal file
49
src/libs/webrtc/ilbcfix/complexityMeasures.m
Normal 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
|
||||
92
src/libs/webrtc/ilbcfix/constants.h
Normal file
92
src/libs/webrtc/ilbcfix/constants.h
Normal 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
|
||||
57
src/libs/webrtc/ilbcfix/create_augmented_vec.c
Normal file
57
src/libs/webrtc/ilbcfix/create_augmented_vec.c
Normal 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));
|
||||
}
|
||||
36
src/libs/webrtc/ilbcfix/create_augmented_vec.h
Normal file
36
src/libs/webrtc/ilbcfix/create_augmented_vec.h
Normal 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
|
||||
37
src/libs/webrtc/ilbcfix/decode.h
Normal file
37
src/libs/webrtc/ilbcfix/decode.h
Normal 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
|
||||
189
src/libs/webrtc/ilbcfix/decode_residual.c
Normal file
189
src/libs/webrtc/ilbcfix/decode_residual.c
Normal 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);
|
||||
}
|
||||
}
|
||||
38
src/libs/webrtc/ilbcfix/decode_residual.h
Normal file
38
src/libs/webrtc/ilbcfix/decode_residual.h
Normal 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
|
||||
82
src/libs/webrtc/ilbcfix/decoder_interpolate_lsf.c
Normal file
82
src/libs/webrtc/ilbcfix/decoder_interpolate_lsf.c
Normal 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);
|
||||
}
|
||||
}
|
||||
38
src/libs/webrtc/ilbcfix/decoder_interpolate_lsf.h
Normal file
38
src/libs/webrtc/ilbcfix/decoder_interpolate_lsf.h
Normal 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
|
||||
219
src/libs/webrtc/ilbcfix/defines.h
Normal file
219
src/libs/webrtc/ilbcfix/defines.h
Normal 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
|
||||
308
src/libs/webrtc/ilbcfix/do_plc.c
Normal file
308
src/libs/webrtc/ilbcfix/do_plc.c
Normal 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;
|
||||
}
|
||||
41
src/libs/webrtc/ilbcfix/do_plc.h
Normal file
41
src/libs/webrtc/ilbcfix/do_plc.h
Normal 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
|
||||
35
src/libs/webrtc/ilbcfix/encode.h
Normal file
35
src/libs/webrtc/ilbcfix/encode.h
Normal 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
|
||||
46
src/libs/webrtc/ilbcfix/energy_inverse.c
Normal file
46
src/libs/webrtc/ilbcfix/energy_inverse.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
32
src/libs/webrtc/ilbcfix/energy_inverse.h
Normal file
32
src/libs/webrtc/ilbcfix/energy_inverse.h
Normal 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
|
||||
110
src/libs/webrtc/ilbcfix/enh_upsample.c
Normal file
110
src/libs/webrtc/ilbcfix/enh_upsample.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
33
src/libs/webrtc/ilbcfix/enh_upsample.h
Normal file
33
src/libs/webrtc/ilbcfix/enh_upsample.h
Normal 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
|
||||
52
src/libs/webrtc/ilbcfix/enhancer.c
Normal file
52
src/libs/webrtc/ilbcfix/enhancer.c
Normal 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);
|
||||
}
|
||||
41
src/libs/webrtc/ilbcfix/enhancer.h
Normal file
41
src/libs/webrtc/ilbcfix/enhancer.h
Normal 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
|
||||
343
src/libs/webrtc/ilbcfix/enhancer_interface.c
Normal file
343
src/libs/webrtc/ilbcfix/enhancer_interface.c
Normal 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(®ressor[-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(®ressor[-lagmax[i]], ®ressor[-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);
|
||||
}
|
||||
34
src/libs/webrtc/ilbcfix/enhancer_interface.h
Normal file
34
src/libs/webrtc/ilbcfix/enhancer_interface.h
Normal 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
|
||||
48
src/libs/webrtc/ilbcfix/filtered_cb_vecs.c
Normal file
48
src/libs/webrtc/ilbcfix/filtered_cb_vecs.c
Normal 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;
|
||||
}
|
||||
38
src/libs/webrtc/ilbcfix/filtered_cb_vecs.h
Normal file
38
src/libs/webrtc/ilbcfix/filtered_cb_vecs.h
Normal 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
|
||||
88
src/libs/webrtc/ilbcfix/frame_classify.c
Normal file
88
src/libs/webrtc/ilbcfix/frame_classify.c
Normal 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);
|
||||
}
|
||||
29
src/libs/webrtc/ilbcfix/frame_classify.h
Normal file
29
src/libs/webrtc/ilbcfix/frame_classify.h
Normal 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
|
||||
45
src/libs/webrtc/ilbcfix/gain_dequant.c
Normal file
45
src/libs/webrtc/ilbcfix/gain_dequant.c
Normal 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));
|
||||
}
|
||||
36
src/libs/webrtc/ilbcfix/gain_dequant.h
Normal file
36
src/libs/webrtc/ilbcfix/gain_dequant.h
Normal 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
|
||||
106
src/libs/webrtc/ilbcfix/gain_quant.c
Normal file
106
src/libs/webrtc/ilbcfix/gain_quant.c
Normal 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);
|
||||
}
|
||||
35
src/libs/webrtc/ilbcfix/gain_quant.h
Normal file
35
src/libs/webrtc/ilbcfix/gain_quant.h
Normal 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
|
||||
111
src/libs/webrtc/ilbcfix/get_cd_vec.c
Normal file
111
src/libs/webrtc/ilbcfix/get_cd_vec.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/libs/webrtc/ilbcfix/get_cd_vec.h
Normal file
30
src/libs/webrtc/ilbcfix/get_cd_vec.h
Normal 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
|
||||
83
src/libs/webrtc/ilbcfix/get_lsp_poly.c
Normal file
83
src/libs/webrtc/ilbcfix/get_lsp_poly.c
Normal 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;
|
||||
}
|
||||
47
src/libs/webrtc/ilbcfix/get_lsp_poly.h
Normal file
47
src/libs/webrtc/ilbcfix/get_lsp_poly.h
Normal 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
|
||||
110
src/libs/webrtc/ilbcfix/get_sync_seq.c
Normal file
110
src/libs/webrtc/ilbcfix/get_sync_seq.c
Normal 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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/libs/webrtc/ilbcfix/get_sync_seq.h
Normal file
42
src/libs/webrtc/ilbcfix/get_sync_seq.h
Normal 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
|
||||
88
src/libs/webrtc/ilbcfix/hp_input.c
Normal file
88
src/libs/webrtc/ilbcfix/hp_input.c
Normal 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;
|
||||
}
|
||||
34
src/libs/webrtc/ilbcfix/hp_input.h
Normal file
34
src/libs/webrtc/ilbcfix/hp_input.h
Normal 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
|
||||
89
src/libs/webrtc/ilbcfix/hp_output.c
Normal file
89
src/libs/webrtc/ilbcfix/hp_output.c
Normal 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;
|
||||
}
|
||||
34
src/libs/webrtc/ilbcfix/hp_output.h
Normal file
34
src/libs/webrtc/ilbcfix/hp_output.h
Normal 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
|
||||
255
src/libs/webrtc/ilbcfix/ilbc.c
Normal file
255
src/libs/webrtc/ilbcfix/ilbc.c
Normal 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");
|
||||
}
|
||||
177
src/libs/webrtc/ilbcfix/ilbc.gyp
Normal file
177
src/libs/webrtc/ilbcfix/ilbc.gyp
Normal 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:
|
||||
260
src/libs/webrtc/ilbcfix/ilbc.h
Normal file
260
src/libs/webrtc/ilbcfix/ilbc.h
Normal 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
|
||||
|
||||
396
src/libs/webrtc/ilbcfix/ilbc_cb_search.c
Normal file
396
src/libs/webrtc/ilbcfix/ilbc_cb_search.c
Normal 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;
|
||||
}
|
||||
666
src/libs/webrtc/ilbcfix/ilbc_constants.c
Normal file
666
src/libs/webrtc/ilbcfix/ilbc_constants.c
Normal 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
|
||||
};
|
||||
244
src/libs/webrtc/ilbcfix/ilbc_decode.c
Normal file
244
src/libs/webrtc/ilbcfix/ilbc_decode.c
Normal 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;
|
||||
}
|
||||
}
|
||||
518
src/libs/webrtc/ilbcfix/ilbc_encode.c
Normal file
518
src/libs/webrtc/ilbcfix/ilbc_encode.c
Normal 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
|
||||
|
||||
}
|
||||
38
src/libs/webrtc/ilbcfix/index_conv_dec.c
Normal file
38
src/libs/webrtc/ilbcfix/index_conv_dec.c
Normal 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
Reference in New Issue
Block a user