📄 npp.c
字号:
L_sum = L_mpy_ls(L_tmp4, tmp1); /* Q26 */
L_sum = L_mpy_ls(L_sum, tmp); /* Q24 */
L_sum = L_add(L_shr(L_tmp3, 6), L_shr(L_sum, 1)); /* Q23 */
if (L_sum < 1)
L_sum = 1;
shift1 = norm_l(L_sum);
biased_spect[i] = extract_h(L_shl(L_sum, shift1));
bias_shift[i] = add(sm_shift[i], sub(8, shift1));
tmp = add(MINV_SUB, shr(tmp5, 2)); /* Q13 */
tmp = add(MINV_SUB2, shr(mult(tmp5, tmp), 1)); /* Q12 */
L_sum = L_mpy_ls(L_tmp4, tmp2); /* Q29 */
L_sum = L_mpy_ls(L_sum, tmp); /* Q26 */
L_sum = L_add(L_shr(L_tmp3, 4), L_shr(L_sum, 1)); /* Q25 */
if (L_sum < 1)
L_sum = 1;
shift1 = norm_l(L_sum);
biased_spect_sub[i] = extract_h(L_shl(L_sum, shift1));
bias_sub_shift[i] = add(sm_shift[i], sub(6, shift1));
}
}
/***************************************************************************/
/* Subroutine noise_slope: compute maximum of the permitted increase of */
/* the noise estimate as a function of the mean signal variance */
/***************************************************************************/
static Shortword noise_slope()
{
Shortword noise_slope_max;
if (var_rel_av > X018_Q15)
noise_slope_max = X132_Q11;
else if ((var_rel_av < X003_Q15) || (enh_i < 50))
noise_slope_max = X88_Q11;
else if (var_rel_av < X005_Q15)
noise_slope_max = X44_Q11;
else if (var_rel_av < X006_Q15)
noise_slope_max = X22_Q11;
else
noise_slope_max = X132_Q11;
return(noise_slope_max);
}
/***************************************************************************/
/* Subroutine comp_data_shift: compare two block floating-point numbers. */
/* It actually compares x1 = (num1 * 2^shift1) and x2 = (num2 * 2^shift2). */
/* The sign of the returned value is the same as that of (x1 - x2). */
/***************************************************************************/
static Shortword comp_data_shift(Shortword num1, Shortword shift1,
Shortword num2, Shortword shift2)
{
Shortword shift;
if ((num1 > 0) && (num2 < 0))
return(1);
else if ((num1 < 0) && (num2 > 0))
return(-1);
else {
shift = sub(shift1, shift2);
if (shift > 0)
num2 = shr(num2, shift);
else
num1 = shl(num1, shift);
return(sub(num1, num2));
}
}
/***************************************************************************/
/* Subroutine min_search: find minimum of psd's in circular buffer */
/***************************************************************************/
static void min_search(Shortword biased_spect[], Shortword bias_shift[],
Shortword biased_spect_sub[],
Shortword bias_sub_shift[])
{
register Shortword i, k;
static BOOLEAN localflag[ENH_VEC_LENF]; /* local minimum indicator */
static Shortword minspec_counter = 0; /* count sub-windows */
static Shortword circb_index = 0; /* ring buffer counter */
static Shortword circb_min[ENH_VEC_LENF];
/* minimum of circular buffer */
static Shortword circb_min_shift[ENH_VEC_LENF];
Shortword noise_slope_max, tmp, tmp_shift, temp1, temp2;
Longword L_sum;
/* localflag[] is initialized to FALSE since it is static. */
if (minspec_counter == 0){
noise_slope_max = noise_slope();
for (i = 0; i < ENH_VEC_LENF; i++){
if (comp_data_shift(biased_spect[i], bias_shift[i],
act_min[i], act_min_shift[i]) < 0){
act_min[i] = biased_spect[i]; /* update minimum */
act_min_shift[i] = bias_shift[i];
act_min_sub[i] = biased_spect_sub[i];
act_min_sub_shift[i] = bias_sub_shift[i];
localflag[i] = FALSE;
}
}
/* write new minimum into ring buffer */
v_equ(circb[circb_index], act_min, ENH_VEC_LENF);
v_equ(circb_shift[circb_index], act_min_shift, ENH_VEC_LENF);
for (i = 0; i < ENH_VEC_LENF; i++){
/* Find minimum of ring buffer. Using temp1 and temp2 as cache */
/* for circb_min[i] and circb_min_shift[i]. */
temp1 = circb[0][i];
temp2 = circb_shift[0][i];
for (k = 1; k < NUM_MINWIN; k++){
if (comp_data_shift(circb[k][i], circb_shift[k][i], temp1,
temp2) < 0){
temp1 = circb[k][i];
temp2 = circb_shift[k][i];
}
}
circb_min[i] = temp1;
circb_min_shift[i] = temp2;
}
for (i = 0; i < ENH_VEC_LENF; i++){
/* rapid update in case of local minima which do not deviate
more than noise_slope_max from the current minima */
tmp = mult(noise_slope_max, circb_min[i]);
tmp_shift = add(circb_min_shift[i], 4); /* adjust for Q11 */
if (localflag[i] &&
comp_data_shift(act_min_sub[i], act_min_sub_shift[i],
circb_min[i], circb_min_shift[i]) > 0 &&
comp_data_shift(act_min_sub[i], act_min_sub_shift[i], tmp,
tmp_shift) < 0){
circb_min[i] = act_min_sub[i];
circb_min_shift[i] = act_min_sub_shift[i];
/* propagate new rapid update minimum into ring buffer */
for (k = 0; k < NUM_MINWIN; k++){
circb[k][i] = circb_min[i];
circb_shift[k][i] = circb_min_shift[i];
}
}
}
/* reset local minimum indicator */
fill(localflag, FALSE, ENH_VEC_LENF);
/* increment ring buffer pointer */
circb_index = add(circb_index, 1);
if (circb_index == NUM_MINWIN)
circb_index = 0;
} else if (minspec_counter == 1){
v_equ(act_min, biased_spect, ENH_VEC_LENF);
v_equ(act_min_shift, bias_shift, ENH_VEC_LENF);
v_equ(act_min_sub, biased_spect_sub, ENH_VEC_LENF);
v_equ(act_min_sub_shift, bias_sub_shift, ENH_VEC_LENF);
} else { /* minspec_counter > 1 */
/* At this point localflag[] is all FALSE. As we loop through */
/* minspec_counter, if any localflag[] is turned TRUE, it will be */
/* preserved until we go through the (minspec_counter == 0) branch. */
for (i = 0; i < ENH_VEC_LENF; i++){
if (comp_data_shift(biased_spect[i], bias_shift[i],
act_min[i], act_min_shift[i]) < 0){
/* update minimum */
act_min[i] = biased_spect[i];
act_min_shift[i] = bias_shift[i];
act_min_sub[i] = biased_spect_sub[i];
act_min_sub_shift[i] = bias_sub_shift[i];
localflag[i] = TRUE;
}
}
for (i = 0; i < ENH_VEC_LENF; i++){
if (comp_data_shift(act_min_sub[i], act_min_sub_shift[i],
circb_min[i], circb_min_shift[i]) < 0){
circb_min[i] = act_min_sub[i];
circb_min_shift[i] = act_min_sub_shift[i];
}
}
v_equ(noisespect, circb_min, ENH_VEC_LENF);
v_equ(noise_shift, circb_min_shift, ENH_VEC_LENF);
for (i = 0; i < ENH_VEC_LENF; i++){
L_sum = L_mult(ENH_NOISE_BIAS, noisespect[i]);
if (L_sum < 0x40000000L){
L_sum = L_shl(L_sum, 1);
lambdaD_shift[i] = noise_shift[i];
} else
lambdaD_shift[i] = add(noise_shift[i], 1);
lambdaD[i] = extract_h(L_sum);
}
}
minspec_counter = add(minspec_counter, 1);
if (minspec_counter == LEN_MINWIN)
minspec_counter = 0;
}
/***************************************************************************/
/* Subroutine enh_init: initialization of variables for the enhancement */
/***************************************************************************/
void enh_init()
{
register Shortword i;
Shortword max, shift, temp, norm_shift, guard;
Shortword a_shift;
Longword L_sum = 0, L_data;
/* initialize noise spectrum */
/* Because initial_noise[] is read once and then never used, we can use */
/* it for tempV2[] too. */
window(initial_noise, sqrt_tukey_256_180, initial_noise, ENH_WINLEN);
/* ---- Find normalization factor of the input signal ---- */
/* Starting max with 1 to avoid norm_s(0). */
max = 1;
for (i = 0; i < ENH_WINLEN; i++){
temp = abs_s(initial_noise[i]);
if (temp > max)
max = temp;
}
shift = norm_s(max);
/* Now remember the amount of shift, normalize initial_noise[], then */
/* process initial_noise[] as Q15. */
a_shift = sub(15, shift);
/* transfer to frequency domain */
v_zap(ybuf, 2*ENH_WINLEN + 2);
for (i = 0; i < ENH_WINLEN; i++)
ybuf[2*i] = shl(initial_noise[i], shift);
guard = fft_npp(ybuf, 1);
/* guard = fft(ybuf, ENH_WINLEN, MONE_Q15); */
/* get rough estimate of lambdaD */
temp_yy[0] = L_shr(L_mult(ybuf[0], ybuf[0]), 1);
temp_yy[1] = 0;
temp_yy[ENH_WINLEN] = L_shr(L_mult(ybuf[ENH_WINLEN], ybuf[ENH_WINLEN]), 1);
temp_yy[ENH_WINLEN + 1] = 0;
for (i = 2; i < ENH_WINLEN - 1; i += 2){
temp_yy[i + 1] = 0;
temp_yy[i] = L_shr(L_add(L_mult(ybuf[i], ybuf[i]),
L_mult(ybuf[i + 1], ybuf[i + 1])), 1);
}
L_sum = temp_yy[0];
for (i = 1; i < ENH_WINLEN + 1; i++){
if (L_sum < temp_yy[i])
L_sum = temp_yy[i];
}
shift = norm_l(L_sum);
for (i = 0; i < ENH_WINLEN + 1; i++)
ybuf[i] = extract_h(L_shl(temp_yy[i], shift));
shift = sub(shl(add(a_shift, guard), 1), add(shift, 7));
/* convert to correlation domain */
for (i = 0; i < ENH_WINLEN/2 - 1; i++){
ybuf[ENH_WINLEN + 2*i + 2] = ybuf[ENH_WINLEN - 2*i - 2];
ybuf[ENH_WINLEN + 2*i + 3] = negate(ybuf[ENH_WINLEN - 2*i - 2 + 1]);
}
guard = fft_npp(ybuf, -1); /* inverse fft */
/* guard = fft(ybuf, ENH_WINLEN, ONE_Q15); */
shift = add(shift, guard);
shift = sub(shift, 8);
for (i = 0; i < ENH_WINLEN; i++)
initial_noise[i] = ybuf[2*i];
max = 0;
for (i = 0; i < ENH_WINLEN; i++){
temp = abs_s(initial_noise[i]);
if (temp > max)
max = temp;
}
temp = norm_s(max);
shift = sub(shift, temp);
for (i = 0; i < ENH_WINLEN; i++)
initial_noise[i] = shl(initial_noise[i], temp);
smoothing_win(initial_noise);
/* convert back to frequency domain */
v_zap(ybuf, 2*ENH_WINLEN + 2);
for (i = 0; i < ENH_WINLEN; i++)
ybuf[2*i] = initial_noise[i];
guard = fft_npp(ybuf, 1);
/* guard = fft(ybuf, ENH_WINLEN, MONE_Q15); */
for (i = 0; i <= (ENH_WINLEN*2); i += 2){
if (ybuf[i] < 0)
ybuf[i] = 0;
}
norm_shift = add(shift, guard);
/* rough estimate of lambdaD */
L_sum = L_shl(L_mult(NOISE_B_BY_NSMTH_B, ybuf[0]), 7);
L_sum = L_add(L_sum, 2);
shift = norm_l(L_sum);
lambdaD[0] = extract_h(L_shl(L_sum, shift));
lambdaD_shift[0] = add(norm_shift, sub(1, shift));
L_sum = L_shr(L_sum, 8);
L_data = L_shl(L_mult(NOISE_B_BY_NSMTH_B, ybuf[ENH_WINLEN]), 7);
L_data = L_add(L_data, 2);
shift = norm_l(L_data);
lambdaD[ENH_WINLEN/2] = extract_h(L_shl(L_data, shift));
lambdaD_shift[ENH_WINLEN/2] = add(norm_shift, sub(1, shift));
L_sum = L_add(L_sum, L_shr(L_data, 8));
for (i = 1; i < ENH_WINLEN/2; i++){
L_data = L_shl(L_mult(NOISE_B_BY_NSMTH_B, ybuf[2*i]), 7);
L_data = L_add(L_data, 2);
shift = norm_l(L_data);
lambdaD[i] = extract_h(L_shl(L_data, shift));
lambdaD_shift[i] = add(norm_shift, sub(1, shift));
L_sum = L_add(L_sum, L_shr(L_data, 7));
}
shift = norm_l(L_sum);
n_pwr = extract_h(L_shl(L_sum, shift));
n_pwr_shift = sub(add(norm_shift, 1), shift);
/* compute initial long term SNR; speech signal power depends on
the window; the Hanning window is used as a reference here with
a squared norm of 96 Q4 */
temp = 14648; /* 0.894/2 Q15 */
shift = 22; /* exp = 22, sum = 1875000 */
SN_LT = divide_s(temp, n_pwr);
SN_LT_shift = sub(shift, n_pwr_shift);
minstat_init();
}
/***************************************************************************/
/* Subroutine minstat_init: initialization of variables for minimum */
/* statistics noise estimation */
/***************************************************************************/
static void minstat_init()
{
/* Initialize Minimum Statistics Noise Estimator */
register Shortword i;
Shortword shift;
Longword L_sum;
v_equ(smoothedspect, lambdaD, ENH_VEC_LENF);
v_scale(smoothedspect, ENH_INV_NOISE_BIAS, ENH_VEC_LENF);
for (i = 0; i < NUM_MINWIN; i++){
v_equ(circb[i], smoothedspect, ENH_VEC_LENF);
v_equ(circb_shift[i], lambdaD_shift, ENH_VEC_LENF);
}
v_equ(sm_shift, lambdaD_shift, ENH_VEC_LENF);
v_equ(act_min, smoothedspect, ENH_VEC_LENF);
v_equ(act_min_shift, lambdaD_shift, ENH_VEC_LENF);
v_equ(act_min_sub, smoothedspect, ENH_VEC_LENF);
v_equ(act_min_sub_shift, lambdaD_shift, ENH_VEC_LENF);
v_equ(noisespect, smoothedspect, ENH_VEC_LENF);
v_equ(noise_shift, lambdaD_shift, ENH_VEC_LENF);
for (i = 0; i < ENH_VEC_LENF; i++){
var_sp_av[i] = mult(smoothedspect[i], 20066); /* Q14, sqrt(3/2) */
av_shift[i] = add(lambdaD_shift[i], 1);
L_sum = L_mult(smoothedspect[i], smoothedspect[i]);
shift = norm_l(L_sum);
var_sp_2[i] = extract_h(L_shl(L_sum, shift));
av2_shift[i] = sub(shl(lambdaD_shift[i], 1), sub(shift, 1));
}
alphacorr = X09_Q15;
}
/***************************************************************************/
/* Subroutine: process_frame
**
** Description: Enhance a given frame of speech
**
** Arguments:
**
** Shortword inspeech[] ---- input speech data buffer (Q0)
** Shortword outspeech[] ---- output speech data buffer (Q0)
**
** Return value: None
**
***************************************************************************/
static void process_frame(Shortword inspeech[], Shortword outspeech[])
{
register Shortword i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -