www.pudn.com > AVS_M_ver10.rar > cod_new_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" 
#include "../include/s_util.h" 
 
/* NEW_STEREO */ 
/* TO BOTTOM OF THIS FILE */ 
#define EPS			0.001f 
 
// initial stereo struction and parameter 
void init_new_stereo_encoder(NEW_STEREO_DATA *newStereo, //(i/o): Encoder states 
							 float bitrate)				 //(i): encoding bitrate 
{ 
	int i; 
 
	set_zero(newStereo->old_speech_side, L_OLD_SPEECH_ST+NEW_STEREO_DELAY); 
	set_zero(newStereo->old_speech_mono, L_OLD_SPEECH_ST+NEW_STEREO_DELAY); 
 
	set_zero(newStereo->mem_side_error, 4); 
	set_zero(newStereo->mem_mono_error, 4); 
 
	set_zero(newStereo->old_AqLF, 5*(M+1)); 
	for (i = 0;i < 5;i++) 
	{ 
		newStereo->old_AqLF[i*(M+1)]=1.0f; 
	} 
 
	set_zero(newStereo->pre_left_gain, MF_GAIN_NUM); 
	set_zero(newStereo->pre_right_gain, MF_GAIN_NUM); 
 
	newStereo->mem_ovlp_size_enc = 0; 
 
	newStereo->signalType.is_transient = 0; 
	newStereo->signalType.min_energy = 10.0f; 
	newStereo->signalType.attack_threshold = 8.0f; 
	newStereo->signalType.prev_frame_energy = 0.0f; 
 
	newStereo->bitrate = bitrate; 
 
	if (bitrate <= 32.0f) 
	{ 
		newStereo->lowfreq_end_num_l = 128; 
		newStereo->lowfreq_end_num_s = newStereo->lowfreq_end_num_l / 4; 
	} 
	else 
	{ 
		newStereo->lowfreq_end_num_l = 192; 
		newStereo->lowfreq_end_num_s = newStereo->lowfreq_end_num_l / 4; 
	} 
 
	// side exc estimation 
	set_zero(newStereo->wiener_filter, HI_FILT_ORDER*4); 
	set_zero(newStereo->old_mono_exc, HI_FILT_ORDER); 
	newStereo->filt_energy_threshold = 0.0f; 
	set_zero(newStereo->old_wh_q, HI_FILT_ORDER); 
} 
 
static void MakeSignalTypeAnalysis(NEW_STEREO_DATA *newStereo, SIGNAL_TYPE* signalType, const float *side_exc) 
{ 
	int i, b; 
	float block_energy[BLOCK_NUM+1]; 
	int block_len = L_FRAME_PLUS/BLOCK_NUM; 
 
	float attack_threshold = signalType->attack_threshold; 
	float min_attack = signalType->min_energy; 
 
	block_energy[0] = signalType->prev_frame_energy; 
	for (b = 0; b < BLOCK_NUM; b++) 
	{ 
		block_energy[b+1] = 0.0f; 
		for (i = b*block_len; i < (b+1)*block_len; i++) 
		{ 
			block_energy[b+1] += side_exc[i] * side_exc[i]; 
		} 
	} 
	signalType->prev_frame_energy = block_energy[BLOCK_NUM]; 
 
	signalType->is_transient = 0; 
	for (b = 1; b < BLOCK_NUM+1; b++) 
	{ 
		if ((block_energy[b] > attack_threshold * block_energy[b-1]) && (block_energy[b] > min_attack)) 
		{ 
			signalType->is_transient = 1; 
			break; 
		} 
	} 
} 
 
