www.pudn.com > AVS_M_ver10.rar > cod_tcx_stereo.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2007  Audio Video Coding Standard, Part ¢ú 
* 
* This software module was developed by AVS Audio sub-group 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
#include  
#include  
#include  
#include  
#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 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;imem_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); 
}