www.pudn.com > AVS_M_ver10.rar > dec_tcx.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" /* local function */ static int find_mpitch(float xri[], int lg); #ifdef NEW_TVC float ol_synth[1024+16]; #endif void decoder_tcx( int prm[], /* input: parameters */ int nbits_AVQ[], /* input: nbits in parameters of AVQ */ float A[], /* input: coefficients NxAz[M+1] */ int L_frame, /* input: frame length */ int bad_frame[], /* input: Bad frame indicator */ float exc[], /* output: exc[-lg..lg] */ float synth[], /* in/out: synth[-M..lg] */ Decoder_State_Plus *st) /* i/o : coder memory state */ { #ifdef PW_UPDATE float mem_temp1[M],mem_temp2[TILT_ORDER]; #endif #ifdef NEW_TVC int i, k, i_subfr, index, index2, lg, lext, bfi, n_pack, tmp2; float tmp, gain, fac_ns,tmp1; float *p_A, Ap[M+1],Ap1[M+1],Ap2[M+1],Ap3[TILT_ORDER+1]; float oldsynth[16]; float *xri, *xnq; float window[128+128]; float gband; int any_loss,num_loss; #else int i, k, i_subfr, index, lg, lext, bfi, n_pack; float tmp, gain, fac_ns; float *p_A, Ap[M+1],Ap1[M+1],Ap2[M+1],Ap3[TILT_ORDER+1]; float *xri, *xnq; float window[128+128]; int any_loss,num_loss; #endif xri = exc; xnq = synth; if (L_frame == (L_FRAME_PLUS/4)) { n_pack = 1; } else if (L_frame == (L_FRAME_PLUS/2)) { n_pack = 2; } else if (L_frame == (L_FRAME_PLUS)) { n_pack = 4; } else { printf( "decoder_tcx: Invalid L_frame, exiting\n" ); exit(1); } any_loss = 0; num_loss = 0; for (i=0; i pitch_tcx; for (i=0; i mem_formant,mem_temp1,M); mvr2r(st->mem_tilt,mem_temp2,TILT_ORDER); for (i_subfr=0; i_subfr mem_wsyn; E_UTIL_deemph(xnq, TILT_FAC, L_frame, &tmp); #endif tmp = 0.7f*st->wsyn_rms; st->wsyn_rms = tmp; for (i=0; i tmp) { xnq[i] = tmp; } else { if (xnq[i] < -tmp) { xnq[i] = -tmp; } } } #ifdef PW_UPDATE p_A = A; for (i_subfr=0; i_subfr mem_tilt); E_UTIL_deformant(&xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant); E_UTIL_synthesis(Ap1, &xnq[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); p_A += (M+1); } #endif #ifndef PW_UPDATE E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &(st->mem_wsyn)); p_A = A; for (i_subfr=0; i_subfr wovlp[i]=0; } } else { /*----- synthesize windowed TCX target (inverse FFT of decoded spectrum + noise fill-in) using available info ------*/ /* decode noise level (fac_ns) (stored in 2nd packet on TCX80) */ index = *prm++; if (n_pack == 4) { bfi = bad_frame[1]; } else { bfi = bad_frame[0]; } if (bfi != 0) { index = 0; } fac_ns = 0.1f*(8.0f - ((float)index)); /* read index of global TCX gain : erased bits are set to 1 to minimize global gain if bad_frame set erased bits to default value (0 or 1 depending on parameter) */ index = *prm++; #ifdef NEW_TVC /* decode gain between two bands */ index2 = *prm++; gband = (float)index2 / (float)64.0; /* decode parameters of multi-rate lattice VQ */ AVQ_demuxdec(n_pack, prm, nbits_AVQ, xri, lg/8, bad_frame); /* amplify low half band with gain gband */ for (i = 0; i < lg/2; i++){ xri[i+lg/2] /= gband; } #else /* decode parameters of multi-rate lattice VQ */ AVQ_demuxdec(n_pack, prm, nbits_AVQ, xri, lg/8, bad_frame); #endif if(any_loss) { adapt_low_freq_deemph_ecu(xri,lg,st); reconst_spect(xri,st->old_xri,n_pack,bad_frame,lg,st->last_mode,xnq); /* generate random excitation buffer */ set_zero(xnq, lg); rnd_ph16(&(st->seed_tcx), &xnq[lg/6], lg-(lg/6)); /*----------------------------------------------* * noise fill-in on unquantized subvector * * injected only from 1066Hz to 6400Hz. * *----------------------------------------------*/ for(k=lg/6; k seed_tcx), &xnq[lg/6], lg-(lg/6)); /*----------------------------------------------* * noise fill-in on unquantized subvector * * injected only from 1066Hz to 6400Hz. * *----------------------------------------------*/ for(k=lg/6; k old_xri,lg); /* find pitch for bfi case */ st->pitch_tcx = find_mpitch(xri, lg); /*-----------------------------------------------------------* * 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. * *-----------------------------------------------------------*/ xri[1] = 0.0; /* freq bin at 6400 Hz zeroed */ ifft9(xri, xnq, (short)lg); /*-----------------------------------------------------------* * decode TCX global gain, multiply xnq[] by gain. * * windowing of xnq[] for TCX overlap. * *-----------------------------------------------------------*/ bfi = 0; /* We never have a missing gain!!! */ gain = d_gain_tcx(index, xnq, lg, bfi, &(st->wsyn_rms)); #ifdef GAIN_CONCEAL_OLA gain_conceal_ola(&gain,xnq,st->wovlp,st->ovlp_size); #endif for (i=0; i ovlp_size==0){ lext=lext/2; } cos_window(window, st->ovlp_size, lext); /* adaptive windowing on overlap (beginning and end of frame) */ for (i=0; i ovlp_size; i++) { xnq[i] *= window[i]; } if (st->ovlp_size ==0){ for (i=0; i ovlp_size+i]; } } else{ for (i=0; i ovlp_size+i]; } } //下面求解帧头的交迭信号合成语音 if(st->ovlp_size==0){ if (lext==16) { mvr2r(& st->wovlp[48], oldsynth, M); tmp1= st->wovlp[80]; } else if (lext==32) { mvr2r(& st->wovlp[32], oldsynth, M); tmp1= st->wovlp[81]; } else { mvr2r( st->wovlp, oldsynth, M); tmp1= st->wovlp[82]; } #ifdef PW_UPDATE mvr2r(&st->wovlp[83], Ap1, M+1); mvr2r(st->wovlp_ap2, Ap2, M+1); mvr2r(st->wovlp_ap3, Ap3, TILT_ORDER+1); set_zero(st->wovlp, L_OVLP); set_zero(st->wovlp_ap2, 17); set_zero(st->wovlp_ap3, 3); #else mvr2r(&st->wovlp[83], Ap, M+1); set_zero(st->wovlp, L_OVLP); #endif tmp2=L_frame+lext; } /*-----------------------------------------------------------* * TCX overlap and add. Update memory for next overlap. * *-----------------------------------------------------------*/ for (i=0; i wovlp[i]; } /* save overlap for next frame */ if(st->ovlp_size==0){ for (i=0; i wovlp[i] = xnq[i+L_frame+lext]; } } else{ for (i=0; i wovlp[i] = xnq[i+L_frame]; } } for (i=lext; i wovlp[i] = 0.0; } /*-----------------------------------------------------------* * find excitation and synthesis * *-----------------------------------------------------------*/ #ifdef PW_UPDATE if(st->g_flg==0 && st->ovlp_size==0){ p_A = A; for (i_subfr=0; i_subfr mem_tilt); E_UTIL_deformant(&xnq[i_subfr+lext],Ap2,L_SUBFR,st->mem_formant); E_UTIL_synthesis(Ap1, &xnq[i_subfr+lext], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); E_UTIL_residu(p_A, &synth[i_subfr], &exc[i_subfr], L_SUBFR); p_A += (M+1); } } else{ if(st->ovlp_size==0){ E_UTIL_detilt(xnq,Ap3,lext,st->mem_tilt); E_UTIL_deformant(xnq,Ap2,lext,st->mem_formant); E_UTIL_synthesis(Ap1, xnq, st->gw_synth, lext, oldsynth, 0); mvr2r(&st->gw_synth[lext-M], ol_synth, M); p_A = A; for (i_subfr=0; i_subfr mem_tilt); E_UTIL_deformant(&xnq[i_subfr+lext],Ap2,L_SUBFR,st->mem_formant); E_UTIL_synthesis(Ap1, &xnq[i_subfr+lext], &ol_synth[i_subfr+M], L_SUBFR, &ol_synth[i_subfr], 0); E_UTIL_residu(p_A, &ol_synth[i_subfr+M], &exc[i_subfr], L_SUBFR); p_A += (M+1); } mvr2r(&ol_synth[M], synth, L_frame); st->mem_wsyn=tmp1; }else{ p_A = A; for (i_subfr=0; i_subfr mem_tilt); E_UTIL_deformant(&xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant); E_UTIL_synthesis(Ap1, &xnq[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); E_UTIL_residu(p_A, &synth[i_subfr], &exc[i_subfr], L_SUBFR); p_A += (M+1); } } } st->ovlp_size = lext; #endif #ifndef PW_UPDATE if(st->g_flg==0 && st->ovlp_size==0){ E_UTIL_f_preemph(&xnq[lext], TILT_FAC, L_frame, &(st->mem_wsyn)); p_A = A; for (i_subfr=0; i_subfr ovlp_size==0){ E_UTIL_f_preemph(xnq, TILT_FAC, tmp2, &tmp1); E_UTIL_synthesis(Ap, xnq, st->gw_synth, lext, oldsynth, 0); mvr2r(&st->gw_synth[lext-M], ol_synth, M); p_A = A; for (i_subfr=0; i_subfr mem_wsyn=tmp1; }else{ E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &(st->mem_wsyn)); p_A = A; for (i_subfr=0; i_subfr ovlp_size = lext; #endif } return; #else /*------ initialize window of TCX target : two halves of a squared root of a hanning window the first part is as long as the overlap length of past frame (ovlp_size) the second part is as long as lext -----*/ cos_window(window, st->ovlp_size, lext); /* adaptive windowing on overlap (beginning and end of frame) */ for (i=0; i ovlp_size; i++) { xnq[i] *= window[i]; } for (i=0; i ovlp_size+i]; } /*-----------------------------------------------------------* * TCX overlap and add. Update memory for next overlap. * *-----------------------------------------------------------*/ for (i=0; i wovlp[i]; } /* save overlap for next frame */ for (i=0; i wovlp[i] = xnq[i+L_frame]; } for (i=lext; i wovlp[i] = 0.0; } st->ovlp_size = lext; /*-----------------------------------------------------------* * find excitation and synthesis * *-----------------------------------------------------------*/ #ifdef PW_UPDATE p_A = A; for (i_subfr=0; i_subfr mem_tilt); E_UTIL_deformant(&xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant); E_UTIL_synthesis(Ap1, &xnq[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); E_UTIL_residu(p_A, &synth[i_subfr], &exc[i_subfr], L_SUBFR); p_A += (M+1); } #endif #ifndef PW_UPDATE E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &(st->mem_wsyn)); p_A = A; for (i_subfr=0; i_subfr max) { max = tmp; n = i; } } pitch = (float)lg*(2.0f/(float)n); /* find pitch multiple under 20ms */ if (pitch >= 256.0f) { n = 256; } else { mpitch = pitch; while (mpitch < 256.0f) { mpitch += pitch; } n = (int)floor(mpitch-pitch); } return(n); }