static void MakeFFTTransform(NEW_STEREO_DATA *newStereo, 
							 SIGNAL_TYPE* signalType, 
							 const float *est_side_ch, 
							 const float *side_ch,  
							 const float *mono_ch, 
							 float *side_fft, 
							 float *mono_fft, 
							 float *left_fft, 
							 float *right_fft, 
							 float *est_left_fft, 
							 float *est_right_fft) 
{ 
	int i, w; 
	int L_frame, lext, lg; 
	float  window[256]; 
	int ovlp_size; 
 
	// memory can be saved by reusing some place 
	float est_xn_side[L_FRAME_PLUS+L_OVLP]; 
	float xn_side[L_FRAME_PLUS+L_OVLP]; 
	float xn_mono[L_FRAME_PLUS+L_OVLP]; 
	float est_side_fft[L_FRAME_PLUS+L_OVLP]; 
 
	if (!signalType->is_transient)	// smooth 
	{ 
		mvr2r(est_side_ch, est_xn_side, L_FRAME_PLUS+L_OVLP); 
		mvr2r(side_ch, xn_side, L_FRAME_PLUS+L_OVLP); 
		mvr2r(mono_ch, xn_mono, L_FRAME_PLUS+L_OVLP); 
 
		lext = L_OVLP; 
		L_frame =L_FRAME_PLUS; 
 
		ovlp_size = newStereo->mem_ovlp_size_enc; 
		lg = L_frame + lext; 
		// built window for overlaps section  
		cos_window(window, ovlp_size, lext); 
 
		// est_xn_side[] etc windowing for DFT overlap  
		for (i = 0; i < ovlp_size; i++)  
		{ 
			est_xn_side[i] *= window[i]; 
			xn_side[i] *= window[i]; 
			xn_mono[i] *= window[i]; 
		} 
		for (i = 0; i < lext; i++)  
		{ 
			est_xn_side[L_frame+i] *= window[ovlp_size+i]; 
			xn_side[L_frame+i] *= window[ovlp_size+i]; 
			xn_mono[L_frame+i] *= window[ovlp_size+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.           * 
		*-----------------------------------------------------------*/ 
		fft9(est_xn_side, est_side_fft, (short)lg); 
		est_side_fft[1] = 0.0f;    // freq bin    at 6400 Hz zeroed  
 
		fft9(xn_side, side_fft, (short)lg); 
		side_fft[1] = 0.0f;    // freq bin    at 6400 Hz zeroed  
 
		fft9(xn_mono, mono_fft, (short)lg); 
		mono_fft[1] = 0.0f;       // freq bin at 6400 Hz zeroed  
 
		newStereo->mem_ovlp_size_enc = L_OVLP; 
	} 
	else 
	{ 
		lext = L_OVLP/4; 
		L_frame =L_FRAME_PLUS/4; 
		lg = L_frame + lext; 
 
		for (w = 0; w < 4; w++) 
		{ 
			float *cur_est_side_fft = est_side_fft + w * lg; 
			float *cur_side_fft = side_fft + w * lg; 
			float *cur_mono_fft = mono_fft + w * lg; 
 
			mvr2r(est_side_ch + w * lg, est_xn_side, lg);	// it IS lg NOT L_frame, because wiener_estimation ovlp 
			mvr2r(side_ch + w * L_frame, xn_side, lg); 
			mvr2r(mono_ch + w * L_frame, xn_mono, lg); 
 
			ovlp_size = newStereo->mem_ovlp_size_enc; 
 
			cos_window(window, ovlp_size, lext); 
 
			// est_xn_side[] windowing for DFT overlap  
			for (i = 0; i < ovlp_size; i++)  
			{ 
				est_xn_side[i] *= window[i]; 
				xn_side[i] *= window[i]; 
				xn_mono[i] *= window[i]; 
			} 
			for (i = 0; i < lext; i++)  
			{ 
				est_xn_side[L_frame+i] *= window[ovlp_size+i]; 
				xn_side[L_frame+i] *= window[ovlp_size+i]; 
				xn_mono[L_frame+i] *= window[ovlp_size+i]; 
			} 
 
			fft9(est_xn_side, cur_est_side_fft, (short)lg); 
			cur_est_side_fft[1] = 0.0f;    // freq bin    at 6400 Hz zeroed  
 
			fft9(xn_side, cur_side_fft, (short)lg); 
			cur_side_fft[1] = 0.0f;    // freq bin    at 6400 Hz zeroed  
 
			fft9(xn_mono, cur_mono_fft, (short)lg); 
			cur_mono_fft[1] = 0.0f;       // freq bin at 6400 Hz zeroed  
 
			newStereo->mem_ovlp_size_enc = L_OVLP/4; 
		} 
	} 
 
	// get left & right signal 
	for (i = 0; i < L_FRAME_PLUS+L_OVLP; i++) 
	{ 
		left_fft[i] = mono_fft[i] + side_fft[i]; 
		right_fft[i] = mono_fft[i] - side_fft[i]; 
 
		est_left_fft[i] = mono_fft[i] + est_side_fft[i]; 
		est_right_fft[i] = mono_fft[i] - est_side_fft[i]; 
	} 
} 
 
// find gain (for low freq AVQ) 
static float get_gain_freq(const float x[], 
						   const float y[], 
						   int n)   
{																											 
	float ener_x = 0.0f, ener_y = 1e-6f; 
	float gain; 
	float x_mag, y_mag; 
	short i; 
 
	for (i = 0; i < n/2; i++)  
	{ 
		x_mag = x[2*i]*x[2*i] + x[2*i+1]*x[2*i+1]; 
		y_mag = y[2*i]*y[2*i] + y[2*i+1]*y[2*i+1]; 
 
		ener_x += (float)sqrt(x_mag*y_mag); 
		ener_y += (float)sqrt(y_mag*y_mag); 
	} 
 
	gain = ener_x / ener_y; 
 
	return gain; 
} 
 
// quantize gain (for low freq AVQ) 
static int q_gain_new_tcx(					// output: return quantization index  
						  float code[],		// (i)  : quantized vector         
						  int lcode,       // (i)  : frame size               
						  float *gain      // in/out: quantized gain          
						  ) 
{ 
	int    i, index; 
	float  tmp, gcode0, gcode; 
	/* energy */ 
	tmp = 0.01f; 
	for(i=0; i 127) { 
		index = 127; 
	} 
	gcode = (float)pow(10.0, ((float)index)/25.0) / gcode0; 
	*gain = gcode; 
	return(index); 
} 
 
static void MakeLowFreqCoding(NEW_STEREO_DATA *newStereo, 
							  const float *side_fft, 
							  int low_freq_num,  
							  int used_bits,	// (i)number of AVQ bits 
							  int *prm)			// (o)AVQ bits stream 
{ 
	int i; 
	float fac_ns; 
	float syn_side_fft[NEW_STEREO_LF_MAX_NUM_L]; 
	float syn_side_fft_q[NEW_STEREO_LF_MAX_NUM_L]; 
	float gain; 
	float gh, gg; // wlei [20070604] 
 
	mvr2r(side_fft, syn_side_fft, low_freq_num); 
 
	/*-----------------------------------------------------------* 
	* Spectral algebraic quantization                           * 
	* with adaptive low frequency emphasis/deemphasis.          * 
	* Noise factor is the average level of unquantized freq.    *  
	*-----------------------------------------------------------*/ 
#ifdef NEW_TVC 
	adap_pulse_emph(syn_side_fft, 4*low_freq_num); 
	used_bits -= (7);        /* gain = 7 bits */ 
	AVQ_gain_allocator(syn_side_fft, low_freq_num, used_bits, &gh, &gg);	// wlei [20070604] 
	fac_ns = AVQ_cod(syn_side_fft, prm+1, used_bits, low_freq_num/8, &gh, &gg); 
#else 
	adap_low_freq_emph(syn_side_fft, 4*low_freq_num); 
	used_bits -= (7);        /* gain = 7 bits */ 
	fac_ns = AVQ_cod(syn_side_fft, prm+1, used_bits, low_freq_num/8); 
#endif 
	for(i=0; i 0) 
			{ 
				left_gain[b] = max(0.0f, left_gain[b]+gain_correlation); 
			} 
			if (right_gain[b] > 0) 
			{ 
				right_gain[b] = max(0.0f, right_gain[b]+gain_correlation); 
			} 
		} 
	} 
 
	if (newStereo->signalType.is_transient == 0) 
	{ 
		for (b = 0; b < gain_num; b++) 
		{ 
			left_error[b] = (left_gain[b]-cb_gain_hi_mean_smooth[0]) - 0.5f*newStereo->pre_left_gain[b]; 
			right_error[b] = (right_gain[b]-cb_gain_hi_mean_smooth[1]) - 0.5f*newStereo->pre_right_gain[b]; 
 
			tmpGain[0] = left_error[b]; 
			tmpGain[1] = right_error[b]; 
 
			VQ_gain(tmpGain, dico_gain_side_hf_smooth, HI_GAIN_ORDER, SIZE_GAIN_HI_MSVQ_5A, param+b); 
 
			quant_left_gain[b] = tmpGain[0] + cb_gain_hi_mean_smooth[0] + 0.5f*newStereo->pre_left_gain[b]; 
			quant_right_gain[b] = tmpGain[1] + cb_gain_hi_mean_smooth[1] + 0.5f*newStereo->pre_right_gain[b]; 
 
			quant_left_gain[b] = (float)pow(10.0, 0.05*quant_left_gain[b]); 
			quant_right_gain[b] = (float)pow(10.0, 0.05*quant_right_gain[b]); 
 
			newStereo->pre_left_gain[b] = tmpGain[0] + 0.5f*newStereo->pre_left_gain[b];  
			newStereo->pre_right_gain[b] = tmpGain[1] + 0.5f*newStereo->pre_right_gain[b]; 
		} 
	} 
	else 
	{ 
		for (b = 0; b < gain_num; b++) 
		{ 
			left_error[b] = left_gain[b] - cb_gain_hi_mean_quick[0]; 
			right_error[b] = right_gain[b] - cb_gain_hi_mean_quick[1]; 
 
			tmpGain[0] = left_error[b]; 
			tmpGain[1] = right_error[b]; 
 
			VQ_gain(tmpGain, dico_gain_side_hf_quick, HI_GAIN_ORDER, SIZE_GAIN_HI_MSVQ_5A, param+b); 
 
			tmpGain[0] += cb_gain_hi_mean_quick[0]; 
			tmpGain[1] += cb_gain_hi_mean_quick[1]; 
 
			quant_left_gain[b] = (float)pow(10.0, 0.05*tmpGain[0]); 
			quant_right_gain[b] = (float)pow(10.0, 0.05*tmpGain[1]); 
		} 
	} 
} 
 
