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

📄 cod_tcx_stereo.c

📁 关于AMR-WB+语音压缩编码的实现代码
💻 C
字号:
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "../include/amr_plus.h"


/* prototypes*/
void init_tcx_stereo_encoder(Coder_State_Plus *st)
{
	st->mem_stereo_ovlp_size = 0;
	set_zero(st->mem_stereo_ovlp,L_OVLP_2k);

}
int q_gain_pan(    /* output: return quantization index */
  float *gain      /* in/out: quantized gain            */
)
{
  int    index;
  index = (int)floor((*gain +2.0f)*(32.0f) + 0.5f);
  if (index < 0) index = 0;
  if (index > 127 ) index = 127;
  *gain = (float) index / 32.0f  - 2.0f;
  return(index); /* 0...127*/
}
void ctcx_stereo(float side[],    /* input:  speech[-M..lg]          */
		 float mono[],
		 float synth[],     /* in/out: synth[-M..lg]           */
		 float wovlp[],     /* i/o:    wovlp[0..127]           */
		 int ovlp_size,     /* input:  0, 64 or 128 (0=acelp)  */
		 int L_frame,       /* input:  frame length            */
		 int nb_bits,       /* input:  number of bits allowed  */
		 int prm[],         /* output: tcx parameters          */
		 int pre_echo)
{
	int i, k, i_subfr, lg;
	int lext=32;
	float tmp, gain, fac_ns,gain_pan;
	float  xri[L_TCX_LB];
	float  xn[L_TCX_LB];
	float  wm[L_TCX_LB];
	float  xnq[L_TCX_LB];
#ifndef COS_FAC
	float  window[L_TCX_LB];
#else
	float tmpfloat;
#endif
	float gain_shap[8];	
	/*------ set length of overlap (lext) and length of encoded frame (lg) -----*/
    switch (L_frame) {
	case 40:
		lext = 8;
		break;
	case 80:
		lext = 16;
		break;
	case 160:
		lext = 32;
		break;
	};
	lg = L_frame + lext;
	/* built window for overlaps section */
#ifndef COS_FAC
	cos_window(window, ovlp_size, lext);
#endif
	/* reduce by the correlation with the mono  */
	for (i=0; i<lg; i++){
		xn[i] = side[i];
		wm[i] = mono[i];	
	}
	/* xn[] windowing for TCX overlap and correlation */
	for (i=0; i<ovlp_size; i++) 
	{
#ifndef COS_FAC
		xn[i] *= window[i];
		wm[i] *= window[i];
#else
		tmpfloat=cos_fac(i,ovlp_size,lext);
		xn[i]*=tmpfloat;
		wm[i] *= tmpfloat;																					
#endif
	}


   for (i=0; i<lext; i++) {
#ifndef COS_FAC
		xn[L_frame+i] *= window[ovlp_size+i];
		wm[L_frame+i] *= window[ovlp_size+i];
#else
		tmpfloat=cos_fac(ovlp_size+i,ovlp_size,lext);
		xn[L_frame+i] *= tmpfloat;
		wm[L_frame+i] *= tmpfloat;															
#endif
	}

	if(pre_echo)
	{
		/* compensate for the gain */
		tmp = 0.0f;
		for(i=0;i<lg;i+=16){	
			gain_shap[i/16] = 0.001f;
			for(k=0;k<16;k++) 
			{
				gain_shap[i/16] += wm[i+k]*wm[i+k];
			}
			/* average log gain in frame */
			tmp += (float)log10(gain_shap[i/16]);
		}
		tmp /= (float)(lg/16);
		for(i=0;i<lg;i+=16){
			gain_shap[i/16] = (float) sqrt(gain_shap[i/16]*pow(10.0f,-tmp));

         gain_shap[i/16] = my_min(2.0,my_max(0.5,gain_shap[i/16]));

			for(k=0;k<16;k++) 
			{
				xn[i+k] /= gain_shap[i/16];

            wm[i+k] /= gain_shap[i/16];

			}
		}
	}
	/* compute the optimal panning gain */
	gain_pan = get_gain(xn, wm, lg);
	/* do not amplify the mono */
	/* quantize the panning gain (would be better if predictive scalar quantizer is used)*/
	nb_bits -= 7;
	prm[0] = q_gain_pan(&gain_pan);
	/* compute the target */
	for(i=0;i<lg;i++){
		xn[i] -= gain_pan * wm[i];
	}
	/*-----------------------------------------------------------*
	* Compute the FFT of xn[].                                  *
	* Coefficients (xri[]) order are                            *
	*    re[0], re[n/2], re[1], re[2], ... re[n/2-1], im[n/2-1] *
	* Note that last FFT element (re[n/2]) is zeroed.           *
	*-----------------------------------------------------------*/
	fft3(xn, xri, (short)lg);
	xri[1] = 0.0;       /* freq bin at 1000 Hz zeroed */
	/*-----------------------------------------------------------*
	* Spectral algebraic quantization                           *
	* with adaptive low frequency emphasis/deemphasis.          *
	* Noise factor is the average level of unquantized freq.    * 
	*-----------------------------------------------------------*/
	adap_low_freq_emph(xri, 4*lg);
	nb_bits -= (7);        /* gain = 7 bits */
	fac_ns = AVQ_cod(xri, prm+2, nb_bits, lg/8);
	for(i=0; i<lg; i++) 
	{
		xri[i] = (float)prm[i+2];
	}
	/*-----------------------------------------------------------*
	* Compute inverse FFT for obtaining xnq[] without noise.    *
	* Coefficients (xri[]) order are                            *
	*    re[0], re[n/2], re[1], re[2], ... re[n/2-1], im[n/2-1] *
	* Note that last FFT element (re[n/2]) is zeroed.           *
	*-----------------------------------------------------------*/
	adap_low_freq_deemph(xri,4*lg);
	xri[1] = 0.0;       /* freq bin at 6400 Hz zeroed */
	ifft3(xri, xnq, (short)lg);
	/*-----------------------------------------------------------*
	* find and quantize gain, multiply xnq[] by gain.           *
	* windowing of xnq[] for TCX overlap.                       *
	*-----------------------------------------------------------*/
	if (pre_echo) {
		for(i=0;i<lg;i+=16){
			for(k=0;k<16;k++) {
				xnq[i+k] *= gain_shap[i/16];
				xn[i+k] *= gain_shap[i/16];

            wm[i+k] *= gain_shap[i/16];

			}
		}
	}
	gain = get_gain(xn, xnq, lg);
	prm[1] = q_gain_tcx(xnq, lg, &gain);
	for (i=0; i<lg; i++) {
		xnq[i] = gain *xnq[i] + gain_pan * wm[i];
	}

	/* adaptive windowing on overlap (beginning and end of frame) */
	for (i=0; i<ovlp_size; i++) 
	{
#ifndef COS_FAC
		xnq[i] *= window[i];
#else
		tmpfloat=cos_fac(i,ovlp_size,lext);
		xnq[i] *= tmpfloat;
#endif
	}
	for (i=0; i<lext; i++) 
	{
#ifndef COS_FAC
		xnq[i+L_frame] *= window[ovlp_size+i];
#else
		tmpfloat=cos_fac(ovlp_size+i,ovlp_size,lext);
		xnq[i+L_frame] *= tmpfloat;
#endif
	}
	for (i=L_frame+lext; i<lg; i++) 
	{
		xnq[i] = 0;
	}
	/*-----------------------------------------------------------*
	* TCX overlap and add.  Update memory for next overlap.     *
	*-----------------------------------------------------------*/
	for (i=0; i<L_OVLP_2k; i++) 
	{
		xnq[i] += wovlp[i];
	}
	/* save overlap for next frame */
	for (i=0; i<lext; i++) 
	{
		wovlp[i] = xnq[i+L_frame];
	}
	for (i=lext; i<L_OVLP_2k; i++)	
	{
		wovlp[i] = 0.0;
	}
	/*-----------------------------------------------------------*
	* find excitation and synthesis                             *
	*-----------------------------------------------------------*/
	for (i_subfr=0; i_subfr<L_frame; i_subfr++)
	{
		synth[i_subfr] = xnq[i_subfr];
	}
	return;
}
/*-----------------------------------------------------------------*
* Funtion c_stereo                                             *
* ~~~~~~~~~~~~~~~~~~~~                                            *
*-----------------------------------------------------------------*/
void cod_tcx_stereo(float mono_2k[],
				 float right_2k[],
				 int param[],
				 int brMode,
				 int mod[],
				 int fscale,
				 Coder_State_Plus *st)
{
	float sig_buf_mono[TCX_L_FFT_2k];
	float sig_buf_right[TCX_L_FFT_2k];
	float sig_buf_side[TCX_L_FFT_2k];
	float synth_tcx[L_FRAME_2k];
	float synth[L_FRAME_2k];
	int ovlp_size[4+1];
	int prm_tcx[NPRM_TCX80_D];
	float ovlp[L_OVLP_2k*5];
	float ovlp_tcx[L_OVLP_2k];
	/* Scalars */
	int i, k, i2, i1, nbits, *prm;
	float snr, snr1, snr2;
	float tmp;
	/* number of bits per frame (80 ms) */
	nbits = StereoNbits[brMode]-24-4;
   if (StereoNbits[brMode]-4 > 300) nbits -= 24;

	set_zero(sig_buf_mono,TCX_L_FFT_2k);
	if(fscale == 0) {
		mvr2r(mono_2k-TCX_STEREO_DELAY_2k,sig_buf_mono,L_FRAME_2k+L_OVLP_2k);
	}
	else {
		mvr2r(mono_2k-TCX_STEREO_DELAY_2k-L_SUBFR_2k,sig_buf_mono,L_FRAME_2k+L_OVLP_2k);
	}
	set_zero(sig_buf_right,TCX_L_FFT_2k);
	if(fscale == 0) {
		mvr2r(right_2k-TCX_STEREO_DELAY_2k,sig_buf_right,L_FRAME_2k+L_OVLP_2k);
	}
	else {
    float *pt = right_2k-TCX_STEREO_DELAY_2k-L_SUBFR_2k;
		mvr2r(right_2k-TCX_STEREO_DELAY_2k-L_SUBFR_2k,sig_buf_right,L_FRAME_2k+L_OVLP_2k);
	}
	set_zero(sig_buf_side,TCX_L_FFT_2k);
	for(i=0;i<TCX_L_FFT_2k;i++) {
		sig_buf_side[i] = sig_buf_mono[i] - sig_buf_right[i];
	}
	/*---------------------------------------------------------------*
	*  Call TCX codec												*
	*---------------------------------------------------------------*/
	ovlp_size[0] = st->mem_stereo_ovlp_size;
	mvr2r(st->mem_stereo_ovlp, ovlp, L_OVLP_2k);
	snr2 = 0.0;
	for (i1=0; i1<2; i1++)
	{
		snr1 = 0.0;
		for (i2=0; i2<2; i2++)
		{
			k = (i1*2) + i2;
			/* set pointer to parameters */
			prm = param + (k*NPRM_DIV_TCX_STEREO);
			/*--------------------------------------------------*
			* Call 20MS TCX with pre-echo coder and find segmental SNR *
			*--------------------------------------------------*/
			mvr2r(&ovlp[k*L_OVLP_2k], ovlp_tcx, L_OVLP_2k);
			ctcx_stereo(
				&sig_buf_side[k*L_DIV_2k],
				&sig_buf_mono[k*L_DIV_2k],
				&synth_tcx[k*L_DIV_2k],
				ovlp_tcx,
				ovlp_size[k],
				L_FRAME_2k/4,
				nbits/4 - 2 ,
				prm_tcx,
				1);		
			tmp = segsnr(&sig_buf_side[k*L_DIV_2k], &synth_tcx[k*L_DIV_2k], L_FRAME_2k/4,L_DIV_2k);
			snr = tmp;
			mod[k] = 0;
			ovlp_size[k+1] = L_OVLP_2k/4;
			mvr2r(ovlp_tcx, &ovlp[(k+1)*L_OVLP_2k], L_OVLP_2k);
			mvr2r(&synth_tcx[k*L_DIV_2k], &synth[k*L_DIV_2k], L_FRAME_2k/4);
			mvi2i(prm_tcx, prm, NPRM_TCX20_D);
			/*--------------------------------------------------*
			* Call 20MS TCX coder and find segmental SNR       *
			*--------------------------------------------------*/
			mvr2r(&ovlp[k*L_OVLP_2k], ovlp_tcx, L_OVLP_2k);
			ctcx_stereo(
				&sig_buf_side[k*L_DIV_2k],
				&sig_buf_mono[k*L_DIV_2k],
				&synth_tcx[k*L_DIV_2k],
				ovlp_tcx,
				ovlp_size[k],
				L_FRAME_2k/4,
				nbits/4 - 2 ,
				prm_tcx,
				0);
			tmp = segsnr(&sig_buf_side[k*L_DIV_2k], &synth_tcx[k*L_DIV_2k], L_FRAME_2k/4,L_DIV_2k);
			if( tmp > snr) {
				snr = tmp;
				mod[k] = 1;
				ovlp_size[k+1] = L_OVLP_2k/4;
				mvr2r(ovlp_tcx, &ovlp[(k+1)*L_OVLP_2k], L_OVLP_2k);
				mvr2r(&synth_tcx[k*L_DIV_2k], &synth[k*L_DIV_2k], L_FRAME_2k/4);
				mvi2i(prm_tcx, prm, NPRM_TCX20_D);
			}
			snr1 += 0.5f*snr;
		} /* end of i2 */
		k = (i1*2);
		/* set pointer to parameters */
		prm = param + (k*NPRM_DIV_TCX_STEREO);
		/*--------------------------------------------------*
		* Call 40MS TCX coder and find segmental SNR       *
		*--------------------------------------------------*/
		mvr2r(&ovlp[k*L_OVLP_2k], ovlp_tcx, L_OVLP_2k);
		ctcx_stereo(
			&sig_buf_side[k*L_DIV_2k],
			&sig_buf_mono[k*L_DIV_2k],
			&synth_tcx[k*L_DIV_2k],
			ovlp_tcx,
			ovlp_size[k],
			L_FRAME_2k/2,
			nbits/2 - 4,
			prm_tcx,
			0);
		tmp = segsnr(&sig_buf_side[k*L_DIV_2k], &synth_tcx[k*L_DIV_2k], L_FRAME_2k/2, L_DIV_2k);
		/*--------------------------------------------------------*
		* Save tcx parameters if tcx segmental SNR is better     *
		*--------------------------------------------------------*/
		if (tmp > snr1)
		{
			snr1 = tmp;
			for (i=0; i<2; i++) 
			{
				mod[k+i] = 2;
			}
			ovlp_size[k+2] = L_OVLP_2k/2;
			mvr2r(ovlp_tcx, &ovlp[(k+2)*L_OVLP_2k], L_OVLP_2k);
			mvr2r(&synth_tcx[k*L_DIV_2k], &synth[k*L_DIV_2k], L_FRAME_2k/2);
			mvi2i(prm_tcx, prm, NPRM_TCX40_D);
		}
		snr2 += 0.5f*snr1;
	}
	k = 0;
	/* set pointer to parameters */
	prm = param + (k*NPRM_DIV_TCX_STEREO);
	/*--------------------------------------------------*
	* Call 80MS TCX coder and find segmental SNR       *
	*--------------------------------------------------*/
	mvr2r(&ovlp[k*L_OVLP_2k], ovlp_tcx, L_OVLP_2k);
	ctcx_stereo(
		sig_buf_side,
		sig_buf_mono,
		synth_tcx,
		ovlp_tcx,
		ovlp_size[k],
		L_FRAME_2k,
		nbits-8,
		prm_tcx,
		0);
	tmp = segsnr(sig_buf_side, synth_tcx, L_FRAME_2k, L_DIV_2k);
	/*--------------------------------------------------------*
	* Save tcx parameters if tcx segmental SNR is better     *
	*--------------------------------------------------------*/
	if (tmp > snr2)
	{
		snr2 = tmp;
		for (i=0; i<4; i++) 
		{
			mod[k+i] = 3;
		}
		ovlp_size[k+4] = L_OVLP_2k;
		mvr2r(ovlp_tcx, &ovlp[(k+4)*L_OVLP_2k], L_OVLP_2k);
		mvr2r(synth_tcx, &synth[k*L_DIV_2k], L_FRAME_2k);
		mvi2i(prm_tcx, prm, NPRM_TCX80_D);
	}
	/*--------------------------------------------------*
	* Update memory.		                            *
	*--------------------------------------------------*/
	st->mem_stereo_ovlp_size = ovlp_size[4];
	mvr2r(&ovlp[4*L_OVLP_2k], st->mem_stereo_ovlp, L_OVLP_2k);
}

⌨️ 快捷键说明

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