diff --git a/lib_com/fd_cng_com_fx.c b/lib_com/fd_cng_com_fx.c index 9e0f2e375bbc4324048bd20ac29d67c699b1525f..c8387c40a11b530f646363fa1ce91b461ad8ee3c 100644 --- a/lib_com/fd_cng_com_fx.c +++ b/lib_com/fd_cng_com_fx.c @@ -2511,7 +2511,7 @@ void SynthesisSTFT( { FOR( i = 0; i < len; i++ ) { - olapBuffer[i] = round_fx( L_shl( fftBuffer[i], fftBufferExp - 15 ) ); + olapBuffer[i] = extract_l( L_shr_r( fftBuffer[i], 31 - fftBufferExp ) ); move16(); } } @@ -2519,9 +2519,11 @@ void SynthesisSTFT( { FOR( i = 0; i < len4; i++ ) { - olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx( L_shl( fftBuffer[i + 1 * len4], fftBufferExp - 15 ) ), olapWin[i].v.im ) ); + // olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx( L_shl( fftBuffer[i + 1 * len4], fftBufferExp - 15 ) ), olapWin[i].v.im ) ); + olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( extract_l( L_shr_r( fftBuffer[i + 1 * len4], 31 - fftBufferExp ) ), olapWin[i].v.im ) ); move16(); - olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx( L_shl( fftBuffer[i + 2 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.re ) ); + // olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx( L_shl( fftBuffer[i + 2 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.re ) ); + olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( extract_l( L_shr_r( fftBuffer[i + 2 * len4], 31 - fftBufferExp ) ), olapWin[len4 - 1 - i].v.re ) ); move16(); } FOR( i = len3; i < len; i++ ) @@ -2532,9 +2534,9 @@ void SynthesisSTFT( FOR( i = 0; i < len4; i++ ) { - olapBuffer[i + 5 * len4] = mult_r( round_fx( L_shl( fftBuffer[i + 5 * len4], fftBufferExp - 15 ) ), olapWin[i].v.re ); + olapBuffer[i + 5 * len4] = mult_r( extract_l( L_shr_r( fftBuffer[i + 5 * len4], 31 - fftBufferExp ) ), olapWin[i].v.re ); move16(); - olapBuffer[i + 6 * len4] = mult_r( round_fx( L_shl( fftBuffer[i + 6 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.im ); + olapBuffer[i + 6 * len4] = mult_r( extract_l( L_shr_r( fftBuffer[i + 6 * len4], 31 - fftBufferExp ) ), olapWin[len4 - 1 - i].v.im ); move16(); } diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 8185faf56d048ef4a077f2ece544d2a76d17ba5e..5ea27f5d8f9c013401f21c11605227975e92ad52 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -7056,6 +7056,16 @@ void generate_comfort_noise_dec_fx( const Word16 nchan_out /* i : number of output channels */ ); +void generate_comfort_noise_dec_ivas_fx( + Word32 **bufferReal, /* o : matrix to real part of i bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of i bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of i bands */ + Decoder_State *stdec, + Word16 *Q_new, + Word16 gen_exc, + const Word16 nchan_out /* i : number of output channels */ +); + void generate_comfort_noise_dec_hf_fx( Word32 **bufferReal, /* o : matrix to real part of i bands */ Word32 **bufferImag, /* o : matrix to imaginary part of i bands */ Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of i bands */ diff --git a/lib_dec/acelp_core_dec_ivas_fx.c b/lib_dec/acelp_core_dec_ivas_fx.c index 422d9c5c6d37379a524cd0a387941bd32b90bf29..8e84bc1ed8140eaaec0f173da812523c2f14e85d 100644 --- a/lib_dec/acelp_core_dec_ivas_fx.c +++ b/lib_dec/acelp_core_dec_ivas_fx.c @@ -692,7 +692,7 @@ ivas_error acelp_core_dec_ivas_fx( } } - generate_comfort_noise_dec_fx( NULL, NULL, NULL, st, &( st->Q_exc ), 1, nchan_out ); + generate_comfort_noise_dec_ivas_fx( NULL, NULL, NULL, st, &( st->Q_exc ), 1, nchan_out ); FdCng_exc( st->hFdCngDec->hFdCngCom, &st->CNG_mode, st->L_frame, st->lsp_old_fx, st->first_CNG, st->lspCNG_fx, Aq_fx, lsp_new_fx, lsf_new_fx, exc_fx, exc2_fx, bwe_exc_fx ); diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index c02850ada55fbd2ea652c00cea70f4ae47cf02f9..a97ac38098626fd42fea460b6ff5584337f28470 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -3803,6 +3803,549 @@ void generate_comfort_noise_dec_fx( } } +void generate_comfort_noise_dec_ivas_fx( + Word32 **bufferReal, /* o : Real part of input bands */ + Word32 **bufferImag, /* o : Imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + Decoder_State *st, /* i/o: decoder state structure */ + Word16 *Q_new, + Word16 gen_exc, + const Word16 nchan_out /* i : number of output channels */ +) +{ + Word16 i, j, s; + Word32 *ptr_r, *ptr_i; + HANDLE_FD_CNG_DEC hFdCngDec = st->hFdCngDec; + HANDLE_FD_CNG_COM hFdCngCom = hFdCngDec->hFdCngCom; + Word32 *cngNoiseLevel = hFdCngCom->cngNoiseLevel; + Word16 cngNoiseLevel_exp = hFdCngCom->cngNoiseLevelExp; + + Word32 *ptr_level = cngNoiseLevel; + Word16 *seed = &( hFdCngCom->seed ); + Word16 *seed2; + Word16 c1, c2; + Word32 tmp1, tmp2; + Word16 scaleCldfb; + Word32 *fftBuffer = hFdCngCom->fftBuffer; + Word16 fftBuffer_exp = hFdCngCom->fftBuffer_exp; + Word16 fftBuffer_temp_exp[FFTLEN]; + Word16 *timeDomainOutput = hFdCngCom->timeDomainBuffer; + Word16 temp; + Word32 sqrtNoiseLevel; + Word16 sqrtNoiseLevel_exp; + Word16 idx = 0; + move16(); + Word16 preemph_fac; + Word16 old_syn_pe_tmp[16]; + Word16 tcx_transition = 0; + TCX_DEC_HANDLE hTcxDec; + move16(); + + hTcxDec = st->hTcxDec; + + scaleCldfb = mult( hFdCngCom->invScalingFactor, CLDFB_SCALING ); + + temp = 0; + move16(); + c1 = Sqrt16( hFdCngCom->coherence_fx, &temp ); + c1 = shl( c1, temp ); + temp = 0; + move16(); + c2 = Sqrt16( sub( MAX_16, hFdCngCom->coherence_fx ), &temp ); + c2 = shl( c2, temp ); + + temp = getScaleFactor32( fftBuffer, FFTLEN ); + scale_sig32( fftBuffer, FFTLEN, temp ); + fftBuffer_exp = sub( fftBuffer_exp, temp ); + hFdCngCom->fftBuffer_exp = fftBuffer_exp; + move16(); + set16_fx( fftBuffer_temp_exp, fftBuffer_exp, FFTLEN ); + fftBuffer_exp = 0; + move16(); + + seed2 = &( hFdCngCom->seed2 ); + if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && EQ_16( st->idchan, 1 ) ) + { + seed2 = &( hFdCngCom->seed3 ); + } + + /* Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel_flt in each bin */ + + IF( hFdCngCom->startBand == 0 ) + { + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) + { + rand_gauss_fx( &tmp1, seed, Q15 ); + rand_gauss_fx( &tmp2, seed2, Q15 ); + fftBuffer[0] = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + fftBuffer_temp_exp[0] = Q16 + Q15; + } + ELSE + { + rand_gauss_fx( &fftBuffer[0], seed, Q15 ); + fftBuffer_temp_exp[0] = Q16; + move16(); + } + sqrtNoiseLevel_exp = cngNoiseLevel_exp; + move16(); + sqrtNoiseLevel = Sqrt32( *ptr_level, &sqrtNoiseLevel_exp ); + fftBuffer[0] = Mpy_32_32( fftBuffer[0], sqrtNoiseLevel ); + move32(); + fftBuffer_temp_exp[0] = add( sqrtNoiseLevel_exp, fftBuffer_temp_exp[0] ); + move16(); + ptr_level++; + ptr_r = fftBuffer + 2; + idx = 2; + } + ELSE + { + fftBuffer[0] = 0; + move16(); + set32_fx( fftBuffer + 2, 0, shl( sub( hFdCngCom->startBand, 1 ), 1 ) ); + ptr_r = fftBuffer + shl( hFdCngCom->startBand, 1 ); + idx = shl( hFdCngCom->startBand, 1 ); + } + + ptr_i = ptr_r + 1; + FOR( ; ptr_level < cngNoiseLevel + sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ); ptr_level++ ) + { + /* Real part in FFT bins */ + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) + { + rand_gauss_fx( &tmp1, seed, Q15 ); + rand_gauss_fx( &tmp2, seed2, Q15 ); + *ptr_r = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + ELSE + { + rand_gauss_fx( ptr_r, seed, Q15 ); + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + + sqrtNoiseLevel_exp = sub( cngNoiseLevel_exp, 1 ); + sqrtNoiseLevel = Sqrt32( *ptr_level, &sqrtNoiseLevel_exp ); + ( *ptr_r ) = Mpy_32_32( ( *ptr_r ), sqrtNoiseLevel ); + move32(); + fftBuffer_temp_exp[idx] = add( fftBuffer_temp_exp[idx], sqrtNoiseLevel_exp ); + move16(); + idx = add( idx, 1 ); + ptr_r += 2; + + /* Imaginary part in FFT bins */ + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) + { + rand_gauss_fx( &tmp1, seed, Q15 ); + rand_gauss_fx( &tmp2, seed2, Q15 ); + *ptr_i = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + ELSE + { + rand_gauss_fx( ptr_i, seed, Q15 ); + fftBuffer_temp_exp[idx] = Q16; + move16(); + } + sqrtNoiseLevel_exp = sub( cngNoiseLevel_exp, 1 ); + sqrtNoiseLevel = Sqrt32( *ptr_level, &sqrtNoiseLevel_exp ); + ( *ptr_i ) = Mpy_32_32( ( *ptr_i ), sqrtNoiseLevel ); + move32(); + fftBuffer_temp_exp[idx] = add( fftBuffer_temp_exp[idx], sqrtNoiseLevel_exp ); + move16(); + idx = add( idx, 1 ); + ptr_i += 2; + } + + /* Remaining FFT bins are set to zero */ + set32_fx( fftBuffer + shl( hFdCngCom->stopFFTbin, 1 ), 0, sub( hFdCngCom->fftlen, shl( hFdCngCom->stopFFTbin, 1 ) ) ); + set16_fx( fftBuffer_temp_exp + shl( hFdCngCom->stopFFTbin, 1 ), 0, sub( hFdCngCom->fftlen, shl( hFdCngCom->stopFFTbin, 1 ) ) ); + + /* Nyquist frequency is discarded */ + fftBuffer[1] = 0; + move32(); + + fftBuffer_exp = MAX_16; + move16(); + FOR( i = 0; i < FFTLEN; i++ ) + { + if ( fftBuffer[i] != 0 ) + { + fftBuffer_exp = s_min( fftBuffer_exp, add( sub( 31, fftBuffer_temp_exp[i] ), norm_l( fftBuffer[i] ) ) ); + } + } + if ( EQ_16( fftBuffer_exp, MAX_16 ) ) + { + fftBuffer_exp = 0; + move16(); + } + fftBuffer_exp = sub( 31, fftBuffer_exp ); + FOR( i = 0; i < FFTLEN; i++ ) + { + fftBuffer[i] = L_shr( fftBuffer[i], sub( fftBuffer_exp, fftBuffer_temp_exp[i] ) ); + move32(); + } + + /* If previous frame is active, reset the overlap-add buffer */ + tcx_transition = 0; + move16(); + IF( EQ_16( hFdCngCom->frame_type_previous, ACTIVE_FRAME ) ) + { + set16_fx( hFdCngCom->olapBufferSynth, 0, hFdCngCom->fftlen ); + test(); + test(); + if ( ( st->last_core_bfi > ACELP_CORE && EQ_16( st->codec_mode, MODE2 ) ) || EQ_16( st->codec_mode, MODE1 ) ) + { + tcx_transition = 1; + move16(); + } + } + + /* Perform STFT synthesis */ + SynthesisSTFT( fftBuffer, fftBuffer_exp, timeDomainOutput, hFdCngCom->olapBufferSynth, hFdCngCom->olapWinSyn, + tcx_transition, hFdCngCom, gen_exc, Q_new, st->element_mode, nchan_out ); + scale_sig32( fftBuffer + hFdCngCom->fftlen, sub( FFTLEN, hFdCngCom->fftlen ), sub( fftBuffer_exp, hFdCngCom->fftBuffer_exp ) ); + + { + Word32 Lener, att; + Word16 exp; + /* update CNG excitation energy for LP_CNG */ + + /* calculate the residual signal energy */ + /*enr = dotp( hFdCngCom->exc_cng, hFdCngCom->exc_cng, hFdCngCom->frameSize ) / hFdCngCom->frameSize;*/ + Lener = Dot_productSq16HQ( 1, hFdCngCom->exc_cng, st->L_frame, &exp ); + exp = add( sub( shl( sub( 15, *Q_new ), 1 ), 8 ), exp ); /*8 = log2(256)*/ + + /* convert log2 of residual signal energy */ + /*(float)log10( enr + 0.1f ) / (float)log10( 2.0f );*/ + Lener = BASOP_Util_Log2( Lener ); + Lener = L_add( Lener, L_shl( L_deposit_l( exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ + if ( EQ_16( st->L_frame, L_FRAME16k ) ) + { + Lener = L_sub( Lener, 10802114l /*0.3219280949f Q25*/ ); /*log2(320) = 8.3219280949f*/ + } + /* decrease the energy in case of WB input */ + IF( st->bwidth != NB ) + { + IF( EQ_16( st->bwidth, WB ) ) + { + IF( st->CNG_mode >= 0 ) + { + /* Bitrate adapted attenuation */ + att = L_shl( L_deposit_l( ENR_ATT_fx[st->CNG_mode] ), 17 ); + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = L_shl( L_deposit_l( ENR_ATT_fx[4] ), 17 ); + } + } + ELSE + { + att = 384 << 17; + move16(); /*1.5 Q8<<17=Q25*/ + } + Lener = L_sub( Lener, att ); + } + /*st->lp_ener = 0.8f * stcod->lp_ener + 0.2f * pow( 2.0f, enr );*/ + Lener = BASOP_util_Pow2( Lener, 6, &exp ); + Lener = Mult_32_16( Lener, 6554 /*0.2f Q15*/ ); + exp = sub( 25, exp ); + Lener = L_shr( Lener, exp ); /*Q6*/ + st->lp_ener_fx = L_add( Mult_32_16( st->lp_ener_fx, 26214 /*0.8f Q15*/ ), Lener ); /*Q6*/ + } + + /* Generate Gaussian random noise in real and imaginary parts of the CLDFB bands + Amplitudes are adjusted to the estimated noise level cngNoiseLevel_flt in each band */ + + test(); + IF( bufferReal != NULL && ( LT_16( hFdCngCom->numCoreBands, hFdCngCom->regularStopBand ) ) ) + { + Word16 bufferReal_exp[CLDFB_NO_COL_MAX]; + Word16 bufferImag_exp[CLDFB_NO_COL_MAX]; + *bufferScale = 0; + move16(); + FOR( j = hFdCngCom->numCoreBands; j < hFdCngCom->regularStopBand; j++ ) + { + sqrtNoiseLevel_exp = add( CLDFBinvScalingFactor_EXP, sub( cngNoiseLevel_exp, 1 ) ); + sqrtNoiseLevel = Sqrt32( Mpy_32_16_1( *ptr_level, scaleCldfb ), &sqrtNoiseLevel_exp ); + + FOR( i = 0; i < hFdCngCom->numSlots; i++ ) + { + /* Real part in CLDFB band */ + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) + { + rand_gauss_fx( &tmp1, seed, Q15 ); + rand_gauss_fx( &tmp2, seed2, Q15 ); + bufferReal[i][j] = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + bufferReal_exp[j] = Q16; + move16(); + } + ELSE + { + rand_gauss_fx( &bufferReal[i][j], seed, Q15 ); + move32(); + bufferReal_exp[j] = Q16; + move16(); + } + + bufferReal[i][j] = Mpy_32_32( bufferReal[i][j], sqrtNoiseLevel ); + move32(); + bufferReal_exp[j] = add( bufferReal_exp[j], sqrtNoiseLevel_exp ); + move16(); + + /* Imaginary part in CLDFB band */ + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( st->element_mode, IVAS_SCE ) && st->cng_ism_flag ) ) + { + rand_gauss_fx( &tmp1, seed, Q15 ); + rand_gauss_fx( &tmp2, seed2, Q15 ); + bufferImag[i][j] = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + bufferImag_exp[j] = Q16; + move16(); + } + ELSE + { + rand_gauss_fx( &bufferImag[i][j], seed, Q15 ); + bufferImag_exp[j] = Q16; + move16(); + } + bufferImag[i][j] = Mpy_32_32( bufferImag[i][j], sqrtNoiseLevel ); + bufferImag_exp[j] = add( bufferImag_exp[j], sqrtNoiseLevel_exp ); + move16(); + + move32(); + } + ptr_level++; + } + + FOR( j = hFdCngCom->numCoreBands; j < hFdCngCom->regularStopBand; j++ ) + { + *bufferScale = s_max( *bufferScale, bufferReal_exp[j] ); + move16(); + *bufferScale = s_max( *bufferScale, bufferImag_exp[j] ); + move16(); + } + + FOR( j = hFdCngCom->numCoreBands; j < hFdCngCom->regularStopBand; j++ ) + { + FOR( i = 0; i < hFdCngCom->numSlots; i++ ) + { + bufferImag[i][j] = L_shr( bufferImag[i][j], sub( *bufferScale, bufferImag_exp[j] ) ); + move32(); + bufferReal[i][j] = L_shr( bufferReal[i][j], sub( *bufferScale, bufferReal_exp[j] ) ); + move32(); + } + } + } + + test(); + IF( EQ_16( hFdCngCom->frame_type_previous, ACTIVE_FRAME ) && EQ_16( st->codec_mode, MODE2 ) ) + { + Word32 old_exc_ener, gain, noise32; + Word16 seed_loc, lpcorder, old_syn, tmp, gain16, N, N2, N4, N8; + Word16 old_exc_ener_exp, gain_exp; + Word16 normFacE, normShiftE, normShiftEM1; + Word16 normFacG, normShiftG, normShiftGM1; + Word16 noiseExp, *old_exc, *old_Aq, *old_syn_pe; + Word16 noise[640], normShiftP2; + Word16 Q_exc, Q_syn; + + + assert( hFdCngCom->frameSize <= 640 ); + + seed_loc = hFdCngCom->seed; + move16(); + N = hFdCngCom->frameSize; + move16(); + N2 = shr( hFdCngCom->frameSize, 1 ); + + IF( st->last_core_bfi > ACELP_CORE ) + { + Word16 left_overlap_mode; + left_overlap_mode = st->hTcxCfg->tcx_last_overlap_mode; + move16(); + if ( EQ_16( left_overlap_mode, ALDO_WINDOW ) ) + { + left_overlap_mode = FULL_OVERLAP; + move16(); + } + tcx_windowing_synthesis_current_frame( timeDomainOutput, st->hTcxCfg->tcx_mdct_window, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_half_length, + st->hTcxCfg->tcx_mdct_window_min_length, 0, left_overlap_mode, NULL, NULL, NULL, NULL, NULL, shr( N, 1 ), shr( sub( abs_s( st->hTcxCfg->tcx_offset ), st->hTcxCfg->tcx_offset ), 1 ), 1, 0, 0 ); + + IF( st->hTcxCfg->last_aldo != 0 ) + { + FOR( i = 0; i < sub( hFdCngCom->frameSize, NS2SA( st->sr_core, N_ZERO_MDCT_NS ) ); i++ ) + { + timeDomainOutput[i] = add( timeDomainOutput[i], shr_r( st->hHQ_core->old_out_LB_fx[i + NS2SA( st->sr_core, N_ZERO_MDCT_NS )], st->hHQ_core->Q_old_wtda_LB ) ); + move16(); + } + } + ELSE + { + tcx_windowing_synthesis_past_frame( hTcxDec->syn_Overl, st->hTcxCfg->tcx_mdct_window, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, + st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, st->hTcxCfg->tcx_last_overlap_mode ); + + FOR( i = 0; i < st->hTcxCfg->tcx_mdct_window_length; i++ ) + { + timeDomainOutput[i] = add( timeDomainOutput[i], shl( hTcxDec->syn_Overl[i], TCX_IMDCT_HEADROOM ) ); + move16(); + } + } + } + ELSE + { + + /* + - the scaling of the LPCs (e.g. old_Aq) is always Q12 (encoder or decoder) + + - the scaling of the deemphasized signals (e.g. old_syn) is always Q0 (encoder or decoder) + + - the scaling of the excitation signals in the encoder (e.g. old_exc) is Q_new + - the scaling of the preemphasized signals in the encoder (e.g. old_syn_pe) is Q_new-1 + + - the scaling of the excitation signals in the decoder (e.g. old_exc) is Q_exc (or stdec->Q_exc) + - the scaling of the preemphasized signals in the decoder (e.g. old_syn_pe) is Q_syn (or stdec->Q_syn) + */ + + lpcorder = M; + move16(); + old_Aq = st->old_Aq_12_8_fx; + old_exc = st->old_exc_fx + sub( L_EXC_MEM_DEC, N2 ); + old_syn_pe = st->mem_syn2_fx; + old_syn = st->syn[lpcorder]; + move16(); + preemph_fac = st->preemph_fac; + move16(); + Q_exc = st->Q_exc; + move16(); + Q_syn = st->Q_syn; + move16(); + + /* shift to be in the range of values supported by getNormReciprocalWord16() */ + N8 = shr( N2, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + assert( N2 == ( N8 << CNG_NORM_RECIPROCAL_RANGE_SHIFT ) ); + + normFacE = getNormReciprocalWord16( N8 ); + normShiftE = BASOP_util_norm_s_bands2shift( N8 ); + normShiftEM1 = sub( normShiftE, 1 ); + normShiftP2 = add( normShiftE, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + old_exc_ener = L_shr( L_mult( old_exc[0], old_exc[0] ), normShiftP2 ); + FOR( i = 1; i < N2; i++ ) + { + old_exc_ener = L_add( old_exc_ener, L_shr( L_mult( old_exc[i], old_exc[i] ), normShiftP2 ) ); + } + old_exc_ener = L_shl( Mpy_32_16_1( old_exc_ener, shl( normFacE, normShiftEM1 ) ), 1 ); + + old_exc_ener_exp = 0; + move16(); + old_exc_ener = Sqrt32( old_exc_ener, &old_exc_ener_exp ); + old_exc_ener_exp = add( old_exc_ener_exp, ( sub( 15, Q_exc ) ) ); + + /* shift to be in the range of values supported by getNormReciprocalWord16() */ + N4 = shr( N, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + assert( N == ( N4 << CNG_NORM_RECIPROCAL_RANGE_SHIFT ) ); + + normFacG = getNormReciprocalWord16( N4 ); + normShiftG = BASOP_util_norm_s_bands2shift( N4 ); + normShiftGM1 = sub( normShiftG, 1 ); + normShiftP2 = add( normShiftG, CNG_NORM_RECIPROCAL_RANGE_SHIFT ); + + gain = L_deposit_l( 0 ); + FOR( i = 0; i < N; i++ ) + { + noise32 = rand_gauss( &seed_loc ); + noise[i] = extract_h( noise32 ); + move16(); + gain = L_add( gain, L_shr( L_mult( noise[i], noise[i] ), normShiftP2 ) ); + } + gain = L_shl( Mpy_32_16_1( gain, shl( normFacG, normShiftGM1 ) ), 1 ); + + gain_exp = 2 * CNG_RAND_GAUSS_SHIFT; + move16(); + gain = ISqrt32( gain, &gain_exp ); + + gain = Mpy_32_32( old_exc_ener, gain ); + gain16 = extract_h( gain ); + + gain_exp = add( old_exc_ener_exp, gain_exp ); + noiseExp = add( CNG_RAND_GAUSS_SHIFT, gain_exp ); + + s = sub( 15 - NOISE_HEADROOM, noiseExp ); + FOR( i = 0; i < N; i++ ) + { +#ifdef BASOP_NOGLOB + noise[i] = shr_sat( mult( noise[i], gain16 ), s ); +#else + noise[i] = shr( mult( noise[i], gain16 ), s ); +#endif + move16(); + } + + assert( lpcorder <= 16 ); + + s = sub( 15 - NOISE_HEADROOM, ( sub( 15, Q_syn ) ) ); + FOR( i = 0; i < lpcorder; i++ ) + { +#ifdef BASOP_NOGLOB + old_syn_pe_tmp[i] = shr_sat( old_syn_pe[i], s ); +#else + old_syn_pe_tmp[i] = shr( old_syn_pe[i], s ); +#endif + move16(); + } + + E_UTIL_synthesis( + 0, /* i : scaling to apply for a[0] Q0 */ + old_Aq, /* i : LP filter coefficients Q12 */ + noise, /* i : input signal Qx */ + noise, /* o : output signal Qx-s */ + N, /* i : size of filtering Q0 */ + old_syn_pe_tmp, /* i/o: memory associated with this filtering. Q0 */ + 0, /* i : 0=no update, 1=update of memory. Q0 */ + lpcorder /* i : order of LP filter Q0 */ + ); + + tmp = old_syn; + move16(); + + E_UTIL_deemph2( + NOISE_HEADROOM, + noise, /* I/O: signal Qx */ + preemph_fac, /* I: deemphasis factor Qx */ + N, /* I: vector size */ + &tmp /* I/O: memory (signal[-1]) Qx */ + ); + + FOR( i = 0; i < N4; i++ ) + { + tmp = mult( noise[i], hFdCngCom->olapWinSyn[i].v.re ); + timeDomainOutput[i] = add( timeDomainOutput[i], tmp ); + move16(); + tmp = mult( noise[add( i, N4 )], hFdCngCom->olapWinSyn[sub( sub( N4, 1 ), i )].v.im ); + timeDomainOutput[add( i, N4 )] = add( timeDomainOutput[add( i, N4 )], tmp ); + move16(); + } + } + } + return; +} void generate_comfort_noise_dec_hf_fx( Word32 **bufferReal, /* o : matrix to real part of input bands */