static void MakeStereoCoding(NEW_STEREO_DATA *newStereo,  
							 SIGNAL_TYPE* signalType,  
							 const float *side_fft, 
							 const float *left_fft, 
							 const float *right_fft, 
							 const float *est_left_fft, 
							 const float *est_right_fft, 
							 int  nbits, 
							 int  *param) 
{ 
	int low_freq_num; 
	int mid_freq_num; 
	int w, lg; 
	int   *prm; 
	float *p_left_gain; 
	float *p_right_gain; 
	float *p_quant_left_gain; 
	float *p_quant_right_gain; 
	int gain_num; 
	int lf_bits; 
	int wiener_bits; 
	float gain_corr; 
 
	int hf_bits = 40; // number of mid-freq gains bits 
	prm = param + 8; // 8 mid-freq's gain 
 
	if (signalType->is_transient == 0)	// smooth frame 
	{ 
		low_freq_num = newStereo->lowfreq_end_num_l; 
		mid_freq_num = L_FRAME_PLUS + L_OVLP - low_freq_num; 
		p_left_gain = newStereo->left_gain; 
		p_right_gain = newStereo->right_gain; 
		p_quant_left_gain = newStereo->quant_left_gain; 
		p_quant_right_gain = newStereo->quant_right_gain; 
		gain_num = MF_GAIN_NUM; 
		gain_corr = newStereo->gain_correlation[0]; 
		 
		wiener_bits = 7; 
		lf_bits = nbits - wiener_bits - hf_bits;	// mid-freq gain 
 
		MakeLowFreqCoding(newStereo, 
						  side_fft, 
						  low_freq_num, 
						  lf_bits, 
						  prm); 
 
		MakeMidFreqCoding(newStereo, 
						  signalType->is_transient, 
						  left_fft+low_freq_num, 
						  right_fft+low_freq_num, 
						  est_left_fft+low_freq_num, 
						  est_right_fft+low_freq_num,				 
						  mid_freq_num,  
						  p_left_gain, 
						  p_right_gain, 
						  p_quant_left_gain, 
						  p_quant_right_gain, 
						  0, 
						  gain_num, 
						  param, 
						  gain_corr); 
	} 
	else 
	{ 
		lg = (L_FRAME_PLUS+L_OVLP)/4; 
		low_freq_num = newStereo->lowfreq_end_num_s; 
		mid_freq_num = lg - low_freq_num; 
		gain_num = MF_GAIN_NUM/4; 
 
		if (newStereo->bitrate < 32.0f) 
		{ 
			wiener_bits = 4*4; 
		} 
		else 
		{ 
			wiener_bits = 7*4; 
		} 
		lf_bits = nbits - hf_bits - wiener_bits - 3; // 3:unused bits 
 
		for (w = 0; w < 4; w++) 
		{			 
			float *cur_side_fft = side_fft + w * lg; 
			float *cur_left_fft = left_fft + w * lg; 
			float *cur_right_fft = right_fft + w * lg; 
			float *cur_est_left_fft = est_left_fft + w * lg; 
			float *cur_est_right_fft = est_right_fft + w * lg; 
			 
			int *cur_prm = prm + w * (1+low_freq_num+low_freq_num/8); //1 global gain 
			p_left_gain = newStereo->left_gain + w * gain_num; 
			p_right_gain = newStereo->right_gain + w * gain_num; 
			p_quant_left_gain = newStereo->quant_left_gain + w * gain_num; 
			p_quant_right_gain = newStereo->quant_right_gain + w * gain_num; 
			gain_corr = newStereo->gain_correlation[w]; 
 
			MakeLowFreqCoding(newStereo, 
							  cur_side_fft, 
							  low_freq_num, 
							  lf_bits/4, 
							  cur_prm); 
 
			MakeMidFreqCoding(newStereo, 
							  signalType->is_transient, 
							  cur_left_fft+low_freq_num, 
							  cur_right_fft+low_freq_num, 
							  cur_est_left_fft+low_freq_num, 
							  cur_est_right_fft+low_freq_num, 
							  mid_freq_num,  
							  p_left_gain, 
							  p_right_gain, 
							  p_quant_left_gain, 
							  p_quant_right_gain, 
							  w, 
							  gain_num, 
							  param+w*gain_num, 
							  gain_corr); 
		} 
	} 
} 
 
