📄 cod_ace.c
字号:
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "../include/amr_plus.h"
void coder_acelp(
float A[], /* input: coefficients 4xAz[M+1] */
float Aq[], /* input: coefficients 4xAz_q[M+1] */
float speech[], /* input: speech[-M..lg] */
float *mem_wsp, /* in/out: wsp memory */
float *mem_wsyn, /* in/out: wsyn memory */
float synth[], /* in/out: synth[-M..lg] */
float exc[], /* in/out: exc[-(PIT_MAX+L_INTERPOL)..lg+1] */
float wovlp[], /* out: wovlp[0..128] */
int lg, /* input: frame length */
int codec_mode, /* input: AMR_WB+ mode (see cnst.h) */
float norm_corr,
float norm_corr2,
int T_op, /* input: open-loop LTP */
int T_op2, /* input: open-loop LTP */
int T_out[], /* output: integer pitch-lag */
float p_out[], /* output: pitch gain */
float c_out[], /* output: fixed codebook gain */
int pit_adj,
int *prm) /* output: acelp parameters */
{
int i, i_subfr, select;
int T0, T0_min, T0_max, index, pit_flag;
long int T0_frac;
float tmp, ener, max, mean_ener_code;
float gain_pit, gain_code, voice_fac, gain1, gain2;
float g_corr[5], g_corr2[2]; /*norm_corr, norm_corr2*/
float *p_A, *p_Aq, Ap[M+1];
float h1[L_SUBFR];
float code[L_SUBFR];
short code3GPP[L_SUBFR];
float error[M+L_SUBFR];
float cn[L_SUBFR];
float xn[L_SUBFR];
float xn2[L_SUBFR];
float dn[L_SUBFR]; /* Correlation between xn and h1 */
float y1[L_SUBFR]; /* Filtered adaptive excitation */
float y2[L_SUBFR]; /* Filtered adaptive excitation */
int PIT_MIN; /* Minimum pitch lag with resolution 1/4 */
int PIT_FR2; /* Minimum pitch lag with resolution 1/2 */
int PIT_FR1; /* Minimum pitch lag with resolution 1 */
int PIT_MAX; /* Maximum pitch lag */
if(pit_adj ==0) {
PIT_MIN = PIT_MIN_12k8;
PIT_FR2 = PIT_FR2_12k8;
PIT_FR1 = PIT_FR1_12k8;
PIT_MAX = PIT_MAX_12k8;
}
else {
i = (((pit_adj*PIT_MIN_12k8)+(FSCALE_DENOM/2))/FSCALE_DENOM)-PIT_MIN_12k8;
PIT_MIN = PIT_MIN_12k8 + i;
PIT_FR2 = PIT_FR2_12k8 - i;
PIT_FR1 = PIT_FR1_12k8;
PIT_MAX = PIT_MAX_12k8 + (6*i);
}
T_op *= OPL_DECIM;
T_op2 *= OPL_DECIM;
/* range for closed loop pitch search in 1st subframe */
T0_min = T_op - 8;
if (T0_min < PIT_MIN) {
T0_min = PIT_MIN;
}
T0_max = T0_min + 15;
if (T0_max > PIT_MAX) {
T0_max = PIT_MAX;
T0_min = T0_max - 15;
}
/*------------------------------------------------------------------------*
* Find and quantize mean_ener_code for gain quantizer (q_gain2_live.c) *
* This absolute reference replace the gains prediction. *
* This modification for AMR_WB+ have the following advantage: *
* - better quantization on attacks (onset, drum impulse, etc.) *
* - robust on packet lost. *
* - independent of previous mode (can be TCX with alg. 7 bits quantizer).*
*------------------------------------------------------------------------*/
max=0.0;
mean_ener_code = 0.0;
p_Aq = Aq;
for (i_subfr=0; i_subfr<lg; i_subfr+=L_SUBFR) {
E_UTIL_residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
ener = 0.01f;
for (i=0; i<L_SUBFR; i++) {
ener += exc[i+i_subfr]*exc[i+i_subfr];
}
ener = 10.0f*(float)log10(ener/((float)L_SUBFR));
if (ener < 0.0) {
ener = 0.0; /* ener in log (0..90dB) */
}
if (ener > max) {
max = ener;
}
mean_ener_code += 0.25f*ener;
p_Aq += (M+1);
}
/* reduce mean energy on voiced signal */
mean_ener_code -= 5.0f*norm_corr;
mean_ener_code -= 5.0f*norm_corr2;
/* quantize mean energy with 2 bits : 18, 30, 42 or 54 dB */
tmp = (mean_ener_code-18.0f) / 12.0f;
index = (int)floor(tmp + 0.5);
if (index < 0) {
index = 0;
}
if (index > 3) {
index = 3;
}
mean_ener_code = (((float)index) * 12.0f) + 18.0f;
/* limit mean energy to be able to quantize attack (table limited to +24dB) */
while ((mean_ener_code < (max-27.0)) && (index < 3)) {
index++;
mean_ener_code += 12.0;
}
*prm = index; prm++;
/*------------------------------------------------------------------------*
* Loop for every subframe in the analysis frame *
*------------------------------------------------------------------------*
* To find the pitch and innovation parameters. The subframe size is *
* L_SUBFR and the loop is repeated L_FRAME_PLUS/L_SUBFR times. *
* - compute impulse response of weighted synthesis filter (h1[]) *
* - compute the target signal for pitch search *
* - find the closed-loop pitch parameters *
* - encode the pitch dealy *
* - update the impulse response h1[] by including fixed-gain pitch *
* - find target vector for codebook search *
* - correlation between target vector and impulse response *
* - codebook search *
* - encode codebook address *
* - VQ of pitch and codebook gains *
* - find synthesis speech *
* - update states of weighting filter *
*------------------------------------------------------------------------*/
p_A = A;
p_Aq = Aq;
for (i_subfr=0; i_subfr<lg; i_subfr+=L_SUBFR) {
pit_flag = i_subfr;
if (i_subfr == (2*L_SUBFR)) {
pit_flag = 0;
/* range for closed loop pitch search in 3rd subframe */
T0_min = T_op2 - 8;
if (T0_min < PIT_MIN) {
T0_min = PIT_MIN;
}
T0_max = T0_min + 15;
if (T0_max > PIT_MAX) {
T0_max = PIT_MAX;
T0_min = T0_max - 15;
}
}
/*-----------------------------------------------------------------------*
Find the target vector for pitch search:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|------| res[n]
speech[n]---| A(z) |--------
|------| | |-------------|
zero -- (-)--| 1/A(z/gamma)|----- target xn[]
exc |-------------|
Instead of subtracting the zero-input response of filters from
the weighted input speech, the above configuration is used to
compute the target vector.
*-----------------------------------------------------------------------*/
/* find WSP (normaly done for pitch ol) */
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_residu(Ap, &speech[i_subfr], xn, L_SUBFR);
E_UTIL_deemph(xn, TILT_FAC, L_SUBFR, mem_wsp);
/* find ZIR in weighted domain */
mvr2r(&synth[i_subfr-M], error, M);
set_zero(error+M, L_SUBFR);
E_UTIL_synthesis(p_Aq, error+M, error+M, L_SUBFR, error, 0);
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_residu(Ap, error+M, xn2, L_SUBFR);
E_UTIL_deemph(xn2, TILT_FAC, L_SUBFR, mem_wsyn);
/* target xn = wsp - ZIR in weighted domain */
for (i=0; i<L_SUBFR; i++) {
xn[i] -= xn2[i];
}
/* fill current exc with residu */
E_UTIL_residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
/*--------------------------------------------------------------*
* Find target in residual domain (cn[]) for innovation search. *
*--------------------------------------------------------------*/
/* first half: xn[] --> cn[] */
set_zero(code, M);
mvr2r(xn, code+M, L_SUBFR/2);
tmp = 0.0;
E_UTIL_f_preemph(code+M, TILT_FAC, L_SUBFR/2, &tmp);
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
E_UTIL_synthesis(Ap, code+M, code+M, L_SUBFR/2, code, 0);
E_UTIL_residu(p_Aq, code+M, cn, L_SUBFR/2);
/* second half: res[] --> cn[] (approximated and faster) */
mvr2r(&exc[i_subfr+(L_SUBFR/2)], cn+(L_SUBFR/2), L_SUBFR/2);
/*---------------------------------------------------------------*
* Compute impulse response, h1[], of weighted synthesis filter *
*---------------------------------------------------------------*/
E_LPC_a_weight(p_A, Ap, GAMMA1, M);
set_zero(h1, L_SUBFR);
mvr2r(Ap, h1, M+1);
E_UTIL_synthesis(p_Aq, h1, h1, L_SUBFR, &h1[M+1], 0);
tmp = 0.0;
E_UTIL_deemph(h1, TILT_FAC, L_SUBFR, &tmp);
/*----------------------------------------------------------------------*
* Closed-loop fractional pitch search *
*----------------------------------------------------------------------*/
/* find closed loop fractional pitch lag */
T0 = E_GAIN_closed_loop_search(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
pit_flag, PIT_FR2, PIT_FR1);
/* encode pitch lag */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -