/*==================================================================================== EVS Codec 3GPP TS26.442 Jun 30, 2015. Version CR 26.442-0010 ====================================================================================*/ #include #include #include #include "options.h" #include "prot_fx.h" #include "basop_util.h" #include "rom_dec_fx.h" #include "stl.h" /***************************************************** calcGainc calculates st->lp_gainc ******************************************************/ static void calcGainc(Word16* exc, Word16 Q_exc, Word32 old_fpitch, Word16 L_subfr, Word32 lp_gainp, Word32* lp_gainc) { Word32 L_c ; Word16 tmp16, tmp16_2, tmp16_3, tmp_e, tmp2_e, tmp_loop, i; Word32 L_acc, L_tmp; L_acc = L_deposit_l(0); L_c = L_deposit_l(0); Overflow = 0; Carry = 0; tmp16 = round_fx(old_fpitch);/*Q0*/ tmp_loop = shl(L_subfr,1); BASOP_SATURATE_WARNING_OFF tmp16_2 = round_fx(L_shl(lp_gainp,2)); /*Q31->Q15, no severe saturation, because st->lp_gainp here is [0,1]*/ BASOP_SATURATE_WARNING_ON FOR ( i=0; i< tmp_loop; i++ ) { /*st->lp_gainc += ( exc[i-2*L_subfr] - st->Mode2_lp_gainp * exc[i-2*L_subfr-(int)(st->old_fpitch+0.5f)] ) * ( exc[i-2*L_subfr] - st->Mode2_lp_gainp * exc[i-2*L_subfr-(int)(st->old_fpitch+0.5f)] );*/ tmp16_3 = sub ( exc[i-2*L_subfr] /*Q1*/, mult_r(tmp16_2 /*Q15*/, exc[i-2*L_subfr-tmp16]/*Q1*/)/*Q1*/ ); L_acc = L_macNs(L_acc,tmp16_3,tmp16_3); /*Q3*/ Overflow = 0; L_c = L_macNs(L_c,0,0); /*Accumulate Carrys*/ Carry = 0; } L_tmp = norm_llQ31(L_c,L_acc,&tmp_e);/*Q3,norm,tmp_e*/ tmp_e = add(tmp_e,31-(add(shl(Q_exc,1),1))); /*L_tmp is Q31, now*/ tmp16 = BASOP_Util_Divide3216_Scale(L_tmp/*Q31,norm,tmp_e*/,shl(L_subfr,1)/*Q15,15*/,&tmp2_e)/*Q15,tmp2_e+tmp_e-15*/; tmp_e = sub(add(tmp2_e,tmp_e), 15); IF (tmp16 != 0) { tmp16 = Sqrt16(tmp16,&tmp_e); /*Q15,norm,tmp_e*/ } *lp_gainc = L_shl(L_deposit_l(tmp16),add(tmp_e,1)); /*15Q16*/ } static void calcGainc2(Word16 *exc, Word16 Q_exc, Word16 L_subfr, Word32* lp_gainc) { Word16 i, cnt, tmp16 , tmp_e, tmp2_e; Word32 L_c, L_acc, L_tmp; Carry = 0; Overflow = 0; L_c = L_deposit_l(0); L_acc = L_deposit_l(0); cnt = shl(L_subfr,1); FOR (i=0; i < cnt; i++) { /* *gainc += ( exc[i-2*L_subfr] ) * ( exc[i-2*L_subfr]); */ L_acc = L_macNs(L_acc, exc[i-2*L_subfr] /*Q1*/, exc[i-2*L_subfr] /*Q1*/); /*Q3*/ Overflow = 0; L_c = L_macNs(L_c,0,0); /* Accumulate Carrys */ Carry = 0; } L_tmp = norm_llQ31(L_c,L_acc,&tmp_e); /*Q3,norm,tmp_e*/ tmp_e = add(tmp_e,31-(add(shl(Q_exc,1),1))); /*L_tmp is Q31, now*/ tmp16 = BASOP_Util_Divide3216_Scale(L_tmp/*Q31,norm,tmp_e*/,shl(L_subfr,1)/*Q15,15*/,&tmp2_e)/*Q15,tmp2_e+tmp_e-15*/; tmp_e = sub(add(tmp2_e,tmp_e), 15); IF ( tmp16 != 0 ) { tmp16 = Sqrt16(tmp16,&tmp_e); /*Q15,norm,tmp_e*/ } *lp_gainc = L_shl(L_deposit_l(tmp16),add(tmp_e,1)); /*15Q16*/ move32(); } /****************************************************** con_tcx \brief main function in time domain TCX concealment *******************************************************/ void con_tcx( Decoder_State_fx *st, /* i/o: coder memory state */ Word16 synth[] /* i/o: synth[] *//*Q0 */ ) { Word16 i, s, c, L_frame, L_subfr, fLowPassFilter, T0; Word16 n, mem_syn_r_size_old, mem_syn_r_size_new; Word16 *noise; Word16 mem_syn[M], *syn; Word16 *exc, buf[OLD_EXC_SIZE_DEC+L_FRAME_MAX+L_FRAME_MAX/NB_SUBFR+1+L_FRAME_MAX/2]; Word16 pre_emph_buf; Word16 hp_filt[L_FIR_FER2]; Word16 alpha; Word16 tmp_deemph, gain, gainCNG, gain_inov; Word16 *pt_exc, *pt1_exc; Word16 Tc, tmpSeed; Word16 fUseExtrapolatedPitch; Word16 *ana_window; Word16 r_h[M+1], A_local[M+1], mem, r_l[M+1]; PWord16 const *w; Word16 W1, W2, W12; Word16 Q_r; Word16 tmp16, tmp16_2, tmp_loop, tmp_e, gain_tmp; Word16 gainCNG_e, noise_e, gain_inov_e ;/*Exponents for gainCNG, noise, gain_inov*/ Word16 Q_syn; /*Q format of temporary synthesis buffer syn*/ Word32 L_tmp, L_tmp2, step32_tmp; Word32 predPitchLag, pitch_buf[NB_SUBFR16k], step32, gain32; Word16 extrapolationFailed; Word16 gainSynthDeemph; Word16 gainSynthDeemph_e; Word32 old_pitch_buf[2*NB_SUBFR16k+2]; Word16 Q_exc, new_Q, exp_scale; Word16 offset; /* inits */ alpha = 0; move16(); fUseExtrapolatedPitch = 0; move16(); extrapolationFailed = 1; move16(); noise_e = 0; move16(); Q_syn = -1; /*Q format of temporary synthesis buffer syn*/ move16(); offset = 0; move16(); /* Framing parameters */ L_frame = st->L_frameTCX; move16(); /* L_subfr = st->L_frameTCX/st->nb_subfr */ L_subfr = mult_r(st->L_frameTCX,div_s(1,st->nb_subfr)); assert( L_subfr == st->L_frameTCX/st->nb_subfr ); move32(); w = st->tcx_cfg.tcx_mdct_windowFB; /*pointer - no need to instrument*/ W1 = st->tcx_cfg.tcx_mdct_window_lengthFB; move16(); W2 = shr(st->tcx_cfg.tcx_mdct_window_lengthFB,1); W12 = shr(W1,1); /* take the previous frame last pitch */ Tc = round_fx(st->old_fpitchFB); set16_fx(buf,0,shr(sizeof(buf),1)); /* initialize buf with 0 */ c = BASOP_Util_Divide1616_Scale( L_frame, st->L_frame_fx, &s ); FOR (i=0; i < (2*NB_SUBFR16k+2); i++) { old_pitch_buf[i] = L_shl(Mpy_32_16_1(st->old_pitch_buf_fx[i],c),s); move32(); } /* set excitation memory*/ exc = buf+OLD_EXC_SIZE_DEC; tmp_deemph = shl(synth[-1],0); pre_emph_buf = synth[-1]; IF ( sub( st->nbLostCmpt , 1 ) == 0 ) { /* apply pre-emphasis to the signal */ mem = synth[-((shr(L_frame,1))+st->pit_max_TCX+M+M)-1]; Q_exc = E_UTIL_f_preemph3(&(synth[-((shr(L_frame,1))+st->pit_max_TCX+2*M)]), st->preemph_fac, add(add(shr(L_frame,1),st->pit_max_TCX),shl(M,1)), &mem,1); st->Mode2_lp_gainc = L_deposit_l(0); st->Mode2_lp_gainp = get_gain2( synth-2*L_subfr, synth-2*L_subfr-Tc, shl(L_subfr,1) ); move32(); st->Mode2_lp_gainp = L_max(st->Mode2_lp_gainp,0); st->Mode2_lp_gainp = L_min(st->Mode2_lp_gainp,65536l/*1.0f Q16*/); st->Mode2_lp_gainp = L_shl(st->Mode2_lp_gainp, 13); ana_window = buf; ham_cos_window(ana_window, mult(L_frame,24576/*0.75f Q15*/), shr(L_frame,2)); /* Autocorrelation */ autocorr_fx(&(synth[-L_frame-1]), M, r_h ,r_l , &Q_r , L_frame, ana_window, 0, 0); /* Lag windowing */ lag_wind( r_h,r_l, M, st->output_Fs_fx, LAGW_STRONG ); /* Levinson Durbin */ E_LPC_lev_dur(r_h, r_l, A_local, NULL, M, NULL); /* copy for multiple frame loss */ Copy(A_local, st->old_Aq_12_8_fx, M+1); /* Residu */ assert((2*L_subfr+Tc+1+M) <= st->old_synth_lenFB); BASOP_SATURATE_WARNING_OFF /*saturation possible in case of spiky synthesis*/ Residu3_fx( A_local, &(synth[-(2*L_subfr+Tc+1+M)]), /*Qx = Q0*/ &(exc[-(2*L_subfr+Tc+1+M)]), /*Qx+1 = Q1*/ add(add(add(shl(L_subfr,1),Tc),1),M), 1); BASOP_SATURATE_WARNING_ON } ELSE { /* apply pre-emphasis to the signal */ mem = synth[-L_frame-1]; Q_exc = E_UTIL_f_preemph3(&(synth[-L_frame]), st->preemph_fac, L_frame, &mem, 1); Copy(st->old_Aq_12_8_fx, A_local, M+1); offset = shr(L_frame,1); IF(sub(st->last_good_fx, UNVOICED_TRANSITION) >= 0 ) { tmp16 = s_max(Tc - shr(L_frame,1), 0); Copy_Scale_sig(st->old_excFB_fx, &(exc[-tmp16]), offset+tmp16, Q_exc-st->Q_exc); } ELSE { Copy_Scale_sig(st->old_excFB_fx, &(exc[-2*L_subfr]), 2*L_subfr+offset, Q_exc-st->Q_exc); } } /*-----------------------------------------------------------------* * PLC: Construct the harmonic part of excitation *-----------------------------------------------------------------*/ test(); test(); IF( sub(st->last_good_fx, UNVOICED_CLAS) > 0 && !(sub(st->last_good_fx, UNVOICED_TRANSITION) == 0 && sub(st->core_ext_mode, GENERIC) == 0) ) { IF ( sub(st->nbLostCmpt,1) == 0 ) { calcGainc( exc, Q_exc, st->old_fpitchFB, L_subfr, st->Mode2_lp_gainp, &(st->Mode2_lp_gainc)); } tmp16 = 0; move16(); if (L_sub(st->output_Fs_fx , 25600) > 0) { tmp16 = 1; move16(); } test(); test(); test(); IF( ( sub(st->nbLostCmpt,1) == 0 ) && sub(st->rf_frame_type,RF_TCXFD) >= 0 && sub(st->rf_frame_type,RF_TCXTD2) <= 0 && st->use_partial_copy ) { Word32 tcxltp_pitch_tmp = L_add(L_deposit_h(st->tcxltp_pitch_int), L_shl(L_deposit_l(div_s(st->tcxltp_pitch_fr,st->pit_res_max)),1)); /*15Q16*/ Word16 scale_tmp = mult_r(st->L_frameTCX, getInvFrameLen(st->L_frame_fx)); /*getInvFrameLen()->9Q6*/ Word16 tmp_shift = norm_s(scale_tmp); predPitchLag = L_shl(Mpy_32_16_1(tcxltp_pitch_tmp, shl(scale_tmp, tmp_shift)), sub(9, tmp_shift)); T0 = round_fx(predPitchLag); test(); test(); test(); if ( (T0 > 0) && (sub(T0,Tc) != 0) && (L_sub(L_deposit_h(abs_s(sub(T0,Tc)))/*Q16*/ , L_mult(4915/*.15f Q15*//*Q15*/,Tc/*Q0*/) /*Q16*/ ) < 0) ) { fUseExtrapolatedPitch = 1; move16(); } } ELSE { pitch_pred_linear_fit( st->nbLostCmpt, st->last_good_fx, old_pitch_buf, &(st->old_fpitchFB), &predPitchLag, st->pit_min_TCX, st->pit_max_TCX, st->mem_pitch_gain, tmp16, st->plc_use_future_lag, &extrapolationFailed, st->nb_subfr ); T0 = round_fx(predPitchLag); test(); test(); test(); if ( (T0 > 0) && (sub(T0,Tc) != 0) && (L_sub(L_deposit_h(abs_s(sub(T0,Tc)))/*Q16*/ , L_mult(4915/*.15f Q15*//*Q15*/,Tc/*Q0*/) /*Q16*/ ) < 0) && (extrapolationFailed == 0) ) { fUseExtrapolatedPitch = 1; move16(); } } fLowPassFilter = 0; move16(); pt_exc = exc + offset; pt1_exc = pt_exc - Tc; if (fUseExtrapolatedPitch != 0) { pt_exc = buf; } test(); IF( sub(st->stab_fac_fx ,32767/*1.f Q15*/) < 0 && sub(st->nbLostCmpt , 1) == 0 ) { /* pitch cycle is first low-pass filtered */ IF (L_sub(st->output_Fs_fx , 16000) <= 0) { FOR( i=0 ; i< Tc; i++ ) { move16(); *pt_exc++ = mac_r(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac( L_mult(174/* 0.0053f Q15*/, pt1_exc[-5]), 0/* 0.0000f Q15*/, pt1_exc[-4]), -1442/*-0.0440f Q15*/, pt1_exc[-3]), 0/* 0.0000f Q15*/, pt1_exc[-2]), 8641/* 0.2637f Q15*/, pt1_exc[-1]), 18022/* 0.5500f Q15*/, pt1_exc[0] ), 8641/* 0.2637f Q15*/, pt1_exc[1] ), 0/* 0.0000f Q15*/, pt1_exc[2] ), -1442/*-0.0440f Q15*/, pt1_exc[3] ), 0/* 0.0000f Q15*/, pt1_exc[4] ), 174/* 0.0053f Q15*/, pt1_exc[5] ); pt1_exc++; } } ELSE /*(st->output_Fs_fx >= 32000)*/ { FOR( i=0 ; i< Tc; i++ ) { move16(); *pt_exc++ = mac_r(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac( L_mult(-174/*-0.0053f Q15*/, pt1_exc[-5]), -121/*-0.0037f Q15*/, pt1_exc[-4]), -459/*-0.0140f Q15*/, pt1_exc[-3]), 590/* 0.0180f Q15*/, pt1_exc[-2]), 8743/* 0.2668f Q15*/, pt1_exc[-1]), 16355/* 0.4991f Q15*/, pt1_exc[0] ), 8743/* 0.2668f Q15*/, pt1_exc[1] ), 590/* 0.0180f Q15*/, pt1_exc[2] ), -459/*-0.0140f Q15*/, pt1_exc[3] ), -121/*-0.0037f Q15*/, pt1_exc[4] ), -174/*-0.0053f Q15*/, pt1_exc[5] ); pt1_exc++; } } fLowPassFilter = 1; move16(); } ELSE { /* copy the first pitch cycle without low-pass filtering */ FOR( i=0 ; i < Tc; i++ ) { *pt_exc++ = *pt1_exc++; move16(); } fLowPassFilter = 1; move16(); } if (fUseExtrapolatedPitch != 0) { pt1_exc = buf; } tmp16 = add(sub(L_frame,imult1616(fLowPassFilter,Tc)),L_subfr); FOR (i = 0; i < tmp16; i++) { *pt_exc++ = *pt1_exc++; move16(); } IF (fUseExtrapolatedPitch != 0) { get_subframe_pitch(st->nb_subfr, st->old_fpitch, /* predPitchLag * L_frame/st->L_frame, */ L_shr(Mpy_32_16_1(predPitchLag/*Q16*/, mult_r(st->L_frame_fx/*Q0*/, getInvFrameLen(L_frame)/*Q21*/ )/*Q6*/ )/*Q7*/, 7-16)/*Q16*/, pitch_buf); PulseResynchronization(buf, exc, L_frame, st->nb_subfr, st->old_fpitchFB, predPitchLag); } ELSE { set32_fx( pitch_buf, st->old_fpitch, st->nb_subfr); } IF ( sub(st->nbLostCmpt , 1) == 0 ) { pt_exc = exc+L_frame; IF (T0 == 0) { pt1_exc = pt_exc - Tc; } ELSE { pt1_exc = pt_exc - T0; } tmp_loop = shr(L_frame,1); FOR (i = 0; i < tmp_loop; i++) { *pt_exc++ = *pt1_exc++; move16(); } } if (fUseExtrapolatedPitch != 0) { st->old_fpitchFB = predPitchLag; move16(); } st->bpf_gain_param = 0; move16(); /* PLC: calculate damping factor */ alpha = Damping_fact(st->core_ext_mode, st->nbLostCmpt, st->last_good_fx, st->stab_fac_fx, &(st->Mode2_lp_gainp), 0);/*Q14*/ IF ( sub(st->nbLostCmpt , 1) == 0 ) { st->cummulative_damping = 32767/*1.f Q15*/; move16(); } ELSE { st->cummulative_damping = shl(mult_r(st->cummulative_damping/*Q15*/,alpha/*Q14*/),1)/*Q15*/; } gain32 = L_add(2147483647l/*1.f Q31*/, 0); /*Q31*/ gain = 32767/*1.f Q15*/; /*Q15*/ move16(); if( sub(st->rf_frame_type, RF_TCXTD1) == 0 && sub(st->use_partial_copy, 1) == 0 ) { gain32 = 1073741824l/*0.5f Q31*/; gain = 16384/*0.5f Q15*/; } /*step = (1.0f/(L_frame+(L_frame/2))) * (gain - alpha);*/ tmp16 = shr(imult1616(3,L_frame),1); tmp_e = norm_s(tmp16); tmp16 = shl(tmp16,tmp_e); tmp16 = div_s(16384/*1.f Q14*/,tmp16);/*Q15,1+tmp_e-15*/ tmp16_2 = sub(shr(gain,1),alpha)/*Q14*/; step32 = L_shl(L_mult(tmp16,tmp16_2)/*Q30, 1+tmp_e-15*/,add(1-14,tmp_e))/*Q31*/; /* PLC: Apply fade out */ tmp_loop = shr(imult1616(L_frame,3),1); FOR ( i=offset; i < tmp_loop; i++ ) { exc[i] = mult_r(exc[i],round_fx(gain32))/*Q1*/; move16(); gain32 = L_sub(gain32 , step32); } /* update old exc without random part */ offset = s_max(round_fx(st->old_fpitchFB) - shr(L_frame,1), 0); Copy(exc+L_frame-offset, st->old_excFB_fx, shr(L_frame,1)+offset); /* copy old_exc as 16kHz for acelp decoding */ IF ( sub(st->nbLostCmpt, 1) == 0 ) { lerp(exc - shr(L_frame,1), st->old_exc_fx, L_EXC_MEM_DEC, add(L_frame, shr(L_frame,1))); } ELSE { Copy(st->old_exc_fx+L_FRAME16k, st->old_exc_fx, L_FRAME16k/2); lerp(exc, st->old_exc_fx+L_FRAME16k/2, L_FRAME16k, L_frame); } st->Q_exc = Q_exc; } ELSE { /* No harmonic part */ set16_fx(&exc[0], 0, add(L_frame,shr(L_frame,1))); IF ( sub(st->nbLostCmpt , 1) == 0 ) { calcGainc2(&exc[0], Q_exc, L_subfr, &(st->Mode2_lp_gainc)); } set32_fx( pitch_buf, L_deposit_h(L_SUBFR), st->nb_subfr); /* PLC: calculate damping factor */ alpha = Damping_fact(st->core_ext_mode, st->nbLostCmpt, st->last_good_fx, st->stab_fac_fx, &(st->Mode2_lp_gainp), 0);/*Q14*/ } /*-----------------------------------------------------------------* * Construct the random part of excitation *-----------------------------------------------------------------*/ tmpSeed = st->seed_acelp; move16(); noise = buf; noise_e = 1;/*set exponent of noise to 1*/ move16(); tmp_loop = add(L_frame,L_FIR_FER2-1); FOR (i = 0; i < tmp_loop; i++) { tmpSeed = own_random2_fx(tmpSeed); noise[i] = shr(tmpSeed,noise_e); move16(); } st->seed_acelp = tmpSeed; move16(); tmp_loop = add(add(L_frame,shr(L_frame,1)) ,shl(L_FIR_FER2,1)); FOR ( ; i < tmp_loop; i++) { tmpSeed = own_random2_fx(tmpSeed); noise[i] = shr(tmpSeed,noise_e); move16(); } test(); IF (sub(st->last_good_fx , VOICED_CLAS)==0 || sub(st->last_good_fx , ONSET)==0) { tmp16 = 19661/*0.6f Q15*/; move16(); if ( L_sub(st->output_Fs_fx,16000) <= 0 ) { tmp16 = 6554/*0.2f Q15*/; move16(); } mem = noise[0]; move16(); preemph_copy_fx(&noise[1], &noise[1], tmp16, L_frame+(L_frame/2)+L_FIR_FER2, &mem); } /* high rate filter tuning */ IF ( L_sub(st->output_Fs_fx,16000) <= 0 ) { FOR( i=0; i< L_FIR_FER2; i++ ) { hp_filt[i] = h_high3_16[i]; move16(); } } ELSE /*(st->output_Fs_fx==32000)*/ { FOR( i=0; i< L_FIR_FER2; i++ ) { hp_filt[i] = h_high3_32[i]; move16(); } } IF ( sub(st->nbLostCmpt,1) == 0 ) { highPassFiltering(st->last_good_fx, add(add(L_frame, shr(L_frame,1)),L_FIR_FER2), noise, hp_filt, L_FIR_FER2); } ELSE { IF(sub( st->last_good_fx , UNVOICED_TRANSITION) > 0 ) { tmp_loop = add(add(L_frame,shr(L_frame,1)),L_FIR_FER2); gain_tmp = negate(add(-32768,st->cummulative_damping));/*Q15*/ FOR( i=0 ; i < tmp_loop; i++ ) { /*noise[i] = (1-st->cummulative_damping)*noise[i] + st->cummulative_damping*dot_product(&noise[i], hp_filt, L_FIR_FER2);*/ move16(); L_tmp2 = L_mac(0, noise[i+L_FIR_FER2-11], hp_filt[0+L_FIR_FER2-11]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-10], hp_filt[0+L_FIR_FER2-10]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-9], hp_filt[0+L_FIR_FER2-9]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-8], hp_filt[0+L_FIR_FER2-8]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-7], hp_filt[0+L_FIR_FER2-7]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-6], hp_filt[0+L_FIR_FER2-6]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-5], hp_filt[0+L_FIR_FER2-5]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-4], hp_filt[0+L_FIR_FER2-4]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-3], hp_filt[0+L_FIR_FER2-3]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-2], hp_filt[0+L_FIR_FER2-2]); L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-1], hp_filt[0+L_FIR_FER2-1]); L_tmp2 = Mpy_32_16_1(L_tmp2, st->cummulative_damping/*Q15*/);/*Q0, noise_e*/ noise[i] = mac_r(L_tmp2, gain_tmp,noise[i]);/*Q15, noise_e*/ } } } /* PLC: [TCX: Fade-out] retrieve background level */ tmp16 = 32767; move16(); gainSynthDeemph = getLevelSynDeemph(&(tmp16), A_local, M, shr(L_frame,2), st->preemph_fac, 1, &gainSynthDeemph_e); IF (0 != st->tcxonly) { /* gainCNG = st->conCngLevelBackgroundTrace/gainSynthDeemph; */ BASOP_Util_Divide_MantExp(st->conCngLevelBackgroundTrace, st->conCngLevelBackgroundTrace_e, gainSynthDeemph, gainSynthDeemph_e, &gainCNG, &gainCNG_e); } ELSE { /* gainCNG = st->cngTDLevel/gainSynthDeemph; */ BASOP_Util_Divide_MantExp(st->cngTDLevel, st->cngTDLevel_e, gainSynthDeemph, gainSynthDeemph_e, &gainCNG, &gainCNG_e); } gain32 = L_add(st->Mode2_lp_gainc, 0); /* start-of-the-frame gain - Q16*/ if( sub(st->rf_frame_type, RF_TCXTD1) == 0 && sub(st->use_partial_copy, 1) == 0 ) { gain32 = Mpy_32_16_1(gain32, 22938/*0.7f Q15*/); } L_tmp = L_shl(gain32,1); IF (L_sub(L_shl(L_deposit_h(gainCNG),sub(gainCNG_e,31-16)/*Q16*/) , L_tmp) > 0) { gainCNG_e = sub(15+1,norm_l(L_tmp)); gainCNG = extract_l(L_shr(L_tmp,gainCNG_e));/*Q15,gainCNG_e*/ gainCNG_e = sub(gainCNG_e,1); } /* st->Mode2_lp_gainc = alpha * (st->Mode2_lp_gainc) + (1.0f - alpha) * gainCNG;*/ /* end-of-the-frame gain */ L_tmp = Mpy_32_16_1(st->Mode2_lp_gainc,alpha)/*Q15*/; L_tmp2 = L_mult(sub(16384/*1.f Q14*/,alpha)/*Q14*/,gainCNG/*Q15,gainCNG_e*/);/*Q30,gainCNG_e*/ st->Mode2_lp_gainc = BASOP_Util_Add_Mant32Exp(L_tmp,31-15,L_tmp2,add(gainCNG_e,31-30),&tmp_e);/*Q31*/ move32(); st->Mode2_lp_gainc = L_shl(st->Mode2_lp_gainc,sub(tmp_e,31-16)); move32(); /* PLC: [TCX: Fade-out] Linearly attenuate the gain through the frame */ /*step = (1.0f/L_frame) * (gain - (st->Mode2_lp_gainc));*/ L_tmp = L_sub(gain32,st->Mode2_lp_gainc);/*Q16*/ tmp_e = norm_l(L_tmp); L_tmp = L_shl(L_tmp,tmp_e);/*Q16,-tmp_e*/ step32 = Mpy_32_16_1(L_tmp/*Q16,-tmp_e*/,getInvFrameLen(L_frame)/*W16Q21*/);/*Q22,-tmp_e*/ step32 = L_shl(step32,sub((25-22),tmp_e));/*Q25*/ pt_exc = noise + L_FIR_FER2/2; /*gain_inov = 1.0f / (float)sqrt( dot_product( pt_exc, pt_exc, L_frame ) / L_frame + 0.01f );*//* normalize energy */ L_tmp = Dot_productSq16HQ(0,pt_exc/*Q0,15+1*/,L_frame,&tmp_e)/*Q31,tmp_e+16+16*/; L_tmp = Mpy_32_16_1(L_tmp,getInvFrameLen(L_frame)/*W16Q21*/)/*W32Q37,tmp_e+16+16*//*Q5,tmp_e*/; tmp_e = add(tmp_e,31-5);/*-->Q31*/ gain_inov = round_fx(ISqrt32(L_tmp,&tmp_e));/*Q15,tmp_e*/ gain_inov_e = tmp_e; move16(); test(); test(); IF (sub(st->last_good_fx , UNVOICED_CLAS) == 0 && sub(st->core_ext_mode , UNVOICED) != 0) { gain_inov = mult_r(gain_inov,26214/*0.8f Q15*/); } ELSE IF (!( sub(st->last_good_fx , UNVOICED_CLAS) == 0 || sub(st->last_good_fx , UNVOICED_TRANSITION) == 0 )) { /*gain_inov *= (1.1f- 0.75*st->lp_gainp);*/ L_tmp = Mpy_32_16_1(L_sub(590558016l/*1.1f Q29*/, Mpy_32_16_1(st->Mode2_lp_gainp,24576))/*Q29*/,gain_inov/*Q15,gain_inov_e*/);/*Q29,gain_inov_e*/ tmp_e = norm_l(L_tmp); L_tmp = L_shl(L_tmp,tmp_e); gain_inov_e = add(sub(gain_inov_e,tmp_e),31-29);/*->Q31*/ gain_inov = round_fx(L_tmp);/*Q15,gain_inov_e*/ } st->Mode2_lp_gainp = L_shr(L_deposit_h(alpha/*Q14*/)/*Q14+16*/,1);/*Q29*/ pt_exc = noise; /* non-causal ringing of the FIR filter */ tmp_e = norm_l(gain32); tmp_e = sub(tmp_e,5); /*5 Bit additional Headroom for the gain - should be enough*/ gain32 = L_shl(gain32,tmp_e);/*Q16,-tmp_e*/ L_tmp = Mpy_32_16_1(gain32/*Q16,-tmp_e*/, gain_inov/*Q15,gain_inov_e*/)/*Q16,gain_inov_e-tmp_e*/; gain_tmp = round_fx(L_tmp);/*Q0, gain_inov_e-tmp_e*/ FOR( i=0 ; i< L_FIR_FER2/2; i++ ) { *pt_exc = mult_r(*pt_exc,gain_tmp);/*Q-15,noise_e+gain_inov_e-tmp_e*/ move16(); pt_exc++; } tmp16 = add(L_frame,L_FIR_FER2/2); step32_tmp = L_shl(step32/*Q25*/,sub(tmp_e,(25-16)));/*Q16,-tmp_e*/ FOR( i=0 ; i< tmp16; i++ ) /* Actual filtered random part of excitation */ { *pt_exc = mult_r(*pt_exc, gain_tmp); move16(); pt_exc++; gain32 = L_sub(gain32/*Q16,-tmp_e*/,step32_tmp);/*Q16,-tmp_e*/ gain_tmp = mult_r(round_fx(gain32/*Q16,-tmp_e*/)/*Q0*/, gain_inov/*Q15,gain_inov_e*/)/*Q0,gain_inov_e-tmp_e*/; } tmp16 = shr(L_frame,1); FOR( i=0 ; i< tmp16; i++ ) /* causal ringing of the FIR filter */ { *pt_exc = mult_r(*pt_exc , gain_tmp); move16(); pt_exc++; } noise_e = add(sub(add(noise_e,gain_inov_e),tmp_e),15);/*--> noise is Q0, noise_e*/ /*buf[0;L_FIR_FER2 + L_Frame + L_Frame/2] Q0, noise_e*/ /*-----------------------------------------------------------------* * Construct the total excitation *-----------------------------------------------------------------*/ IF( sub(st->last_good_fx , UNVOICED_TRANSITION) >= 0 ) { tmp16 = add(L_frame,shr(L_frame,1)); FOR( i=0 ; i< tmp16; i++ ) { exc[i] = add(exc[i] , shl(noise[i+(L_FIR_FER2/2)],Q_exc+noise_e));/*Q1*/ move16(); } } ELSE { bufferCopyFx(noise+L_FIR_FER2/2, exc, add(L_frame , shr(L_frame,1)),0/*Q_noise*/, noise_e, Q_exc, 0/*exc_e*/); Copy(exc+L_frame-2*L_subfr, st->old_excFB_fx, 2*L_subfr+shr(L_frame,1)); /* copy old_exc as 16kHz for acelp decoding */ IF ( sub(st->nbLostCmpt, 1) == 0 ) { lerp(exc, st->old_exc_fx, L_EXC_MEM_DEC, add(L_frame, shr(L_frame,1))); } ELSE { Copy(st->old_exc_fx+L_FRAME16k, st->old_exc_fx, L_FRAME16k/2); lerp(exc, st->old_exc_fx+L_FRAME16k/2, L_FRAME16k, L_frame); } st->Q_exc = Q_exc; } /*buf[0;L_FIR_FER2 + L_Frame + L_Frame/2] Q0, noise_e*/ /*buf[OLD_EXC_SIZE_DEC;3/2 L_frame] Q1*/ /* Update Pitch Lag memory */ Copy32( &st->old_pitch_buf_fx[st->nb_subfr], st->old_pitch_buf_fx, st->nb_subfr ); Copy32( pitch_buf, &st->old_pitch_buf_fx[st->nb_subfr], st->nb_subfr ); /*----------------------------------------------------------* * - compute the synthesis speech * *----------------------------------------------------------*/ syn = buf + M; Copy(synth-M, buf, M); new_Q = sub(Q_exc, 3); new_Q = s_max(new_Q, -1); tmp16 = s_min(new_Q, st->prev_Q_syn); st->prev_Q_syn = new_Q; move16(); exp_scale = sub(tmp16, Q_exc-1); Q_syn = tmp16; move16(); Copy_Scale_sig(buf, mem_syn, M, exp_scale); tmp_deemph = shl(tmp_deemph,Q_syn); st->Q_syn = Q_syn; /*buf[OLD_EXC_SIZE_DEC;3/2 L_frame] Q1: exc*/ /*buf[0;M] Q0: mem_syn*/ E_UTIL_synthesis( sub(Q_exc, Q_syn), A_local, &exc[0], &syn[0], add(L_frame, shr(L_frame,1)), mem_syn, 1, M); /*buf[OLD_EXC_SIZE_DEC;3/2 L_frame-1] Q1: exc*/ /*buf[0;M-1] Q0: mem_syn*/ /*buf[M;3/2 L_frame-1] Q-1: syn*/ n = extract_h(L_mult(L_frame,9216/*(float)N_ZERO_MDCT_NS/(float)FRAME_SIZE_NS Q15*/)); /* update ACELP synthesis memory */ mem_syn_r_size_old = shr(L_frame,4); /* replace 1.25/20.0 by shr(4) */ /* copy mem_syn as 16kHz */ mem_syn_r_size_new = shr(L_FRAME16k,4); /* replace 1.25/20.0 by shr(4) */ Copy(syn+L_frame-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM); lerp(st->mem_syn_r+L_SYN_MEM-mem_syn_r_size_old, st->mem_syn_r+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old); Copy(st->mem_syn_r+L_SYN_MEM-M, st->mem_syn2_fx, M); /* Deemphasis and output synth and ZIR */ deemph_fx(syn, st->preemph_fac, add(L_frame,shr(L_frame,1)), &tmp_deemph); bufferCopyFx(syn+L_frame-M-1, st->syn, 1+M, Q_syn, 0, 0, 0); lerp( syn+L_frame-shr(L_frame, 1), st->old_syn_Overl, shr(st->L_frame_fx, 1), shr(L_frame, 1) ); Copy(syn+L_frame-n, st->old_out_fx, sub(L_frame,n)); FOR (i=0; i < W12; i++) { st->old_out_fx[i+n] = round_fx(Mpy_32_16_1(L_mult(w[i].v.re,w[i].v.re),st->old_out_fx[i+n])); } FOR ( ; i < W1; i++) { st->old_out_fx[i+n] = round_fx(Mpy_32_16_1(L_mult(w[W12-1-(i-W12)].v.im,w[W12-1-(i-W12)].v.im),st->old_out_fx[i+n])); } set16_fx(&st->old_out_fx[W1+n], 0, n); st->Q_old_wtda = Q_syn; move16(); /* As long as there is no synth scaling factor introduced, which is given to the outside, there might occur overflows here */ BASOP_SATURATE_WARNING_OFF bufferCopyFx(syn, synth, L_frame, Q_syn, 0, 0, 0); BASOP_SATURATE_WARNING_ON Copy_Scale_sig(syn+L_frame, st->syn_OverlFB, shr(L_frame,1), negate(Q_syn)); /* copy total excitation exc2 as 16kHz for acelp mode1 decoding */ lerp(exc, st->old_exc2_fx, L_EXC_MEM, L_frame); lerp(syn, st->old_syn2_fx, L_EXC_MEM, L_frame); st->bfi_pitch_fx/*Q6*/ = round_fx(L_shl(pitch_buf[st->nb_subfr-1]/*15Q16*/,6/*Q6*/)); move16(); st->bfi_pitch_frame_fx = st->L_frame_fx; move16(); /* create aliasing and windowing need for transition to TCX10/5 */ bufferCopyFx(syn+L_frame, st->syn_Overl_TDACFB, shr(L_frame,1),Q_syn,0,-1,0); FOR (i=0 ; i < W12 ; i++) { buf[i] = mult_r(st->syn_Overl_TDACFB[i] , w[i].v.re); move16(); } FOR ( ; i syn_Overl_TDACFB[i],w[W12-1-(i-W12)].v.im); move16(); } FOR (i=0; isyn_Overl_TDACFB[i] = add(buf[i] , buf[W1-1-i]); move16(); } FOR (i=0; isyn_Overl_TDACFB[W2+i] = add(buf[W2+i] , buf[W1-1-W2-i]); move16(); } FOR (i=0 ; i < W12 ; i++) { st->syn_Overl_TDACFB[i] = mult_r(st->syn_Overl_TDACFB[i],w[i].v.re); move16(); } FOR ( ; i syn_Overl_TDACFB[i] = mult_r(st->syn_Overl_TDACFB[i],w[W12-1-(i-W12)].v.im); move16(); } st->tcx_cfg.tcx_curr_overlap_mode = FULL_OVERLAP; synth[-1] = pre_emph_buf; move16(); /* update memory for low band */ Scale_sig(st->old_syn_Overl, shr(st->L_frame_fx, 1), sub(-1, Q_syn)); lerp( st->syn_OverlFB, st->syn_Overl, shr(st->L_frame_fx, 1), shr(L_frame, 1) ); lerp( st->syn_Overl_TDACFB, st->syn_Overl_TDAC, shr(st->L_frame_fx, 1), shr(L_frame, 1) ); lerp( st->old_out_fx, st->old_out_LB_fx, st->L_frame_fx, L_frame ); st->old_enr_LP = Enr_1_Az_fx(A_local, L_SUBFR); /*Q3*/ return; }