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;i 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); }