/* filter smoother */ 
static void smooth_ener_filter(float *filter, 
							   float *threshold) 
{ 
	float tmp, ener,old_ener; 
	int i; 
	/* compute energy over subframe */ 
	ener = 0.0001f; 
	for (i=0; i 16.0f){ 
		ener= 16.0f; 
	} 
	/* if energy *threshold)  
		{ 
			tmp = *threshold; 
		} 
	} 
	else { 
		tmp = tmp/1.414f; 
		if (tmp < *threshold)  
		{ 
			tmp = *threshold; 
		} 
	} 
	/* set the threshold for next subframer to the current modified energy */ 
	*threshold = tmp; 
	/* apply correction scale factor to HF signal */ 
	tmp = (float)sqrt(tmp/old_ener); 
	for (i=0; i 1e-10) | (y1 < -1e-10)) ? y1 : 0; 
	mem[1] = ((y2 > 1e-10) | (y2 < -1e-10)) ? y2 : 0; 
	mem[2] = ((x0 > 1e-10) | (x0 < -1e-10)) ? x0 : 0; 
	mem[3] = ((x1 > 1e-10) | (x1 < -1e-10)) ? x1 : 0; 
} 
 
static void  GetEstimatedSideExc(NEW_STEREO_DATA *newStereo, 
								 int nIsTransient, 
								 const float *side_exc,  
								 const float *mono_exc,  
								 float *est_side_exc,  
								 int est_len, 
								 int *param) 
{ 
	int k, t, j, i; 
	float tmp_mono_exc[L_FRAME_PLUS+L_OVLP+HI_FILT_ORDER]; 
	float filted_side_exc[L_FRAME_PLUS+L_OVLP]; 
	float filted_mono_exc[L_FRAME_PLUS+L_OVLP]; 
	/* covariance matrix */ 
	float r[HI_FILT_ORDER][HI_FILT_ORDER]; 
	float c[HI_FILT_ORDER]; 
	float *p_h = newStereo->wiener_filter; 
	float *x, *y; 
	int *prm; 
 
	float energy_right; 
	float energy_left; 
	float energy_mono; 
 
#if 1 
	hp1K_12k8(side_exc, filted_side_exc, newStereo->mem_side_error, est_len); 
	hp1K_12k8(mono_exc, filted_mono_exc, newStereo->mem_mono_error, est_len); 
#else 
	mvr2r(side_exc, filted_side_exc, est_len); 
	mvr2r(mono_exc, filted_mono_exc, est_len); 
#endif 
 
	mvr2r(newStereo->old_mono_exc, tmp_mono_exc, HI_FILT_ORDER); 
	mvr2r(filted_mono_exc, tmp_mono_exc+HI_FILT_ORDER, est_len); 
	mvr2r(filted_mono_exc+L_FRAME_PLUS-HI_FILT_ORDER, newStereo->old_mono_exc, HI_FILT_ORDER); 
 
	if (nIsTransient == 0)	// smooth 
	{ 
		newStereo->filt_hi_pmsvq = &filt_hi_pmsvq7; 
 
		prm = param; 
		/* set signal pointers */ 
		x = tmp_mono_exc+HI_FILT_ORDER; 
		//	y = side_exc; 
		y = filted_side_exc; 
		/* compute cross-correlation terms */ 
		for (k = 0; k < HI_FILT_ORDER; k++) 
		{ 
			c[k] = 0.0f; 
			for (t = 0; t < est_len; t++) 
			{ 
				c[k] += y[t]*x[t-k]; 
			} 
		} 
		/* compute correlation matrix */ 
		for (k = 0; k < HI_FILT_ORDER; k++) 
		{ 
			for (j = k; j < HI_FILT_ORDER; j++) 
			{ 
				r[k][j] = 0.0f; 
				for (t = 0; t < est_len; t++) 
				{ 
					r[k][j] += x[t-k]*x[t-j]; 
				} 
			} 
		} 
		/* compute a solution to the linear system */ 
		if (cholsolc(r, c, p_h, HI_FILT_ORDER)) 
		{ 
			/* cholesky failed use panning */ 
			for (k = 1; k < HI_FILT_ORDER; k++) 
			{ 
				p_h[k] = 0.0f; 
			} 
			p_h[0] = c[0]/(r[0][0]+1.0f); 
		} 
 
		energy_left = 0.001f; 
		energy_right = 0.001f; 
		energy_mono = 0.001f; 
		for (t = 0; t < est_len; t++) 
		{ 
			/* mono + side */ 
			energy_left += (x[t]+y[t]) * (x[t]+y[t]); 
			/* mono */ 
			energy_mono += x[t] * x[t]; 
			/* mono - side */ 
			energy_right += (x[t]-y[t]) * (x[t]-y[t]); 
		} 
 
		newStereo->gain_correlation[0] = (4.0f*energy_mono)/(energy_left+energy_right); 
		newStereo->gain_correlation[0] = 10.0f*(float)log10(newStereo->gain_correlation[0]); 
 
		/* wiener filter energy smoothing  */ 
		smooth_ener_filter(p_h, &newStereo->filt_energy_threshold); 
		/* quantize the filters*/ 
		quant_filt(p_h, newStereo->old_wh_q, &prm, newStereo->filt_hi_pmsvq); 
		/* local synthesis */ 
		fir_filt(p_h, HI_FILT_ORDER, x, est_side_exc, est_len); 
	} 
	else // quick signal 
	{ 
		int est_len_quick = est_len / 4; 
 
		if (newStereo->bitrate < 32.0) 
		{ 
			newStereo->filt_hi_pmsvq = &filt_hi_pmsvq4; 
		} 
		else 
		{ 
			newStereo->filt_hi_pmsvq = &filt_hi_pmsvq7; 
		} 
 
		for (i = 0; i < 4; i++) 
		{ 
			prm = param + i * 2;	// maximum: 2 msvq stages (filt) 
			/* set signal pointers */ 
			x = tmp_mono_exc + HI_FILT_ORDER + i*256; 
			//	y = side_exc; 
			y = filted_side_exc + i*256; 
			/* compute cross-correlation terms */ 
			for (k = 0; k < HI_FILT_ORDER; k++) 
			{ 
				c[k] = 0.0f; 
				for (t = 0; t < est_len_quick; t++) 
				{ 
					c[k] += y[t]*x[t-k]; 
				} 
			} 
			/* compute correlation matrix */ 
			for (k = 0; k < HI_FILT_ORDER; k++) 
			{ 
				for (j = k; j < HI_FILT_ORDER; j++) 
				{ 
					r[k][j] = 0.0f; 
					for (t = 0; t < est_len_quick; t++) 
					{ 
						r[k][j] += x[t-k]*x[t-j]; 
					} 
				} 
			} 
			/* compute a solution to the linear system */ 
			if (cholsolc(r, c, p_h, HI_FILT_ORDER)) 
			{ 
				/* cholesky failed use panning */ 
				for (k = 1; k < HI_FILT_ORDER; k++) 
				{ 
					p_h[k] = 0.0f; 
				} 
				p_h[0] = c[0]/(r[0][0]+1.0f); 
			} 
 
			energy_left = 0.001f; 
			energy_right = 0.001f; 
			energy_mono = 0.001f; 
			for (t = 0; t < est_len_quick; t++) 
			{ 
				/* mono + side */ 
				energy_left += (x[t]+y[t]) * (x[t]+y[t]); 
				/* mono */ 
				energy_mono += x[t] * x[t]; 
				/* mono - side */ 
				energy_right += (x[t]-y[t]) * (x[t]-y[t]); 
			} 
 
			newStereo->gain_correlation[i] = (4.0f*energy_mono)/(energy_left+energy_right); 
			newStereo->gain_correlation[i] = 10.0f*(float)log10(newStereo->gain_correlation[i]); 
 
			/* wiener filter energy smoothing  */ 
			smooth_ener_filter(p_h, &newStereo->filt_energy_threshold); 
			/* quantize the filters*/ 
			quant_filt(p_h, newStereo->old_wh_q, &prm, newStereo->filt_hi_pmsvq); 
			// est_side_exc has 32-point overlap every other 288-point!!!!! because it is est_len_quick(288), NO 256 
			fir_filt(p_h, HI_FILT_ORDER, x, est_side_exc+i*est_len_quick, est_len_quick); 
 
			p_h += HI_FILT_ORDER; 
		} 
	} 
} 
 
