⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ns127.c

📁 完整的EVRC压缩解压缩算法源码,附带一个简单的例子程序。
💻 C
📖 第 1 页 / 共 2 页
字号:


/* Functions */
	void r_fft(short *, short);

/* Init the window function, channel gains one time */
	if (first == TRUE)
	{
		ch_gain[0] = ch_gain[1] = SW_MAX;
		for (i = LO_CHAN; i <= HI_CHAN; i++)
			ch_enrg[i] = 0;
		for (i = 0; i < DELAY; i++)
			window_overlap[i] = 0;
		for (i = 0; i < FFT_LEN - FRM_LEN; i++)
			overlap[i] = 0;
		pre_emp_mem = 0;
		de_emp_mem = 0;
		update_cnt = 0;
		frame_cnt = 0;
	}

/* Increment frame counter */
	frame_cnt++;

/* Block normalize the input */
	normb_shift = block_norm(farray_ptr, FRM_LEN, FFT_HEADROOM);

/*
 * Preemphasize the input data and store in the data buffer with
 * appropriate delay 
 */
	for (i = 0; i < DELAY; i++)
		data_buffer[i] = shift_r(window_overlap[i], normb_shift-last_normb_shift);

	pre_emp_mem = shift_r(pre_emp_mem, normb_shift-last_normb_shift);
	last_normb_shift = normb_shift;

	data_buffer[DELAY] = add(*farray_ptr, mult(PRE_EMP_FAC, pre_emp_mem));

	for (i = DELAY + 1, j = 1; i < DELAY + FRM_LEN; i++, j++)
		data_buffer[i] = add(*(farray_ptr + j), mult(PRE_EMP_FAC, *(farray_ptr + j - 1)));

	pre_emp_mem = *(farray_ptr + FRM_LEN - 1);

	for (i = DELAY + FRM_LEN; i < FFT_LEN; i++)
		data_buffer[i] = 0;

/* update window_overlap buffer */
	for (i = 0, j = FRM_LEN; i < DELAY; i++, j++)
		window_overlap[i] = data_buffer[j];

/* Apply window to frame prior to FFT */
	for (i = 0; i < FRM_LEN + DELAY; i++)
		data_buffer[i] = mult_r(data_buffer[i], window[i]);

/* Perform FFT on the data buffer */
	r_fft(data_buffer, +1);

/* Estimate the energy in each channel */
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		enrg = 0;
		j1 = ch_tbl[i][0];
		j2 = ch_tbl[i][1];

		for (j = j1; j <= j2; j++)
		{
			enrg = L_mac(enrg, data_buffer[2 * j], data_buffer[2 * j]);
			enrg = L_mac(enrg, data_buffer[2 * j + 1], data_buffer[2 * j + 1]);
		}

		if (ch_tbl_sh[i][0] == TRUE)
			enrg = L_shr(enrg, ch_tbl_sh[i][1]);
		else
		{
			norm_shift = norm_l(enrg);
			tmp = extract_h(L_shl(enrg, norm_shift));
			enrg = L_mult(tmp, ch_tbl_sh[i][1]);
			enrg = L_shr(enrg, norm_shift);
		}

		if (first == TRUE)
			ch_enrg[i] = L_shl(enrg, 7 - (2 * normb_shift));	/* rescaled from 30,1 to 23,8 (w/block denorm) */
		else
		{
			norm_shift = norm_l(enrg);
			Ltmp1 = L_shl(enrg, norm_shift);
			Ltmp1 = L_mpy_ls(CEE_SM_FAC, extract_h(Ltmp1));
			Ltmp1 = L_shr(Ltmp1, norm_shift);
			Ltmp2 = L_shl(Ltmp1, 7 - (2 * normb_shift));	/* rescaled from 30,1 to 23,8 (w/block denorm) */

			norm_shift = norm_l(ch_enrg[i]);
			Ltmp1 = L_shl(ch_enrg[i], norm_shift);
			Ltmp3 = L_mpy_ls(ONE_MINUS_CEE_SM_FAC, extract_h(Ltmp1));
			Ltmp3 = L_shr(Ltmp3, norm_shift);

			ch_enrg[i] = L_add(Ltmp3, Ltmp2);
		}

		if (ch_enrg[i] < MIN_CHAN_ENRG)
			ch_enrg[i] = MIN_CHAN_ENRG;

	}

/* Initialize channel noise estimate to channel energy of first four frames */
	if (frame_cnt <= 4)
	{
		for (i = LO_CHAN; i <= HI_CHAN; i++)
		{
			if (ch_enrg[i] < INE_CHAN)
				ch_noise[i] = INE_NOISE;
			else
				ch_noise[i] = ch_enrg[i];
		}
	}

