int32_t WebRtcG729fix_Inv_sqrt( /* (o) Q30 : output value (range: 0<=val<1) */ int32_t L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ ) { int16_t exp, i, a, tmp; int32_t L_y; if( L_x <= (int32_t)0) return ( (int32_t)0x3fffffffL); exp = WebRtcSpl_NormW32(L_x); L_x = L_shl(L_x, exp ); /* L_x is normalize */ exp = WebRtcSpl_SubSatW16(30, exp); if( (exp & 1) == 0 ) /* If exponent even -> shift right */ L_x = L_shr(L_x, 1); exp = shr(exp, 1); exp = WebRtcSpl_AddSatW16(exp, 1); L_x = L_shr(L_x, 9); i = extract_h(L_x); /* Extract b25-b31 */ L_x = L_shr(L_x, 1); a = extract_l(L_x); /* Extract b10-b24 */ a = a & (int16_t)0x7fff; i = WebRtcSpl_SubSatW16(i, 16); L_y = L_deposit_h(WebRtcG729fix_tabsqr[i]); /* tabsqr[i] << 16 */ tmp = WebRtcSpl_SubSatW16(WebRtcG729fix_tabsqr[i], WebRtcG729fix_tabsqr[i+1]); /* tabsqr[i] - tabsqr[i+1]) */ L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */ L_y = L_shr(L_y, exp); /* denormalization */ return(L_y); }
void WebRtcG729fix_Lsf_lsp2( int16_t lsf[], /* (i) Q13 : lsf[m] (range: 0.0<=val<PI) */ int16_t lsp[], /* (o) Q15 : lsp[m] (range: -1<=val<1) */ int16_t m /* (i) : LPC order */ ) { int16_t i, ind; int16_t offset; /* in Q8 */ int16_t freq; /* normalized frequency in Q15 */ int32_t L_tmp; for(i=0; i<m; i++) { /* freq = abs_s(freq);*/ freq = mult(lsf[i], 20861); /* 20861: 1.0/(2.0*PI) in Q17 */ ind = shr(freq, 8); /* ind = b8-b15 of freq */ offset = freq & (int16_t)0x00ff; /* offset = b0-b7 of freq */ if (ind > 63){ ind = 63; /* 0 <= ind <= 63 */ } /* lsp[i] = table2[ind]+ (slope_cos[ind]*offset >> 12) */ L_tmp = L_mult(WebRtcG729fix_slope_cos[ind], offset); /* L_tmp in Q28 */ lsp[i] = WebRtcSpl_AddSatW16(WebRtcG729fix_table2[ind], extract_l(L_shr(L_tmp, 13))); } }
void WebRtcG729fix_Lsp_lsf2( int16_t lsp[], /* (i) Q15 : lsp[m] (range: -1<=val<1) */ int16_t lsf[], /* (o) Q13 : lsf[m] (range: 0.0<=val<PI) */ int16_t m /* (i) : LPC order */ ) { int16_t i, ind; int16_t offset; /* in Q15 */ int16_t freq; /* normalized frequency in Q16 */ int32_t L_tmp; ind = 63; /* begin at end of table2 -1 */ for(i= m-(int16_t)1; i >= 0; i--) { /* find value in table2 that is just greater than lsp[i] */ while( WebRtcSpl_SubSatW16(WebRtcG729fix_table2[ind], lsp[i]) < 0 ) { ind = WebRtcSpl_SubSatW16(ind,1); if ( ind <= 0 ) break; } offset = WebRtcSpl_SubSatW16(lsp[i], WebRtcG729fix_table2[ind]); /* acos(lsp[i])= ind*512 + (slope_acos[ind]*offset >> 11) */ L_tmp = L_mult( WebRtcG729fix_slope_acos[ind], offset ); /* L_tmp in Q28 */ freq = WebRtcSpl_AddSatW16(shl(ind, 9), extract_l(L_shr(L_tmp, 12))); lsf[i] = mult(freq, 25736); /* 25736: 2.0*PI in Q12 */ } }
void WebRtcG729fix_Lsp_lsf( int16_t lsp[], /* (i) Q15 : lsp[m] (range: -1<=val<1) */ int16_t lsf[], /* (o) Q15 : lsf[m] normalized (range: 0.0<=val<=0.5) */ int16_t m /* (i) : LPC order */ ) { int16_t i, ind, tmp; int32_t L_tmp; ind = 63; /* begin at end of table -1 */ for(i= m-(int16_t)1; i >= 0; i--) { /* find value in table that is just greater than lsp[i] */ while( WebRtcSpl_SubSatW16(WebRtcG729fix_table[ind], lsp[i]) < 0 ) { ind = WebRtcSpl_SubSatW16(ind,1); } /* acos(lsp[i])= ind*256 + ( ( lsp[i]-table[ind] ) * slope[ind] )/4096 */ L_tmp = L_mult(WebRtcSpl_SubSatW16(lsp[i], WebRtcG729fix_table[ind]), WebRtcG729fix_slope[ind]); tmp = L_round(L_shl(L_tmp, 3)); /*(lsp[i]-table[ind])*slope[ind])>>12*/ lsf[i] = WebRtcSpl_AddSatW16(tmp, shl(ind, 8)); } }
static int16_t Sqrt(int32_t Num) { int16_t i; int16_t Rez = (int16_t)0; int16_t Exp = (int16_t)0x4000; int32_t Acc, L_temp; for (i = 0; i < 14 ; i++) { Acc = L_mult(WebRtcSpl_AddSatW16(Rez, Exp), WebRtcSpl_AddSatW16(Rez, Exp)); L_temp = WebRtcSpl_SubSatW32(Num, Acc); if (L_temp >= 0L) Rez = WebRtcSpl_AddSatW16(Rez, Exp); Exp = shr(Exp, (int16_t)1); } return Rez; }
void WebRtcG729fix_Int_qlpc( int16_t lsp_old[], /* input : LSP vector of past frame */ int16_t lsp_new[], /* input : LSP vector of present frame */ int16_t Az[] /* output: interpolated Az() for the 2 subframes */ ) { int16_t i; int16_t lsp[M]; /* lsp[i] = lsp_new[i] * 0.5 + lsp_old[i] * 0.5 */ for (i = 0; i < M; i++) { lsp[i] = WebRtcSpl_AddSatW16(shr(lsp_new[i], 1), shr(lsp_old[i], 1)); } WebRtcG729fix_Lsp_Az(lsp, Az); /* Subframe 1 */ WebRtcG729fix_Lsp_Az(lsp_new, &Az[MP1]); /* Subframe 2 */ }
void WebRtcG729fix_Lsf_lsp( int16_t lsf[], /* (i) Q15 : lsf[m] normalized (range: 0.0<=val<=0.5) */ int16_t lsp[], /* (o) Q15 : lsp[m] (range: -1<=val<1) */ int16_t m /* (i) : LPC order */ ) { int16_t i, ind, offset; int32_t L_tmp; for(i=0; i<m; i++) { ind = shr(lsf[i], 8); /* ind = b8-b15 of lsf[i] */ offset = lsf[i] & (int16_t)0x00ff; /* offset = b0-b7 of lsf[i] */ /* lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256 */ L_tmp = L_mult(WebRtcSpl_SubSatW16(WebRtcG729fix_table[ind+1], WebRtcG729fix_table[ind]), offset); lsp[i] = WebRtcSpl_AddSatW16(WebRtcG729fix_table[ind], extract_l(L_shr(L_tmp, 9))); } }
int16_t WebRtcIsacfix_DecodeImpl(int16_t *signal_out16, ISACFIX_DecInst_t *ISACdec_obj, int16_t *current_framesamples) { int k; int err; int16_t BWno; int16_t len = 0; int16_t model; int16_t Vector_Word16_1[FRAMESAMPLES/2]; int16_t Vector_Word16_2[FRAMESAMPLES/2]; int32_t Vector_Word32_1[FRAMESAMPLES/2]; int32_t Vector_Word32_2[FRAMESAMPLES/2]; int16_t lofilt_coefQ15[ORDERLO*SUBFRAMES]; //refl. coeffs int16_t hifilt_coefQ15[ORDERHI*SUBFRAMES]; //refl. coeffs int32_t gain_lo_hiQ17[2*SUBFRAMES]; int16_t PitchLags_Q7[PITCH_SUBFRAMES]; int16_t PitchGains_Q12[PITCH_SUBFRAMES]; int16_t AvgPitchGain_Q12; int16_t tmp_1, tmp_2; int32_t tmp32a, tmp32b; int16_t gainQ13; int16_t frame_nb; /* counter */ int16_t frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */ int16_t processed_samples; /* PLC */ int16_t overlapWin[ 240 ]; (ISACdec_obj->bitstr_obj).W_upper = 0xFFFFFFFF; (ISACdec_obj->bitstr_obj).streamval = 0; (ISACdec_obj->bitstr_obj).stream_index = 0; (ISACdec_obj->bitstr_obj).full = 1; /* decode framelength and BW estimation - not used, only for stream pointer*/ err = WebRtcIsacfix_DecodeFrameLen(&ISACdec_obj->bitstr_obj, current_framesamples); if (err<0) // error check return err; frame_mode = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, MAX_FRAMESAMPLES); /* 0, or 1 */ processed_samples = (int16_t)WEBRTC_SPL_DIV(*current_framesamples, frame_mode+1); /* either 320 (20ms) or 480 (30, 60 ms) */ err = WebRtcIsacfix_DecodeSendBandwidth(&ISACdec_obj->bitstr_obj, &BWno); if (err<0) // error check return err; /* one loop if it's one frame (20 or 30ms), 2 loops if 2 frames bundled together (60ms) */ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) { /* decode & dequantize pitch parameters */ err = WebRtcIsacfix_DecodePitchGain(&(ISACdec_obj->bitstr_obj), PitchGains_Q12); if (err<0) // error check return err; err = WebRtcIsacfix_DecodePitchLag(&ISACdec_obj->bitstr_obj, PitchGains_Q12, PitchLags_Q7); if (err<0) // error check return err; AvgPitchGain_Q12 = (int16_t)(((int32_t)PitchGains_Q12[0] + PitchGains_Q12[1] + PitchGains_Q12[2] + PitchGains_Q12[3])>>2); /* decode & dequantize FiltCoef */ err = WebRtcIsacfix_DecodeLpc(gain_lo_hiQ17, lofilt_coefQ15, hifilt_coefQ15, &ISACdec_obj->bitstr_obj, &model); if (err<0) // error check return err; /* decode & dequantize spectrum */ len = WebRtcIsacfix_DecodeSpec(&ISACdec_obj->bitstr_obj, Vector_Word16_1, Vector_Word16_2, AvgPitchGain_Q12); if (len < 0) // error check return len; // Why does this need Q16 in and out? /JS WebRtcIsacfix_Spec2Time(Vector_Word16_1, Vector_Word16_2, Vector_Word32_1, Vector_Word32_2); for (k=0; k<FRAMESAMPLES/2; k++) { Vector_Word16_1[k] = (int16_t)WEBRTC_SPL_RSHIFT_W32(Vector_Word32_1[k]+64, 7); //Q16 -> Q9 } /* ---- If this is recovery frame ---- */ if( (ISACdec_obj->plcstr_obj).used == PLC_WAS_USED ) { (ISACdec_obj->plcstr_obj).used = PLC_NOT_USED; if( (ISACdec_obj->plcstr_obj).B < 1000 ) { (ISACdec_obj->plcstr_obj).decayCoeffPriodic = 4000; } ISACdec_obj->plcstr_obj.decayCoeffPriodic = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */ ISACdec_obj->plcstr_obj.decayCoeffNoise = WEBRTC_SPL_WORD16_MAX; /* DECAY_RATE is in Q15 */ ISACdec_obj->plcstr_obj.pitchCycles = 0; PitchGains_Q12[0] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(PitchGains_Q12[0], 700, 10 ); /* ---- Add-overlap ---- */ WebRtcSpl_GetHanningWindow( overlapWin, RECOVERY_OVERLAP ); for( k = 0; k < RECOVERY_OVERLAP; k++ ) Vector_Word16_1[k] = WebRtcSpl_AddSatW16( (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( (ISACdec_obj->plcstr_obj).overlapLP[k], overlapWin[RECOVERY_OVERLAP - k - 1], 14), (int16_t)WEBRTC_SPL_MUL_16_16_RSFT( Vector_Word16_1[k], overlapWin[k], 14) ); } /* --- Store side info --- */ if( frame_nb == frame_mode ) { /* --- LPC info */ WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).lofilt_coefQ15, &lofilt_coefQ15[(SUBFRAMES-1)*ORDERLO], ORDERLO ); WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).hifilt_coefQ15, &hifilt_coefQ15[(SUBFRAMES-1)*ORDERHI], ORDERHI ); (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[0] = gain_lo_hiQ17[(SUBFRAMES-1) * 2]; (ISACdec_obj->plcstr_obj).gain_lo_hiQ17[1] = gain_lo_hiQ17[(SUBFRAMES-1) * 2 + 1]; /* --- LTP info */ (ISACdec_obj->plcstr_obj).AvgPitchGain_Q12 = PitchGains_Q12[3]; (ISACdec_obj->plcstr_obj).lastPitchGain_Q12 = PitchGains_Q12[3]; (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 = PitchLags_Q7[3]; if( PitchLags_Q7[3] < 3000 ) (ISACdec_obj->plcstr_obj).lastPitchLag_Q7 += PitchLags_Q7[3]; WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvIn, Vector_Word16_1, FRAMESAMPLES/2 ); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* inverse pitch filter */ WebRtcIsacfix_PitchFilter(Vector_Word16_1, Vector_Word16_2, &ISACdec_obj->pitchfiltstr_obj, PitchLags_Q7, PitchGains_Q12, 4); if( frame_nb == frame_mode ) { WEBRTC_SPL_MEMCPY_W16( (ISACdec_obj->plcstr_obj).prevPitchInvOut, &(Vector_Word16_2[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10)]), PITCH_MAX_LAG ); } /* reduce gain to compensate for pitch enhancer */ /* gain = 1.0f - 0.45f * AvgPitchGain; */ tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(AvgPitchGain_Q12, 29, 0); // Q18 tmp32b = 262144 - tmp32a; // Q18 gainQ13 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q13 for (k = 0; k < FRAMESAMPLES/2; k++) { Vector_Word32_1[k] = (int32_t) WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(Vector_Word16_2[k], gainQ13), 3); // Q25 } /* perceptual post-filtering (using normalized lattice filter) */ WebRtcIsacfix_NormLatticeFilterAr(ORDERLO, (ISACdec_obj->maskfiltstr_obj).PostStateLoGQ0, Vector_Word32_1, lofilt_coefQ15, gain_lo_hiQ17, 0, Vector_Word16_1); /* --- Store Highpass Residual --- */ for (k = 0; k < FRAMESAMPLES/2; k++) Vector_Word32_1[k] = WEBRTC_SPL_LSHIFT_W32(Vector_Word32_2[k], 9); // Q16 -> Q25 for( k = 0; k < PITCH_MAX_LAG + 10; k++ ) (ISACdec_obj->plcstr_obj).prevHP[k] = Vector_Word32_1[FRAMESAMPLES/2 - (PITCH_MAX_LAG + 10) + k]; WebRtcIsacfix_NormLatticeFilterAr(ORDERHI, (ISACdec_obj->maskfiltstr_obj).PostStateHiGQ0, Vector_Word32_1, hifilt_coefQ15, gain_lo_hiQ17, 1, Vector_Word16_2); /* recombine the 2 bands */ /* Form the polyphase signals, and compensate for DC offset */ for (k=0;k<FRAMESAMPLES/2;k++) { tmp_1 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]+Vector_Word16_2[k] + 1)); /* Construct a new upper channel signal*/ tmp_2 = (int16_t)WebRtcSpl_SatW32ToW16(((int32_t)Vector_Word16_1[k]-Vector_Word16_2[k])); /* Construct a new lower channel signal*/ Vector_Word16_1[k] = tmp_1; Vector_Word16_2[k] = tmp_2; } WebRtcIsacfix_FilterAndCombine1(Vector_Word16_1, Vector_Word16_2, signal_out16 + frame_nb * processed_samples, &ISACdec_obj->postfiltbankstr_obj); } return len; }
/*---------------------------------------------------------------------------* * Function Dec_gain * * ~~~~~~~~~~~~~~~~~~ * * Decode the pitch and codebook gains * * * *---------------------------------------------------------------------------* * input arguments: * * * * index :Quantization index * * code[] :Innovative code vector * * L_subfr :Subframe size * * bfi :Bad frame indicator * * * * output arguments: * * * * gain_pit :Quantized pitch gain * * gain_cod :Quantized codebook gain * * * *---------------------------------------------------------------------------*/ void WebRtcG729fix_Dec_gain( Decod_ld8a_state *st, int16_t index, /* (i) :Index of quantization. */ int16_t code[], /* (i) Q13 :Innovative vector. */ int16_t L_subfr, /* (i) :Subframe length. */ int16_t bfi, /* (i) :Bad frame indicator */ int16_t *gain_pit, /* (o) Q14 :Pitch gain. */ int16_t *gain_cod /* (o) Q1 :Code gain. */ ) { int16_t index1, index2, tmp; int16_t gcode0, exp_gcode0; int32_t L_gbk12, L_acc, L_accb; /*-------------- Case of erasure. ---------------*/ if(bfi != 0){ *gain_pit = mult( *gain_pit, 29491 ); /* *0.9 in Q15 */ if (*gain_pit > 29491) *gain_pit = 29491; *gain_cod = mult( *gain_cod, 32111 ); /* *0.98 in Q15 */ /*----------------------------------------------* * update table of past quantized energies * * (frame erasure) * *----------------------------------------------*/ WebRtcG729fix_Gain_update_erasure(st->past_qua_en); return; } /*-------------- Decode pitch gain ---------------*/ index1 = WebRtcG729fix_imap1[ shr(index,NCODE2_B) ] ; index2 = WebRtcG729fix_imap2[ index & (NCODE2-1) ] ; *gain_pit = WebRtcSpl_AddSatW16( WebRtcG729fix_gbk1[index1][0], WebRtcG729fix_gbk2[index2][0] ); /*-------------- Decode codebook gain ---------------*/ /*---------------------------------------------------* *- energy due to innovation -* *- predicted energy -* *- predicted codebook gain => gcode0[exp_gcode0] -* *---------------------------------------------------*/ WebRtcG729fix_Gain_predict(st->past_qua_en, code, L_subfr, &gcode0, &exp_gcode0 ); /*-----------------------------------------------------------------* * *gain_code = (gbk1[indice1][1]+gbk2[indice2][1]) * gcode0; * *-----------------------------------------------------------------*/ L_acc = L_deposit_l( WebRtcG729fix_gbk1[index1][1] ); L_accb = L_deposit_l( WebRtcG729fix_gbk2[index2][1] ); L_gbk12 = WebRtcSpl_AddSatW32( L_acc, L_accb ); /* Q13 */ tmp = extract_l( L_shr( L_gbk12,1 ) ); /* Q12 */ L_acc = L_mult(tmp, gcode0); /* Q[exp_gcode0+12+1] */ L_acc = L_shl(L_acc, WebRtcSpl_AddSatW16( negate(exp_gcode0),(-12-1+1+16) )); *gain_cod = extract_h( L_acc ); /* Q1 */ /*----------------------------------------------* * update table of past quantized energies * *----------------------------------------------*/ WebRtcG729fix_Gain_update(st->past_qua_en, L_gbk12 ); return; }
void WebRtcG729fix_Decod_ld8a( Decod_ld8a_state *st, int16_t parm[], /* (i) : vector of synthesis parameters parm[0] = bad frame indicator (bfi) */ int16_t synth[], /* (o) : synthesis speech */ int16_t A_t[], /* (o) : decoded LP filter in 2 subframes */ int16_t *T2, /* (o) : decoded pitch lag in 2 subframes */ int16_t *Vad, /* (o) : frame type */ int16_t bad_lsf /* (i) : bad LSF indicator */ ) { int16_t *Az; /* Pointer on A_t */ int16_t lsp_new[M]; /* LSPs */ int16_t code[L_SUBFR]; /* ACELP codevector */ /* Scalars */ int16_t i, j, i_subfr; int16_t T0, T0_frac, index; int16_t bfi; int32_t L_temp; int16_t bad_pitch; /* bad pitch indicator */ /* for G.729B */ int16_t ftyp; int16_t lsfq_mem[MA_NP][M]; int Overflow; /* Test bad frame indicator (bfi) */ bfi = *parm++; /* for G.729B */ ftyp = *parm; if(bfi == 1) { if(st->past_ftyp == 1) { ftyp = 1; parm[4] = 1; /* G.729 maintenance */ } else ftyp = 0; *parm = ftyp; /* modification introduced in version V1.3 */ } *Vad = ftyp; /* Processing non active frames (SID & not transmitted) */ if(ftyp != 1) { WebRtcG729fix_Get_decfreq_prev(st, lsfq_mem); WebRtcG729fix_Dec_cng(st, st->past_ftyp, st->sid_sav, st->sh_sid_sav, parm, st->exc, st->lsp_old, A_t, &st->seed, lsfq_mem); WebRtcG729fix_Update_decfreq_prev(st, lsfq_mem); Az = A_t; for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { Overflow = WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 0); if(Overflow != 0) { /* In case of overflow in the synthesis */ /* -> Scale down vector exc[] and redo synthesis */ for (i = 0; i < PIT_MAX + L_INTERPOL + L_FRAME; i++) st->old_exc[i] = shr(st->old_exc[i], 2); WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 1); } else WEBRTC_SPL_MEMCPY_W16(st->mem_syn, &synth[i_subfr+L_SUBFR-M], M); Az += MP1; *T2++ = st->old_T0; } st->sharp = SHARPMIN; } /* Processing active frame */ else { st->seed = INIT_SEED; parm++; /* Decode the LSPs */ WebRtcG729fix_D_lsp(st, parm, lsp_new, WebRtcSpl_AddSatW16(bfi, bad_lsf)); parm += 2; /* Note: "bad_lsf" is introduce in case the standard is used with channel protection. */ /* Interpolation of LPC for the 2 subframes */ WebRtcG729fix_Int_qlpc(st->lsp_old, lsp_new, A_t); /* update the LSFs for the next frame */ WEBRTC_SPL_MEMCPY_W16(st->lsp_old, lsp_new, M); /*------------------------------------------------------------------------* * Loop for every subframe in the analysis frame * *------------------------------------------------------------------------* * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR * * times * * - decode the pitch delay * * - decode algebraic code * * - decode pitch and codebook gains * * - find the excitation and compute synthesis speech * *------------------------------------------------------------------------*/ Az = A_t; /* pointer to interpolated LPC parameters */ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { index = *parm++; /* pitch index */ if(i_subfr == 0) { i = *parm++; /* get parity check result */ bad_pitch = WebRtcSpl_AddSatW16(bfi, i); if( bad_pitch == 0) { WebRtcG729fix_Dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, &T0, &T0_frac); st->old_T0 = T0; } else /* Bad frame, or parity error */ { T0 = st->old_T0; T0_frac = 0; st->old_T0 = WebRtcSpl_AddSatW16(st->old_T0, 1); if(st->old_T0 > PIT_MAX) { st->old_T0 = PIT_MAX; } } } else /* second subframe */ { if(bfi == 0) { WebRtcG729fix_Dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, &T0, &T0_frac); st->old_T0 = T0; } else { T0 = st->old_T0; T0_frac = 0; st->old_T0 = WebRtcSpl_AddSatW16(st->old_T0, 1); if (st->old_T0 > PIT_MAX) { st->old_T0 = PIT_MAX; } } } *T2++ = T0; /*-------------------------------------------------* * - Find the adaptive codebook vector. * *-------------------------------------------------*/ WebRtcG729fix_Pred_lt_3(&st->exc[i_subfr], T0, T0_frac, L_SUBFR); /*-------------------------------------------------------* * - Decode innovative codebook. * * - Add the fixed-gain pitch contribution to code[]. * *-------------------------------------------------------*/ if(bfi != 0) /* Bad frame */ { parm[0] = WebRtcG729fix_Random(&st->seed_fer) & (int16_t)0x1fff; /* 13 bits random */ parm[1] = WebRtcG729fix_Random(&st->seed_fer) & (int16_t)0x000f; /* 4 bits random */ } WebRtcG729fix_Decod_ACELP(parm[1], parm[0], code); parm +=2; j = shl(st->sharp, 1); /* From Q14 to Q15 */ if(T0 < L_SUBFR) { for (i = T0; i < L_SUBFR; i++) { code[i] = WebRtcSpl_AddSatW16(code[i], mult(code[i-T0], j)); } } /*-------------------------------------------------* * - Decode pitch and codebook gains. * *-------------------------------------------------*/ index = *parm++; /* index of energy VQ */ WebRtcG729fix_Dec_gain(st, index, code, L_SUBFR, bfi, &st->gain_pitch, &st->gain_code); /*-------------------------------------------------------------* * - Update pitch sharpening "sharp" with quantized gain_pitch * *-------------------------------------------------------------*/ st->sharp = st->gain_pitch; if (st->sharp > SHARPMAX) { st->sharp = SHARPMAX; } else if (st->sharp < SHARPMIN) { st->sharp = SHARPMIN; } /*-------------------------------------------------------* * - Find the total excitation. * * - Find synthesis speech corresponding to exc[]. * *-------------------------------------------------------*/ for (i = 0; i < L_SUBFR; i++) { /* exc[i] = gain_pitch*exc[i] + gain_code*code[i]; */ /* exc[i] in Q0 gain_pitch in Q14 */ /* code[i] in Q13 gain_codeode in Q1 */ L_temp = L_mult(st->exc[i+i_subfr], st->gain_pitch); L_temp = L_mac(L_temp, code[i], st->gain_code); L_temp = L_shl(L_temp, 1); st->exc[i+i_subfr] = L_round(L_temp); } Overflow = WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 0); if(Overflow != 0) { /* In case of overflow in the synthesis */ /* -> Scale down vector exc[] and redo synthesis */ for (i = 0; i < PIT_MAX + L_INTERPOL + L_FRAME; i++) st->old_exc[i] = shr(st->old_exc[i], 2); WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 1); } else WEBRTC_SPL_MEMCPY_W16(st->mem_syn, &synth[i_subfr+L_SUBFR-M], M); Az += MP1; /* interpolated LPC parameters for next subframe */ } } /*------------* * For G729b *-----------*/ if(bfi == 0) { L_temp = 0L; for (i = 0; i < L_FRAME; i++) { L_temp = L_mac(L_temp, st->exc[i], st->exc[i]); } /* may overflow => last level of SID quantizer */ st->sh_sid_sav = WebRtcSpl_NormW32(L_temp); st->sid_sav = L_round(L_shl(L_temp, st->sh_sid_sav)); st->sh_sid_sav = WebRtcSpl_SubSatW16(16, st->sh_sid_sav); } /*--------------------------------------------------* * Update signal for next frame. * * -> shift to the left by L_FRAME exc[] * *--------------------------------------------------*/ Copy(&st->old_exc[L_FRAME], &st->old_exc[0], PIT_MAX+L_INTERPOL); /* for G729b */ st->past_ftyp = ftyp; return; }
void WebRtcG729fix_Dec_lag3( int16_t index, /* input : received pitch index */ int16_t pit_min, /* input : minimum pitch lag */ int16_t pit_max, /* input : maximum pitch lag */ int16_t i_subfr, /* input : subframe flag */ int16_t *T0, /* output: integer part of pitch lag */ int16_t *T0_frac /* output: fractional part of pitch lag */ ) { int16_t i; int16_t T0_min, T0_max; if (i_subfr == 0) /* if 1st subframe */ { if (index < 197) { /* *T0 = (index+2)/3 + 19 */ *T0 = WebRtcSpl_AddSatW16(mult(WebRtcSpl_AddSatW16(index, 2), 10923), 19); /* *T0_frac = index - *T0*3 + 58 */ i = WebRtcSpl_AddSatW16(WebRtcSpl_AddSatW16(*T0, *T0), *T0); *T0_frac = WebRtcSpl_AddSatW16(WebRtcSpl_SubSatW16(index, i), 58); } else { *T0 = WebRtcSpl_SubSatW16(index, 112); *T0_frac = 0; } } else /* second subframe */ { /* find T0_min and T0_max for 2nd subframe */ T0_min = WebRtcSpl_SubSatW16(*T0, 5); if (T0_min < pit_min) { T0_min = pit_min; } T0_max = WebRtcSpl_AddSatW16(T0_min, 9); if (T0_max > pit_max) { T0_max = pit_max; T0_min = WebRtcSpl_SubSatW16(T0_max, 9); } /* i = (index+2)/3 - 1 */ /* *T0 = i + t0_min; */ i = WebRtcSpl_SubSatW16(mult(WebRtcSpl_AddSatW16(index, 2), 10923), 1); *T0 = WebRtcSpl_AddSatW16(i, T0_min); /* t0_frac = index - 2 - i*3; */ i = WebRtcSpl_AddSatW16(WebRtcSpl_AddSatW16(i, i), i); *T0_frac = WebRtcSpl_SubSatW16(WebRtcSpl_SubSatW16(index, 2), i); } return; }
/*-----------------------------------------------------------* * procedure Calc_exc_rand * * ~~~~~~~~~~~~~ * * Computes comfort noise excitation * * for SID and not-transmitted frames * *-----------------------------------------------------------*/ void WebRtcG729fix_Calc_exc_rand( int32_t L_exc_err[], int16_t cur_gain, /* (i) : target sample gain */ int16_t *exc, /* (i/o) : excitation array */ int16_t *seed, /* (i) : current Vad decision */ int flag_cod /* (i) : encoder/decoder flag */ ) { int16_t i, j, i_subfr; int16_t temp1, temp2; int16_t pos[4]; int16_t sign[4]; int16_t t0, frac; int16_t *cur_exc; int16_t g, Gp, Gp2; int16_t excg[L_SUBFR], excs[L_SUBFR]; int32_t L_acc, L_ener, L_k; int16_t max, hi, lo, inter_exc; int16_t sh; int16_t x1, x2; if (cur_gain == 0) { WebRtcSpl_ZerosArrayW16(exc, L_FRAME); Gp = 0; t0 = WebRtcSpl_AddSatW16(L_SUBFR,1); for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { if (flag_cod != FLAG_DEC) WebRtcG729fix_update_exc_err(L_exc_err, Gp, t0); } return; } /* Loop on subframes */ cur_exc = exc; for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) { /* generate random adaptive codebook & fixed codebook parameters */ /*****************************************************************/ temp1 = WebRtcG729fix_Random(seed); frac = WebRtcSpl_SubSatW16((temp1 & (int16_t)0x0003), 1); if(frac == 2) frac = 0; temp1 = shr(temp1, 2); t0 = WebRtcSpl_AddSatW16((temp1 & (int16_t)0x003F), 40); temp1 = shr(temp1, 6); temp2 = temp1 & (int16_t)0x0007; pos[0] = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2); /* 5 * temp2 */ temp1 = shr(temp1, 3); sign[0] = temp1 & (int16_t)0x0001; temp1 = shr(temp1, 1); temp2 = temp1 & (int16_t)0x0007; temp2 = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2); pos[1] = WebRtcSpl_AddSatW16(temp2, 1); /* 5 * x + 1 */ temp1 = shr(temp1, 3); sign[1] = temp1 & (int16_t)0x0001; temp1 = WebRtcG729fix_Random(seed); temp2 = temp1 & (int16_t)0x0007; temp2 = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2); pos[2] = WebRtcSpl_AddSatW16(temp2, 2); /* 5 * x + 2 */ temp1 = shr(temp1, 3); sign[2] = temp1 & (int16_t)0x0001; temp1 = shr(temp1, 1); temp2 = temp1 & (int16_t)0x000F; pos[3] = WebRtcSpl_AddSatW16((temp2 & (int16_t)1), 3); /* j+3*/ temp2 = (shr(temp2, 1)) & (int16_t)7; temp2 = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2); /* 5i */ pos[3] = WebRtcSpl_AddSatW16(pos[3], temp2); temp1 = shr(temp1, 4); sign[3] = temp1 & (int16_t)0x0001; Gp = WebRtcG729fix_Random(seed) & (int16_t)0x1FFF; /* < 0.5 Q14 */ Gp2 = shl(Gp, 1); /* Q15 */ /* Generate gaussian excitation */ /********************************/ L_acc = 0L; for(i=0; i<L_SUBFR; i++) { temp1 = Gauss(seed); L_acc = L_mac(L_acc, temp1, temp1); excg[i] = temp1; } /* Compute fact = alpha x cur_gain * sqrt(L_SUBFR / Eg) with Eg = SUM(i=0->39) excg[i]^2 and alpha = 0.5 alpha x sqrt(L_SUBFR)/2 = 1 + FRAC1 */ L_acc = WebRtcG729fix_Inv_sqrt(L_shr(L_acc,1)); /* Q30 */ WebRtcG729fix_L_Extract(L_acc, &hi, &lo); /* cur_gain = cur_gainR << 3 */ temp1 = mult_r(cur_gain, FRAC1); temp1 = WebRtcSpl_AddSatW16(cur_gain, temp1); /* <=> alpha x cur_gainR x 2^2 x sqrt(L_SUBFR) */ L_acc = WebRtcG729fix_Mpy_32_16(hi, lo, temp1); /* fact << 17 */ sh = WebRtcSpl_NormW32(L_acc); temp1 = extract_h(L_shl(L_acc, sh)); /* fact << (sh+1) */ sh = WebRtcSpl_SubSatW16(sh, 14); for (i = 0; i < L_SUBFR; i++) { temp2 = mult_r(excg[i], temp1); temp2 = shr_r(temp2, sh); /* shl if sh < 0 */ excg[i] = temp2; } /* generate random adaptive excitation */ /****************************************/ WebRtcG729fix_Pred_lt_3(cur_exc, t0, frac, L_SUBFR); /* compute adaptive + gaussian exc -> cur_exc */ /**********************************************/ max = 0; for(i = 0; i < L_SUBFR; i++) { temp1 = mult_r(cur_exc[i], Gp2); temp1 = WebRtcSpl_AddSatW16(temp1, excg[i]); /* may overflow */ cur_exc[i] = temp1; temp1 = abs_s(temp1); if (temp1 > max) max = temp1; } /* rescale cur_exc -> excs */ if (max == 0) sh = 0; else { sh = WebRtcSpl_SubSatW16(3, WebRtcSpl_NormW16(max)); if (sh <= 0) sh = 0; } for (i = 0; i < L_SUBFR; i++) { excs[i] = shr(cur_exc[i], sh); } /* Compute fixed code gain */ /***************************/ /**********************************************************/ /*** Solve EQ(X) = 4 X**2 + 2 b X + c */ /**********************************************************/ L_ener = 0L; for (i = 0; i < L_SUBFR; i++) { L_ener = L_mac(L_ener, excs[i], excs[i]); } /* ener x 2^(-2sh + 1) */ /* inter_exc = b >> sh */ inter_exc = 0; for (i = 0; i < 4; i++) { j = pos[i]; if (sign[i] == 0) { inter_exc = WebRtcSpl_SubSatW16(inter_exc, excs[j]); } else { inter_exc = WebRtcSpl_AddSatW16(inter_exc, excs[j]); } } /* Compute k = cur_gainR x cur_gainR x L_SUBFR */ L_acc = L_mult(cur_gain, L_SUBFR); L_acc = L_shr(L_acc, 6); temp1 = extract_l(L_acc); /* cur_gainR x L_SUBFR x 2^(-2) */ L_k = L_mult(cur_gain, temp1); /* k << 2 */ temp1 = WebRtcSpl_AddSatW16(1, shl(sh,1)); L_acc = L_shr(L_k, temp1); /* k x 2^(-2sh+1) */ /* Compute delta = b^2 - 4 c */ L_acc = WebRtcSpl_SubSatW32(L_acc, L_ener); /* - 4 c x 2^(-2sh-1) */ inter_exc = shr(inter_exc, 1); L_acc = L_mac(L_acc, inter_exc, inter_exc); /* 2^(-2sh-1) */ sh = WebRtcSpl_AddSatW16(sh, 1); /* inter_exc = b x 2^(-sh) */ /* L_acc = delta x 2^(-2sh+1) */ if (L_acc < 0) { /* adaptive excitation = 0 */ WEBRTC_SPL_MEMCPY_W16(cur_exc, excg, L_SUBFR); temp1 = abs_s(excg[(int)pos[0]]) | abs_s(excg[(int)pos[1]]); temp2 = abs_s(excg[(int)pos[2]]) | abs_s(excg[(int)pos[3]]); temp1 = temp1 | temp2; sh = ((temp1 & (int16_t)0x4000) == 0) ? (int16_t)1 : (int16_t)2; inter_exc = 0; for(i=0; i<4; i++) { temp1 = shr(excg[(int)pos[i]], sh); if(sign[i] == 0) { inter_exc = WebRtcSpl_SubSatW16(inter_exc, temp1); } else { inter_exc = WebRtcSpl_AddSatW16(inter_exc, temp1); } } /* inter_exc = b >> sh */ WebRtcG729fix_L_Extract(L_k, &hi, &lo); L_acc = WebRtcG729fix_Mpy_32_16(hi, lo, K0); /* k x (1- alpha^2) << 2 */ temp1 = WebRtcSpl_SubSatW16(shl(sh, 1), 1); /* temp1 > 0 */ L_acc = L_shr(L_acc, temp1); /* 4k x (1 - alpha^2) << (-2sh+1) */ L_acc = L_mac(L_acc, inter_exc, inter_exc); /* delta << (-2sh+1) */ Gp = 0; } temp2 = Sqrt(L_acc); /* >> sh */ x1 = WebRtcSpl_SubSatW16(temp2, inter_exc); x2 = negate(WebRtcSpl_AddSatW16(inter_exc, temp2)); /* x 2^(-sh+2) */ if(abs_s(x2) < abs_s(x1)) x1 = x2; temp1 = WebRtcSpl_SubSatW16(2, sh); g = shr_r(x1, temp1); /* shl if temp1 < 0 */ if (g >= 0) { if (g > G_MAX) g = G_MAX; } else { if (WebRtcSpl_AddSatW16(g, G_MAX) < 0) g = negate(G_MAX); } /* Update cur_exc with ACELP excitation */ for (i = 0; i < 4; i++) { j = pos[i]; if (sign[i] != 0) { cur_exc[j] = WebRtcSpl_AddSatW16(cur_exc[j], g); } else { cur_exc[j] = WebRtcSpl_SubSatW16(cur_exc[j], g); } } if (flag_cod != FLAG_DEC) WebRtcG729fix_update_exc_err(L_exc_err, Gp, t0); cur_exc += L_SUBFR; } /* end of loop on subframes */ return; }