void cod_new_stereo_side(const float *sig_left,	// (i)mono channel 
					const float *sig_right,		// (i)right channel 
					int brMode,					 
					float AqLF[],				 
					int param_stereo[],			// (o)Encoded parameters 
					NEW_STEREO_DATA *newStereo)	//(i/o): Encoder states 
{ 
	int i_subfr, k; 
	int nbits; 
	float mono_exc[L_FRAME_PLUS+NEW_STEREO_DELAY];//NEW_STEREO_DELAY >= L_OVLP 
	float side_exc[L_FRAME_PLUS+NEW_STEREO_DELAY]; 
	float est_side_exc[L_FRAME_PLUS+L_OVLP]; 
	float *p_Aq; 
	int *prm = NULL; 
 
	float old_speech_side[L_TOTAL_ST+NEW_STEREO_DELAY]; 
	float *speech_side, *new_speech_side; 
	float old_speech_mono[L_TOTAL_ST+NEW_STEREO_DELAY]; 
	float *speech_mono, *new_speech_mono; 
 
	set_zero(old_speech_side, L_TOTAL_ST+NEW_STEREO_DELAY); 
	set_zero(old_speech_mono, L_TOTAL_ST+NEW_STEREO_DELAY); 
 
	new_speech_side = old_speech_side + L_OLD_SPEECH_ST + NEW_STEREO_DELAY; 
	speech_side     = old_speech_side + L_TOTAL_ST - L_FRAME_PLUS - L_A_MAX - L_BSP; 
 
	new_speech_mono = old_speech_mono + L_OLD_SPEECH_ST + NEW_STEREO_DELAY; 
	speech_mono     = old_speech_mono + L_TOTAL_ST - L_FRAME_PLUS - L_A_MAX - L_BSP; 
 
	mvr2r(newStereo->old_speech_side, old_speech_side, L_OLD_SPEECH_ST+NEW_STEREO_DELAY); 
	mvr2r(newStereo->old_speech_mono, old_speech_mono, L_OLD_SPEECH_ST+NEW_STEREO_DELAY); 
 
	mix_ch(sig_left, sig_right, new_speech_mono, L_FRAME_PLUS, 1.0f, 1.0f); 
	mvr2r(sig_right, new_speech_side, L_FRAME_PLUS); 
 
	mvr2r(old_speech_side+L_FRAME_PLUS, newStereo->old_speech_side, L_OLD_SPEECH_ST+NEW_STEREO_DELAY); 
	mvr2r(old_speech_mono+L_FRAME_PLUS, newStereo->old_speech_mono, L_OLD_SPEECH_ST+NEW_STEREO_DELAY); 
 
	// calc available bits  
	/* number of bits per frame (80 ms) */ 
	// 1 bit: signal type 
	nbits = StereoNbits[brMode]; 
 
	nbits -= 1;		// signal type, 
	 
	// get old mono lf exc 
	p_Aq = newStereo->old_AqLF; 
	residu(p_Aq, M, &speech_mono[0], &mono_exc[0], L_SUBFR/2); 
	residu(p_Aq, M, &speech_side[0], &side_exc[0], L_SUBFR/2); 
 
	p_Aq += (M+1); 
	for (i_subfr = L_SUBFR/2; i_subfr < 4*L_SUBFR+L_SUBFR/2; i_subfr+=L_SUBFR) 
	{ 
		residu(p_Aq, M, &speech_mono[i_subfr], &mono_exc[i_subfr], L_SUBFR); 
		residu(p_Aq, M, &speech_side[i_subfr], &side_exc[i_subfr], L_SUBFR); 
		p_Aq += (M+1); 
	} 
 
	// get mono lf exc, forced delay 288 in order to synchonize with decoder 
	p_Aq = AqLF; 
	for (i_subfr = L_SUBFR/2+4*L_SUBFR; i_subfr < L_FRAME_PLUS+L_SUBFR/2+4*L_SUBFR; i_subfr+=L_SUBFR) 
	{ 
		residu(p_Aq, M, &speech_mono[i_subfr], &mono_exc[i_subfr], L_SUBFR); 
		residu(p_Aq, M, &speech_side[i_subfr], &side_exc[i_subfr], L_SUBFR); 
		p_Aq += (M+1); 
	} 
	mvr2r(&AqLF[11*(M+1)], newStereo->old_AqLF, 5*(M+1)); 
 
	// get real side 
	for (k = 0; k < L_FRAME_PLUS+L_OVLP; k++) 
	{ 
		side_exc[k] = mono_exc[k] - side_exc[k]; 
	} 
 
	MakeSignalTypeAnalysis(newStereo, &newStereo->signalType, side_exc); 
	param_stereo[0] = newStereo->signalType.is_transient; 
 
	// wiener estimation 
	prm = param_stereo + 1; 
	GetEstimatedSideExc(newStereo, 
						newStereo->signalType.is_transient, 
						side_exc, 
						mono_exc, 
						est_side_exc, 
						L_FRAME_PLUS+L_OVLP, 
						prm); 
 
	// time-frequency transform 
	MakeFFTTransform(newStereo,  
					 &newStereo->signalType, 
					 est_side_exc, 
					 side_exc, 
					 mono_exc, 
					 newStereo->side_fft,  
					 newStereo->mono_fft, 
					 newStereo->left_fft, 
					 newStereo->right_fft, 
					 newStereo->est_left_fft, 
					 newStereo->est_right_fft); 
 
	// low-frequency AVQ coding and mid-frequency gain control 
	prm = param_stereo + (1+8); // 1: signal type; 8: wiener VQ 
	MakeStereoCoding(newStereo, 
					 &newStereo->signalType, 
					 newStereo->side_fft, 
					 newStereo->left_fft, 
					 newStereo->right_fft, 
					 newStereo->est_left_fft, 
					 newStereo->est_right_fft, 
					 nbits, 
					 prm); 
} 
 