/* Compute the channel SNR indices */
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{

		norm_shift = norm_l(ch_noise[i]);
		Ltmp = L_shl(ch_noise[i], norm_shift);

		norm_shift1 = norm_l(ch_enrg[i]);
		Ltmp3 = L_shl(ch_enrg[i], norm_shift1 - 1);

		Ltmp2 = L_divide(Ltmp3, Ltmp);
		Ltmp2 = L_shr(Ltmp2, 27 - 1 + norm_shift1 - norm_shift);	/* scaled as 27,4 */

		if (Ltmp2 == 0)
			Ltmp2 = 1;

		Ltmp1 = fnLog10(Ltmp2);
		Ltmp3 = L_add(Ltmp1, LOG_OFFSET - 80807124);	/* -round32(log10(2^4)*2^26 */
		Ltmp2 = L_mult(TEN_S5_10, extract_h(Ltmp3));
		if (Ltmp2 < 0)
			Ltmp2 = 0;
		/* 0.1875 scaled as 10,21 */
		Ltmp1 = L_add(Ltmp2, CONST_0_1875_S10_21);
		/* tmp / 0.375  2.667 scaled as 5,10, Ltmp is scaled 15,16 */
		Ltmp = L_mult(extract_h(Ltmp1), CONST_2_667_S5_10);
		ch_snr[i] = extract_h(Ltmp);

	}

/* Compute the sum of voice metrics */
	vm_sum = 0;
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		if (ch_snr[i] < 89)
			j = ch_snr[i];
		else
			j = 89;

		vm_sum = add(vm_sum, vm_tbl[j]);
	}
/* Compute the total noise estimate (tne) and total channel energy estimate (tce) */
	tne = tce = 0;
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		tne = L_add(tne, ch_noise[i]);
		tce = L_add(tce, ch_enrg[i]);
	}

/* Calculate log spectral deviation */
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		Ltmp = ch_enrg[i];
		if (Ltmp == 0)
			Ltmp = 1;
		Ltmp1 = fnLog10(Ltmp);
		Ltmp2 = L_add(Ltmp1, LOG_OFFSET - 161614248);	/* -round32(log10(2^8)*2^26) */
		ch_enrg_db[i] = mult(TEN_S5_10, extract_h(Ltmp2));
	}

	if (first == TRUE)
		for (i = LO_CHAN; i <= HI_CHAN; i++)
			ch_enrg_long_db[i] = ch_enrg_db[i];

	ch_enrg_dev = 0;
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		tmp = abs_s(sub(ch_enrg_long_db[i], ch_enrg_db[i]));
		ch_enrg_dev = add(ch_enrg_dev, tmp);
	}

/*
 * Calculate long term integration constant as a function of total channel energy (tce) 
 * (i.e., high tce (-40 dB) -> slow integration (alpha = 0.99),
 *         low tce (-60 dB) -> fast integration (alpha = 0.50)
 */

	Ltmp1 = fnLog10(tce);
	Ltmp2 = L_add(Ltmp1, LOG_OFFSET - 161614248);	/* -round32(log10(2^8)*2^26) */
	tmp = mult(TEN_S5_10, extract_h(Ltmp2));

	tmp2 = sub(HIGH_TCE_DB, tmp);	/* HIGH_TCE_DB and tmp scaled as 10,5 */
	tmp2 = shl(tmp2, 5);		/* move scale to 5,10 get more fraction */
	tmp1 = mult(ALPHA_RAN_DIV_TCE_RAN, tmp2);
	alpha = sub(HIGH_ALPHA_S5_10, tmp1);

	if (alpha > HIGH_ALPHA_S5_10)
		alpha = HIGH_ALPHA;
	else if (alpha < LOW_ALPHA_S5_10)
		alpha = LOW_ALPHA;
	else
		alpha = shl(alpha, 5);	/* rescale from 5,10 to 0,15 alpha is a fraction */

/* Calc long term log spectral energy */
	tmp = sub(SW_MAX, alpha);
	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		Ltmp1 = L_mult(tmp, ch_enrg_db[i]);
		Ltmp2 = L_mult(alpha, ch_enrg_long_db[i]);
		ch_enrg_long_db[i] = extract_h(L_add(Ltmp1, Ltmp2));
	}

/* Set or reset the update flag */
	update_flag = FALSE;

	if (vm_sum <= UPDATE_THLD)
	{
		update_flag = TRUE;
		update_cnt = 0;
	}
	else if (tce > NOISE_FLOOR_CHAN && ch_enrg_dev < DEV_THLD)
	{
		update_cnt++;
		if (update_cnt >= UPDATE_CNT_THLD)
			update_flag = TRUE;
	}

	if (update_cnt == last_update_cnt)
		hyster_cnt++;
	else
		hyster_cnt = 0;

	last_update_cnt = update_cnt;

	if (hyster_cnt > HYSTER_CNT_THLD)
		update_cnt = 0;