static int unpack4bits_d(int nbits, int *prm, short *ptr) 
{ 
	int i; 
	i=0; 
	while (nbits > 4) 
	{ 
		int2bin(prm[i], 4, ptr); 
		ptr += 4; 
		nbits -= 4; 
		i++; 
	} 
	int2bin(prm[i], nbits, ptr); 
	i++; 
	return(i); 
} 
 
void enc_prm_new_stereo(int param[],       /* (i) : parameters                       */ 
						short serial[],    /* (o) : serial bits stream               */ 
						int nbits_pack,     /* (i) : number of bits per packet of 20ms*/ 
						int nbits_bwe,	/* (i) : number of BWE bits per 20ms  */ 
						int brMode, 
						NEW_STEREO_DATA *newStereo 
						) 
{ 
	int nbits; 
	int k,j; 
	short *ptr = NULL; 
	int *prm = NULL; 
	int mod[NB_DIV],nbits_AVQ[NB_DIV]; 
	int n_pack; 
	int prm_AVQ[(NBITS_MAX/4)+N_PACK_MAX]; 
	int hf_bits = 0; 
	int si_bits = 0; 
	int signal_type; 
 
	int low_freq_len_l = newStereo->lowfreq_end_num_l; 
	int low_freq_len_s = newStereo->lowfreq_end_num_s; 
	/*----------------------------------------------------------* 
	* Set number of bits used for stereo (per packet of 20 ms) * 
	* When stereo is transmitted, the bit ordering is:         * 
	* serial: mode (2bits), core, stereo, 2xBWE(2x16bits)      * 
	*----------------------------------------------------------*/ 
	nbits = (StereoNbits[brMode] + (2*nbits_bwe))/4; // exclude sum side's low freq 
 
	signal_type = param[0]; 
	/*----------------------------------------------------------* 
	* Encode the high band parameters	 		   * 
	*----------------------------------------------------------*/ 
	k = 0; 
 
	if (signal_type == 0)  // smooth type 
	{ 
		prm = param + 17; // skip to AVQ param 
		n_pack = 4; 
		nbits_AVQ[0] = ((StereoNbits[brMode])/4)-1-4-3-5-5;	// 
		nbits_AVQ[1] = ((StereoNbits[brMode])/4)-1-7-5-5; 
		nbits_AVQ[2] = ((StereoNbits[brMode])/4)-5-5; 
		nbits_AVQ[3] = ((StereoNbits[brMode])/4)-5-5; 
		AVQ_encmux(n_pack, prm+1, prm_AVQ, nbits_AVQ, low_freq_len_l/8); 
		/* set pointer to bit stream */ 
		ptr = serial + (k+1)*nbits_pack - nbits; 
 
		/* encode first 20 ms frame */ 
		int2bin(param[0], 1, ptr);		ptr += 1;	// signal type 
		int2bin(param[1], 4, ptr);		ptr += 4;	// 1st FIR coef 
		int2bin(param[2], 3, ptr);		ptr += 3;	// 2nd FIR coef 
		int2bin(param[9], 5, ptr);		ptr += 5;	// 1st mid-freq's gain 
		int2bin(param[10], 5, ptr);		ptr += 5;	// 2nd mid-freq's gain 
		j = unpack4bits_d(nbits_AVQ[0], prm_AVQ, ptr);	// AVQ 
		/* set pointer to bit stream */ 
		ptr = serial + (k+2)*nbits_pack - nbits; 
 
		/* encode second 20 ms frame */ 
		*ptr = 0;						ptr += 1;	// unused bits 
		int2bin(param[17], 7, ptr);		ptr += 7;	// global gain 
		int2bin(param[11], 5, ptr);		ptr += 5;	// 3rd mid-freq's gain 
		int2bin(param[12], 5, ptr);		ptr += 5;	// 4th mid-freq's gain 
		j += unpack4bits_d(nbits_AVQ[1], prm_AVQ+j, ptr); 
		/* set pointer to bit stream */ 
		ptr = serial + (k+3)*nbits_pack - nbits; 
 
		/* encode third 20 ms frame */	 
		int2bin(param[13], 5, ptr);		ptr += 5;	// 5th mid-freq's gain 
		int2bin(param[14], 5, ptr);		ptr += 5;	// 6th mid-freq's gain 
		j += unpack4bits_d(nbits_AVQ[2], prm_AVQ+j, ptr); 
		/* set pointer to bit stream */ 
		ptr = serial + (k+4)*nbits_pack - nbits; 
 
		/* encode forth 20 ms frame */ 
		int2bin(param[15], 5, ptr);		ptr += 5;	// 7th mid-freq's gain 
		int2bin(param[16], 5, ptr);		ptr += 5;	// 8th mid-freq's gain 
		unpack4bits_d(nbits_AVQ[3], prm_AVQ+j, ptr); 
	} 
	else	// quick type 
	{ 
		// side information 
		// 1st packet 
		/* set pointer to bit stream */ 
		k = 0; 
		ptr = serial + (k+1)*nbits_pack - nbits;		 
		int2bin(param[0], 1, ptr);	ptr += 1;	// signal type 
		if (newStereo->bitrate < 32.0f) 
		{ 
			int2bin(param[1], 4, ptr); ptr += 4;	// 1st FIR coef 
		} 
		else  
		{ 
			int2bin(param[1], 4, ptr); ptr += 4;	// 1st FIR coef 
			int2bin(param[2], 3, ptr); ptr += 3;	// 2nd FIR coef 
		}		 
		int2bin(param[9], 5, ptr);	ptr += 5; // 1st mid-freq's gain 
		int2bin(param[10], 5, ptr); ptr += 5; // 2nd mid-freq's gain 
		k = 1; 
		ptr = serial + (k+1)*nbits_pack - nbits;		 
		*ptr = 0;   ptr += 1;	// reserved bits		 
		if (newStereo->bitrate < 32.0f) 
		{ 
			int2bin(param[3], 4, ptr); ptr += 4;	// 1st FIR coef 
		} 
		else  
		{ 
			int2bin(param[3], 4, ptr); ptr += 4;	// 1st FIR coef 
			int2bin(param[4], 3, ptr); ptr += 3;	// 2nd FIR coef 
		}		 
		int2bin(param[11], 5, ptr); ptr += 5;	// 3rd mid-freq's gain 
		int2bin(param[12], 5, ptr); ptr += 5;	// 4th mid-freq's gain 
		// 3rd packet 
		k = 2; 
		ptr = serial + (k+1)*nbits_pack - nbits;		 
		*ptr = 0;   ptr += 1;	// reserved bits		 
		if (newStereo->bitrate < 32.0f) 
		{ 
			int2bin(param[5], 4, ptr); ptr += 4;	// 1st FIR coef 
		} 
		else  
		{ 
			int2bin(param[5], 4, ptr); ptr += 4;	// 1st FIR coef 
			int2bin(param[6], 3, ptr); ptr += 3;	// 2nd FIR coef 
		}		 
		int2bin(param[13], 5, ptr); ptr += 5;	// 5th mid-freq's gain 
		int2bin(param[14], 5, ptr); ptr += 5;	// 6th mid-freq's gain 
 
		k = 3; 
		ptr = serial + (k+1)*nbits_pack - nbits;		 
		*ptr = 0;   ptr += 1;	// reserved bits		 
		if (newStereo->bitrate < 32.0f) 
		{ 
			int2bin(param[7], 4, ptr); ptr += 4;	// 1st FIR coef 
		} 
		else  
		{ 
			int2bin(param[7], 4, ptr); ptr += 4;	// 1st FIR coef 
			int2bin(param[8], 3, ptr); ptr += 3;	// 2nd FIR coef 
		}		 
		int2bin(param[15], 5, ptr); ptr += 5;	// 7th mid-freq's gain 
		int2bin(param[16], 5, ptr); ptr += 5;	// 8th mid-freq's gain 
 
		if (newStereo->bitrate < 32.0f) 
		{ 
			si_bits = 15; 
		} 
		else 
		{ 
			si_bits = 18; 
		} 
 
		prm = param + 17; // 17 side info used 
 
		// core (SplitVQ + global gain) 
		for (k = 0; k < 4; k++)	// 4 packets 
		{ 
			n_pack = 1; 
			nbits_AVQ[0] = ((StereoNbits[brMode])/4) - si_bits - 7; // 7 global gain 
			AVQ_encmux(n_pack, prm+1, prm_AVQ, nbits_AVQ, low_freq_len_s/8); 
			/* set pointer to bit stream */ 
			ptr = serial + (k+1)*nbits_pack - nbits + si_bits; 
 
			int2bin(prm[0], 7, ptr); ptr += 7;	// global gain 
			unpack4bits_d(nbits_AVQ[0], prm_AVQ, ptr); 
 
			ptr += nbits_AVQ[0]; 
			prm += (1+(low_freq_len_s+low_freq_len_s/8)); 
		} 
	} 
 
	return; 
} 
 
/* END_NEW_STEREO */ 
/* FROM TOP OF THIS FILE */