/* Set or reset modify flag */
	index_cnt = 0;

	for (i = MID_CHAN; i <= HI_CHAN; i++)
		if (ch_snr[i] >= INDEX_THLD)
			index_cnt++;

	modify_flag = (index_cnt < INDEX_CNT_THLD) ? TRUE : FALSE;

/* Modify the SNR indices */
	if (modify_flag == TRUE)
	{
		for (i = LO_CHAN; i <= HI_CHAN; i++)
			if ((vm_sum <= METRIC_THLD) || (ch_snr[i] <= SETBACK_THLD))
				ch_snr[i] = 1;
	}

/* Compute the channel gains */
	Ltmp1 = fnLog10(tne);
	Ltmp1 = L_add(Ltmp1, LOG_OFFSET - 161614248);	/* -round32(log10(2^8)*2^26) */
	Ltmp1 = L_negate(Ltmp1);
	gain = L_mpy_ls(Ltmp1, TEN_S5_10);
	if (gain < MIN_GAIN)
		gain = MIN_GAIN;

	for (i = LO_CHAN; i <= HI_CHAN; i++)
	{
		if (ch_snr[i] <= SNR_THLD)
			ch_snr[i] = SNR_THLD;

		tmp = sub(ch_snr[i], SNR_THLD);
		Ltmp1 = L_mult(tmp, GAIN_SLOPE);
		Ltmp2 = L_shl(Ltmp1, 5);	/* rescaled to 10,5 */
		Ltmp = L_add(Ltmp2, gain);	/* gain scaled as 10,5 */
		if (Ltmp > 0)
			Ltmp = 0;

		Ltmp1 = L_mpy_ls(Ltmp, ONE_OVER_20);
		Ltmp1 = L_shl(Ltmp1, 5);	/* rescale Ltmp1 to 5,26 */
		if (Ltmp1 == 0)
			Ltmp1 = -1;
		Ltmp2 = fnExp10(Ltmp1);
		ftmp2 = extract_h(Ltmp2);

		j1 = ch_tbl[i][0], j2 = ch_tbl[i][1];
		for (j = j1; j <= j2; j++)
		{
			ch_gain[j] = ftmp2;
		}
	}

/* Update the channel noise estimates */

	if (update_flag == TRUE)
	{
		for (i = LO_CHAN; i <= HI_CHAN; i++)
		{
			norm_shift = norm_l(ch_noise[i]);
			Ltmp = L_shl(ch_noise[i], norm_shift);
			Ltmp1 = L_mult(extract_h(Ltmp), ONE_MINUS_CNE_SM_FAC);
			Ltmp1 = L_shr(Ltmp1, norm_shift);

			norm_shift = norm_l(ch_enrg[i]);
			Ltmp = L_shl(ch_enrg[i], norm_shift);
			Ltmp2 = L_mult(extract_h(Ltmp), CNE_SM_FAC);
			Ltmp2 = L_shr(Ltmp2, norm_shift);

			ch_noise[i] = L_add(Ltmp1, Ltmp2);

			if (ch_noise[i] < MIN_NOISE_ENRG)
				ch_noise[i] = MIN_NOISE_ENRG;
		}
	}

/* Filter the input data in the frequency domain and perform IFFT */

	for (i = 0; i < FFT_LEN / 2; i++)
	{
		data_buffer[2 * i] = mult(data_buffer[2 * i], ch_gain[i]);
		data_buffer[2 * i + 1] = mult(data_buffer[2 * i + 1], ch_gain[i]);
	}

/* Block normalize data_buffer */
	norm_shift = block_norm(data_buffer, FFT_LEN, IFFT_HEADROOM);

/* Inverse FFT */
	r_fft(data_buffer, -1);

/* Block denormalize data_buffer */
/*	block_denorm(data_buffer, FFT_LEN, normb_shift + norm_shift); */
	block_denorm(data_buffer, FFT_LEN, normb_shift + norm_shift + 1); 

/* Overlap add the filtered data from previous block.
 * Save data from this block for the next. */

	for (i = 0; i < FFT_LEN - FRM_LEN; i++)
		data_buffer[i] = add(data_buffer[i], overlap[i]);

	for (i = FRM_LEN; i < FFT_LEN; i++)
		overlap[i - FRM_LEN] = data_buffer[i];

/* Deemphasize the filtered speech and write it out to farray */
	tmp = mult(DE_EMP_FAC, de_emp_mem);
	*farray_ptr = add(data_buffer[0], tmp);

	for (i = 1; i < FRM_LEN; i++)
	{
		tmp = mult_r(DE_EMP_FAC, *(farray_ptr + i - 1));
		*(farray_ptr + i) = add(data_buffer[i], tmp);
	}

	de_emp_mem = *(farray_ptr + FRM_LEN - 1);

	first = FALSE;

}								/* end noise_suprs () */


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -