diff --git a/lib_com/fd_cng_com_fx.c b/lib_com/fd_cng_com_fx.c index 0ea787913f26b9509610e01b0983c969669f8ef2..3ddbb5ddf4fcc92fa5a7fe41603a53e5c18d9a8d 100644 --- a/lib_com/fd_cng_com_fx.c +++ b/lib_com/fd_cng_com_fx.c @@ -484,6 +484,7 @@ void expand_range_var_exp( return; } +#ifndef FIX_2485_HARMONIZE_minimum_statistics /*------------------------------------------------------------------- * minimum_statistics() * @@ -1688,6 +1689,810 @@ void minimum_statistics_fx( assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ ); } } +#else + +void minimum_statistics_fx( + Word16 len, /* i : Total number of partitions (CLDFB or FFT) */ + Word16 lenFFT, /* i : Number of FFT partitions */ + Word16 *psize, /* i : Partition sizes, fractional Q9*/ + Word16 *msPeriodog, /* i : Periodogram (energies) */ + void *msNoiseFloor_buffer, /* i/o: Noise floors (energies) Q25*/ + void *msNoiseEst_buffer, /* i/o: Noise estimates (energies) Q25*/ + Word32 *msAlpha, /* i/o: Forgetting factors */ + Word16 *msPsd, /* i/o: Power Spectral Density (smoothed periodogram => energies) */ + Word16 *msPsdFirstMoment, /* i/o: PSD statistics of 1st order (energy means) */ + Word32 *msPsdSecondMoment, /* i/o: PSD statistics of 2nd order (energy variances) */ + Word32 *msMinBuf, /* i/o: Buffer of minima (energies) */ + Word32 *msBminWin, /* o : Bias correction factors */ + Word32 *msBminSubWin, /* o : Bias correction factors */ + Word32 *msCurrentMin, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinOut, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies) */ + Word16 *msLocalMinFlag, /* i : Binary flag */ + Word16 *msNewMinFlag, /* i : Binary flag */ + Word16 *msPeriodogBuf, /* i/o: Buffer of periodograms (energies) */ + Word16 *msPeriodogBufPtr, /* i/o: Counter */ + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + const Word16 enc_dec, /* i : encoder/decoder indicator */ + const Word16 element_mode, /* i : IVAS element mode type */ + const Word16 isIVAS ) +{ + Word16 i, j, k, s, s1, s2, s3; + Word16 len2; + Word16 current_len; + Word16 start, stop, cnt; + Word16 totsize; + Word16 inv_totsize; + + Word32 tmp, tmp0, tmp1; + Word32 scalar, scalar2, scalar3; + Word32 snr; + Word32 msAlphaHatMin2; + Word32 BminCorr; + Word32 QeqInvAv; + Word32 *ptr; + Word32 *msPsdSum; + Word32 *msPeriodogSum; + + Word16 tmp16, tmp16_1; + Word16 beta; + Word16 slope; + Word16 QeqInv; + Word16 scalar16; + Word16 scalar216; + Word16 scalar316; + Word16 msM_win; + Word16 msM_subwin; + Word16 msAlphaCorAlpha; + Word16 msAlphaCorAlpha2; + Word16 msPeriodogSum16; + Word16 msNoiseFloor16_scalar; + +#ifdef FIX_2485_HARMONIZE_minimum_statistics + Word32 *msNoiseFloor_buffer32 = (Word32 *) msNoiseFloor_buffer; + Word16 *msNoiseFloor_buffer16 = (Word16 *) msNoiseFloor_buffer; + Word32 *msNoiseEst_buffer32 = (Word32 *) msNoiseEst_buffer; + Word16 *msNoiseEst_buffer16 = (Word16 *) msNoiseEst_buffer; + + + IF( element_mode == 0 ) + { + (void) enc_dec; + (void) hFdCngCom; + } +#endif + + len2 = i_mult( MSNUMSUBFR, len ); + + msM_win = hFdCngCom->msM_win; + move16(); + msM_subwin = hFdCngCom->msM_subwin; + move16(); + + msAlphaCorAlpha = MSALPHACORALPHA; + move16(); + msAlphaCorAlpha2 = MSALPHACORALPHA2; + move16(); + + msPsdSum = hFdCngCom->msPsdSum; + msPeriodogSum = hFdCngCom->msPeriodogSum; + + /* No minimum statistics at initialization */ + IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) ) + { +#ifdef FIX_2485_HARMONIZE_minimum_statistics + Copy( msPeriodog, msPsd, len ); /* 6Q9 */ + Copy( msPeriodog, msPsdFirstMoment, len ); /* 6Q9 */ + IF( isIVAS == 0 ) + { + + Copy( msPeriodog, msNoiseFloor_buffer16, len ); /* 6Q9 */ + Copy( msPeriodog, msNoiseEst_buffer16, len ); /* 6Q9 */ + } + ELSE + { + Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseFloor_buffer32, len, Q16 ); /* Q25 */ + Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseEst_buffer32, len, Q16 ); /* Q25 */ + } +#else + Copy( msPeriodog, msPsd, len ); /* 6Q9 */ + Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseFloor_buffer, len, Q16 ); /* Q25 */ + Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseEst_buffer, len, Q16 ); /* Q25 */ + Copy( msPeriodog, msPsdFirstMoment, len ); /* 6Q9 */ +#endif + + set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len ); + msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS ); + move32(); + msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */ + move32(); + + IF( LT_16( lenFFT, len ) ) + { + msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS ); + move32(); + msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */ + move32(); + } + + /* Increment frame counter at initialization */ + /* Some frames are sometimes zero at initialization => ignore them */ + IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) ) + { + set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */ + set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */ + set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 ); /* 16Q15 */ + set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */ + + hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 ); + move16(); + } + hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */ + move16(); + } + ELSE + { + /* Consider the FFT and CLDFB bands separately + - first iteration for FFT bins, + - second one for CLDFB bands in SWB mode */ + cnt = 0; + move16(); + start = 0; + move16(); + stop = lenFFT; + move16(); + totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ); + WHILE( GT_16( stop, start ) ) + { + current_len = sub( stop, start ); + + /* Compute smoothed correction factor for PSD smoothing */ + + /* msPeriodogSum[cnt] with format 16Q15 */ + msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS ); + move32(); + + IF( msPeriodogSum[cnt] == 0 ) + { + hFdCngCom->msAlphaCor[cnt] = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha ); + move32(); + } + ELSE + { + /* calculate scalar with normalized msPeriodogSum[cnt], exponent -2*s1 */ + s1 = norm_l( msPeriodogSum[cnt] ); +#ifdef FIX_2485_HARMONIZE_minimum_statistics + msPeriodogSum16 = round_fx_sat( L_shl_sat( msPeriodogSum[cnt], s1 ) ); +#else + msPeriodogSum16 = round_fx_sat( L_shl( msPeriodogSum[cnt], s1 ) ); +#endif + scalar = L_mult( msPeriodogSum16, msPeriodogSum16 ); + + /* calculate difference, both elements in 16Q15 format, use absolute value + to avoid -1.0 x -1.0 multiplications later */ + scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) ); + + s2 = WORD32_BITS - 1; + move16(); + if ( scalar2 != 0 ) + { + /* use absolute value to avoid -1.0 x -1.0 multiplications */ + s2 = norm_l( scalar2 ); + } + scalar216 = round_fx_sat( L_shl( scalar2, s2 ) ); + scalar2 = L_mult( scalar216, scalar216 ); + + /* find common exponent */ + tmp16_1 = sub( s1, s2 ); + tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 ); + if ( tmp16_1 < 0 ) + { + scalar2 = L_shr( scalar2, tmp16 ); + } + if ( tmp16_1 > 0 ) + { + scalar = L_shr( scalar, tmp16 ); + } + + + /* add scalar and scalar2, avoid overflows */ + scalar = L_shr( scalar, 1 ); + scalar2 = L_shr( scalar2, 1 ); + scalar3 = L_add( scalar, scalar2 ); + + /* calculate division */ + scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 ); + s3 = s_max( s3, -( WORD16_BITS - 1 ) ); + scalar16 = shl( scalar16, s3 ); + scalar16 = s_max( scalar16, MSALPHACORMAX ); + +#ifdef FIX_2485_HARMONIZE_minimum_statistics + hFdCngCom->msAlphaCor[cnt] = L_add( Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha ), + L_mult( scalar16, msAlphaCorAlpha2 ) ); +#else + hFdCngCom->msAlphaCor[cnt] = Madd_32_16( L_mult( scalar16, msAlphaCorAlpha2 ), hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha ); +#endif + + move32(); + } + + /* Compute SNR */ + + /* msPeriodogSum[cnt] with format 16Q15 */ + Word16 msNoiseFloor16tmp[NPART_SHAPING]; +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + snr = dotp_s_fx( msNoiseFloor_buffer16 + start, psize + start, current_len, CNG_HS ); + } + ELSE + { + IF( enc_dec == ENC ) + { + Copy_Scale_sig32_16( msNoiseFloor_buffer32, msNoiseFloor16tmp, NPART, 0 ); + } + ELSE + { + Copy_Scale_sig32_16( msNoiseFloor_buffer32, msNoiseFloor16tmp, NPART_SHAPING, 0 ); + } + snr = dotp_s_fx( &msNoiseFloor16tmp[start], psize + start, current_len, CNG_HS ); + } +#else + IF( enc_dec == ENC ) + { + Copy_Scale_sig32_16( msNoiseFloor_buffer, msNoiseFloor16tmp, NPART, 0 ); + } + ELSE + { + Copy_Scale_sig32_16( msNoiseFloor_buffer, msNoiseFloor16tmp, NPART_SHAPING, 0 ); + } + snr = dotp_s_fx( &msNoiseFloor16tmp[start], psize + start, current_len, CNG_HS ); +#endif + + IF( GT_32( L_shr( Mpy_32_16_1( msPsdSum[cnt], 18431 /*0.56246299817 Q15*/ ), 13 ), snr ) ) + { + tmp0 = BASOP_Util_Log2( msPsdSum[cnt] ); + tmp1 = BASOP_Util_Log2( snr ); + tmp1 = L_sub( tmp0, tmp1 ); + tmp1 = Mpy_32_16_1( tmp1, MSSNREXP ); + msAlphaHatMin2 = BASOP_Util_InvLog2( tmp1 ); + } + ELSE + { + msAlphaHatMin2 = MSALPHAHATMIN; + move32(); + } + scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX ); + + FOR( j = start; j < stop; j++ ) + { + /* Compute optimal smoothing parameter for PSD estimation */ + test(); +#ifdef FIX_2485_HARMONIZE_minimum_statistics + test(); + test(); + test(); + IF( ( scalar == 0 ) || ( ( isIVAS == 0 ) ? ( msNoiseFloor_buffer16[j] == 0 ) : ( msNoiseFloor_buffer32[j] == 0 ) ) ) +#else + IF( ( scalar == 0 ) || ( msNoiseFloor_buffer[j] == 0 ) ) +#endif + { + msAlpha[j] = msAlphaHatMin2; + move32(); + } + ELSE + { + /* calculate scalar2 with normalized msNoiseFloor[j], exponent -2*s1 */ + s1 = WORD16_BITS - 1; + move16(); +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + if ( msNoiseFloor_buffer16[j] != 0 ) + { + s1 = norm_s( msNoiseFloor_buffer16[j] ); + } + msNoiseFloor16_scalar = shl( msNoiseFloor_buffer16[j], s1 ); + scalar2 = L_mult( msNoiseFloor16_scalar, msNoiseFloor16_scalar ); + + /* calculate difference, both elements in 6Q9 format, use absolute value + to avoid -1.0 x -1.0 multiplications later */ + scalar316 = abs_s( sub( msPsd[j], msNoiseFloor_buffer16[j] ) ); + } + ELSE + { + if ( msNoiseFloor16tmp[j] != 0 ) + { + s1 = norm_s( msNoiseFloor16tmp[j] ); + } + msNoiseFloor16_scalar = shl( msNoiseFloor16tmp[j], s1 ); + scalar2 = L_mult( msNoiseFloor16_scalar, msNoiseFloor16_scalar ); + + /* calculate difference, both elements in 6Q9 format, use absolute value + to avoid -1.0 x -1.0 multiplications later */ + scalar316 = abs_s( sub( msPsd[j], msNoiseFloor16tmp[j] ) ); + } +#else + if ( msNoiseFloor16tmp[j] != 0 ) + { + s1 = norm_s( msNoiseFloor16tmp[j] ); + } + msNoiseFloor16_scalar = shl( msNoiseFloor16tmp[j], s1 ); + scalar2 = L_mult( msNoiseFloor16_scalar, msNoiseFloor16_scalar ); + + /* calculate difference, both elements in 6Q9 format, use absolute value + to avoid -1.0 x -1.0 multiplications later */ + scalar316 = abs_s( sub( msPsd[j], msNoiseFloor16tmp[j] ) ); +#endif + s2 = WORD16_BITS - 1; + move16(); + if ( scalar316 != 0 ) + { + /* use absolute value to avoid -1.0 x -1.0 multiplications */ + s2 = norm_s( scalar316 ); + } + scalar316 = shl( scalar316, s2 ); + scalar3 = L_mult( scalar316, scalar316 ); + + /* find common exponent */ + tmp16_1 = sub( s1, s2 ); + tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 ); + if ( tmp16_1 < 0 ) + { + scalar3 = L_shr( scalar3, tmp16 ); + } + if ( tmp16_1 > 0 ) + { + scalar2 = L_shr( scalar2, tmp16 ); + } + + /* add scalar2 and scalar3, avoid overflows */ + scalar2 = L_shr( scalar2, 1 ); + scalar3 = L_shr( scalar3, 1 ); + scalar3 = L_add( scalar2, scalar3 ); + + /* calculate division */ + tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 ); + scalar2 = Mpy_32_16_1( scalar, tmp16 ); + s3 = s_max( s3, -( WORD32_BITS - 1 ) ); + scalar2 = L_shl( scalar2, s3 ); + msAlpha[j] = L_max( scalar2, msAlphaHatMin2 ); + move32(); + } + + /* Compute the PSD (smoothed periodogram) in each band */ +#ifdef FIX_2485_HARMONIZE_minimum_statistics + msPsd[j] = round_fx( L_add( Mpy_32_16_1( msAlpha[j], msPsd[j] ), + Mpy_32_16_1( L_sub( 2147483647l, msAlpha[j] ), msPeriodog[j] ) ) ); +#else + msPsd[j] = round_fx( Madd_32_16( Mpy_32_16_1( msAlpha[j], msPsd[j] ), L_sub( 2147483647l /*1.0 Q31*/, msAlpha[j] ), msPeriodog[j] ) ); +#endif + + move16(); + } + msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS ); + move32(); + + QeqInvAv = 0l /*0.0 Q31*/; + move32(); + + /* scalar: 7Q24 format */ + tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/; + move32(); + scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) ); + + /* scalar2: 4Q27 format */ + tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/; + move32(); + scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) ); + + FOR( j = start; j < stop; j++ ) + { + /* Compute variance of PSD */ + tmp = L_min( msAlpha[j], MSBETAMAX_SQRT ); + + s1 = WORD32_BITS - 1; + move16(); + if ( tmp != 0 ) + { + s1 = norm_l( tmp ); + } + s2 = shl( s1, 1 ); + + s2 = s_min( s2, WORD32_BITS - 1 ); + + /* beta: scaled by s2 */ + tmp16 = round_fx_sat( L_shl( tmp, s1 ) ); + beta = mult_r( tmp16, tmp16 ); + + /* scalar3: scaled by s3 */ + scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) ); + s3 = norm_l( scalar3 ); + scalar3 = L_shl( scalar3, s3 ); + + /* msPsdFirstMoment: 6Q9 */ + tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] ); + msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] ); + move16(); + + /* msPsdSecondMoment: 12Q19 */ + tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 ); + tmp1 = Mpy_32_32( scalar3, scalar3 ); + tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) ); + msPsdSecondMoment[j] = L_add( tmp0, tmp1 ); + move32(); + + /* Compute inverse of amount of degrees of freedom */ + QeqInv = MSQEQINVMAX; + move16(); +#ifdef FIX_2485_HARMONIZE_minimum_statistics + test(); + test(); + IF( ( isIVAS == 0 ) ? ( msNoiseFloor_buffer16[j] != 0 ) : ( msNoiseFloor_buffer32[j] != 0 ) ) +#else + IF( msNoiseFloor_buffer[j] != 0 /*0.0 Q15*/ ) +#endif + { +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + tmp = L_mult( msNoiseFloor_buffer16[j], msNoiseFloor_buffer16[j] ); + } + ELSE + { + tmp = Mpy_32_32( msNoiseFloor_buffer32[j], msNoiseFloor_buffer32[j] ); + } +#else + tmp = Mpy_32_32( msNoiseFloor_buffer[j], msNoiseFloor_buffer[j] ); +#endif + tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s ); + /* consider factor of 2 */ + s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) ); + if ( s < 0 ) + { + QeqInv = shl( tmp16, s ); + } + QeqInv = s_min( QeqInv, MSQEQINVMAX ); + } + QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) ); + + /* Compute bias correction Bmin */ + tmp0 = Mpy_32_16_1( scalar, QeqInv ); + tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_win, QeqInv ); + tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s ); + msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) ); + move32(); + + tmp0 = Mpy_32_16_1( scalar2, QeqInv ); + tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_subwin, QeqInv ); + tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s ); + msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) ); + move32(); + } + + inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s ); + QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize ); + QeqInvAv = L_shl( QeqInvAv, s ); + hFdCngCom->msQeqInvAv[cnt] = QeqInvAv; + move32(); + + /* New minimum? */ + + /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */ + s = CNG_S + 2 * MSAV_EXP; + move16(); + BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV ); + BminCorr = L_shl( BminCorr, sub( s, 1 ) ); + + /* exponent BminCorr: 1 */ + BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ ); + + FOR( j = start; j < stop; j++ ) + { + /* exponent scalar: CNG_S+1 */ + scalar = Mpy_32_16_1( BminCorr, msPsd[j] ); + + /* exponent scalar2: CNG_S+1+4 */ + scalar2 = Mpy_32_32( scalar, msBminWin[j] ); + + msNewMinFlag[j] = 0; + move16(); + IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ ) + { + msNewMinFlag[j] = 1; + move16(); + /* exponent msCurrentMin[j]: CNG_S+1+4 */ + msCurrentMin[j] = scalar2; + move32(); + /* exponent msCurrentMinSubWindow[j]: CNG_S */ + BASOP_SATURATE_WARNING_OFF_EVS; + msCurrentMinSubWindow[j] = L_shl_sat( Mpy_32_32( scalar, msBminSubWin[j] ), 5 ); + move32(); + BASOP_SATURATE_WARNING_ON_EVS; + } + } + + /* This is used later to identify local minima */ + IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) ) + { + FOR( i = 0; i < 3; i++ ) + { + IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ ) + { + BREAK; + } + } + /* format 1Q30 */ + hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i]; + move32(); + } + + /* Consider the FFT and CLDFB bands separately */ + start = stop; + move16(); + stop = len; + move16(); + totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin ); + cnt = add( cnt, 1 ); + } /*while (stop > start)*/ + + /* Update minimum between sub windows */ + test(); + IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) ) + { + FOR( j = 0; j < len; j++ ) + { + if ( msNewMinFlag[j] > 0 ) + { + msLocalMinFlag[j] = 1; + move16(); + } + if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ ) + { + /* msCurrentMinOut[j] scaled with CNG_S */ + msCurrentMinOut[j] = msCurrentMinSubWindow[j]; + move32(); + } + } + /* Get the current noise floor */ +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor_buffer16, len, -16 ); + } + ELSE + { + Copy32( msCurrentMinOut, msNoiseFloor_buffer32, len ); + } +#else + Copy32( msCurrentMinOut, msNoiseFloor_buffer, len ); +#endif + } + ELSE /* sub window complete */ + { + IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) ) + { + /* Collect buffers */ + Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len ); + + /* Compute minimum among all buffers */ + Copy32( msMinBuf, msCurrentMinOut, len ); + ptr = msMinBuf + len; + FOR( i = 1; i < MSNUMSUBFR; i++ ) + { + FOR( j = 0; j < len; j++ ) + { + if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ ) + { + msCurrentMinOut[j] = *ptr; + move32(); + } + ptr++; + } + } + + /* Take over local minima */ + slope = hFdCngCom->msSlope[0]; + move16(); + FOR( j = 0; j < len; j++ ) + { + if ( EQ_16( j, lenFFT ) ) + { + slope = hFdCngCom->msSlope[1]; + move16(); + } + test(); + test(); + test(); + IF( ( msLocalMinFlag[j] != 0 ) && ( msNewMinFlag[j] == 0 ) && ( LT_32( L_shr( msCurrentMinSubWindow[j], 1 ), Mpy_32_16_1( msCurrentMinOut[j], slope ) ) /*0.0 Q31*/ ) && ( GT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ ) ) + { + msCurrentMinOut[j] = msCurrentMinSubWindow[j]; + move32(); + i = j; + move16(); + FOR( k = 0; k < MSNUMSUBFR; k++ ) + { + msMinBuf[i] = msCurrentMinOut[j]; + move32(); + i = add( i, len ); + } + } + } + + /* Reset */ + set16_fx( msLocalMinFlag, 0, len ); + set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len ); + + /* Get the current noise floor */ +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor_buffer16, len, -16 ); + } + ELSE + { + Copy32( msCurrentMinOut, msNoiseFloor_buffer32, len ); + } +#else + Copy32( msCurrentMinOut, msNoiseFloor_buffer, len ); +#endif + } + } + + + /* Detect sudden offsets based on the FFT bins (core bandwidth) */ + IF( GT_32( Mpy_32_16_1( msPsdSum[0], 655 /*0.02 Q15*/ ), msPeriodogSum[0] ) /*0.0 Q31*/ ) + { + IF( hFdCngCom->offsetflag > 0 ) + { + Copy( msPeriodog, msPsd, len ); + FOR( j = 0; j < len; j++ ) + { + msCurrentMinOut[j] = L_deposit_h( msPeriodog[j] ); + move32(); + } + set32_fx( hFdCngCom->msAlphaCor, 2147483647l /*1.0 Q31*/, cnt ); + set32_fx( msAlpha, 0l /*0.0 Q31*/, len ); + Copy( msPeriodog, msPsdFirstMoment, len ); + set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len ); + + msPsdSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS ); + move32(); + IF( LT_16( lenFFT, len ) ) + { + msPsdSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS ); + move32(); + } + } + hFdCngCom->offsetflag = 1; + move16(); + } + ELSE + { + hFdCngCom->offsetflag = 0; + move16(); + } + + + /* Increment frame counter */ + IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) ) + { + hFdCngCom->msFrCnt = 1; + move16(); + hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 ); + move16(); + if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) ) + { + hFdCngCom->msMinBufferPtr = 0; + move16(); + } + } + ELSE + { + hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 ); + move16(); + } + + /* Smooth noise estimate during CNG phases */ +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + FOR( j = 0; j < len; j++ ) + { + msNoiseEst_buffer16[j] = round_fx( L_mac( L_mult( 31130 /*0.95 Q15*/, msNoiseEst_buffer16[j] ), 1638 /*0.05 Q15*/, msNoiseFloor_buffer16[j] ) ); + move16(); + } + } + ELSE + { + Word64 tmp64; + FOR( j = 0; j < len; j++ ) + { + tmp64 = W_add( W_mult_32_16( msNoiseEst_buffer32[j], 31130 /*0.95 Q15*/ ), W_mult_32_16( msNoiseFloor_buffer32[j], 1638 /*0.05 Q15*/ ) ); + msNoiseEst_buffer32[j] = W_extract_h( W_shl( tmp64, 16 ) ); // Q25 + move32(); + } + } +#else + Word64 tmp64; + FOR( j = 0; j < len; j++ ) + { + tmp64 = W_add( W_mult_32_16( msNoiseEst_buffer[j], 31130 /*0.95 Q15*/ ), W_mult_32_16( msNoiseFloor_buffer[j], 1638 /*0.05 Q15*/ ) ); + msNoiseEst_buffer[j] = W_extract_h( W_shl( tmp64, 16 ) ); // Q25 + move32(); + } +#endif + } + +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS > 0 ) + { + IF( EQ_16( enc_dec, DEC ) && EQ_16( element_mode, IVAS_CPE_TD ) ) + { + // v_multc(msNoiseEst, 1.4125f, msNoiseEst, NPART_SHAPING); + v_multc_att32( msNoiseEst_buffer32, 23142, msNoiseEst_buffer32, NPART_SHAPING ); + } + } +#else + IF( EQ_16( enc_dec, DEC ) && EQ_16( element_mode, IVAS_CPE_TD ) ) + { + // v_multc(msNoiseEst, 1.4125f, msNoiseEst, NPART_SHAPING); + v_multc_att32( msNoiseEst_buffer, 23142, msNoiseEst_buffer, NPART_SHAPING ); + } +#endif + /* Collect buffers */ + Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len ); + + *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 ); + move16(); + if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) ) + { + ( *msPeriodogBufPtr ) = 0; + move16(); + } + + /* Upper limit the noise floors with the averaged input energy */ + FOR( j = 0; j < len; j++ ) + { + scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ ); + + FOR( i = j + len; i < MSBUFLEN * len; i += len ) + { + scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ ); + } +#ifdef FIX_2485_HARMONIZE_minimum_statistics + IF( isIVAS == 0 ) + { + scalar16 = round_fx( scalar ); + if ( GT_16( msNoiseEst_buffer16[j], scalar16 ) /*0.0 Q15*/ ) + { + msNoiseEst_buffer16[j] = scalar16; + move16(); + } + } + ELSE + { + if ( GT_32( msNoiseEst_buffer32[j], scalar ) /*0.0 Q15*/ ) + { + msNoiseEst_buffer32[j] = scalar; + move32(); + } + } + assert( ( ( isIVAS == 0 ) ? ( msNoiseEst_buffer16[j] >= 0 ) : ( msNoiseEst_buffer32[j] >= 0 ) ) ); +#else + if ( GT_32( msNoiseEst_buffer[j], scalar ) /*0.0 Q15*/ ) + { + msNoiseEst_buffer[j] = scalar; + move32(); + } + assert( msNoiseEst[j] >= 0 ); +#endif + } +} + +#endif /*FIX_2485_HARMONIZE_minimum_statistics*/ + + /*------------------------------------------------------------------- * apply_scale() * diff --git a/lib_com/options.h b/lib_com/options.h index 598299d16be2487400788cbb8f308feabd723e21..f2005357a1252a38ee1e7f4bf04c00e070658f02 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -88,6 +88,9 @@ #define FIX_2480_HARM_TONALMDCT /* FhG: basop issue 2480: Harmonize TonalMDCTConceal_Detect_fx() and TonalMDCTConceal_Detect_ivas_fx() */ #define FIX_2479_HARM_PITCH_GAIN /* FhG: basop issue 2479: Harmonize tcx_ltp_pitch_search_*(), tcx_ltp_find_gain_*fx() */ #define HARMONIZE_2481_EXTEND_SHRINK /* FhG: basop issue 2481: Harmonize extend_frm_*fx() and shrink_frm_*fx() */ +#define FIX_2485_HARMONIZE_perform_noise_estimation_enc /* FhG: harmonize perform_noise_estimation_enc and perform_noise_estimation_enc_ivas */ +#define FIX_2485_HARMONIZE_minimum_statistics /* FhG: harmonize minimum_statistics and minimum_statistics_fx */ + /* #################### End BE switches ################################## */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 346bedd078d4914517869feae2414323d4258a0e..82d7a3ef2fc17a8ec3d7a573f35bbd5415f51c3e 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -4587,6 +4587,33 @@ void expand_range_var_exp( Word16 *out_exp, const Word16 len ); +#ifdef FIX_2485_HARMONIZE_minimum_statistics +void minimum_statistics_fx( + Word16 len, /* i : Total number of partitions (CLDFB or FFT) */ + Word16 lenFFT, /* i : Number of FFT partitions */ + Word16 *psize, /* i : Partition sizes, fractional Q9*/ + Word16 *msPeriodog, /* i : Periodogram (energies) */ + void *msNoiseFloor_buffer, /* i/o: Noise floors (energies) Q25*/ + void *msNoiseEst_buffer, /* i/o: Noise estimates (energies) Q25*/ + Word32 *msAlpha, /* i/o: Forgetting factors */ + Word16 *msPsd, /* i/o: Power Spectral Density (smoothed periodogram => energies) */ + Word16 *msPsdFirstMoment, /* i/o: PSD statistics of 1st order (energy means) */ + Word32 *msPsdSecondMoment, /* i/o: PSD statistics of 2nd order (energy variances) */ + Word32 *msMinBuf, /* i/o: Buffer of minima (energies) */ + Word32 *msBminWin, /* o : Bias correction factors */ + Word32 *msBminSubWin, /* o : Bias correction factors */ + Word32 *msCurrentMin, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinOut, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies) */ + Word16 *msLocalMinFlag, /* i : Binary flag */ + Word16 *msNewMinFlag, /* i : Binary flag */ + Word16 *msPeriodogBuf, /* i/o: Buffer of periodograms (energies) */ + Word16 *msPeriodogBufPtr, /* i/o: Counter */ + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + const Word16 enc_dec, /* i : encoder/decoder indicator */ + const Word16 element_mode, /* i : IVAS element mode type */ + const Word16 isIVAS ); +#else void minimum_statistics( Word16 len, /* i : Total number of partitions (CLDFB or FFT) */ Word16 lenFFT, /* i : Number of FFT partitions */ @@ -4636,6 +4663,7 @@ void minimum_statistics_fx( const Word16 enc_dec, /* i : encoder/decoder indicator */ const Word16 element_mode /* i : IVAS element mode type */ ); +#endif /* Apply bitrate-dependant scale */ void apply_scale( diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index 901d2c5cbea9d4a33e9b09a3c69060e338488738..b81e13e27d309c2df236f3af5d4508ae8f998ee6 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -1280,6 +1280,33 @@ void perform_noise_estimation_dec_fx( compress_range( hFdCngDec->msPeriodog, hFdCngDec->msPeriodog_exp, hFdCngDec->msLogPeriodog, npart ); /* Call the minimum statistics routine for noise estimation */ +#ifdef FIX_2485_HARMONIZE_minimum_statistics + minimum_statistics_fx( + npart, + nFFTpart, + psize_norm, + hFdCngDec->msLogPeriodog, + hFdCngDec->msNoiseFloor, + hFdCngDec->msLogNoiseEst, + hFdCngDec->msAlpha, + hFdCngDec->msPsd, + hFdCngDec->msPsdFirstMoment, + hFdCngDec->msPsdSecondMoment, + hFdCngDec->msMinBuf, + hFdCngDec->msBminWin, + hFdCngDec->msBminSubWin, + hFdCngDec->msCurrentMin, + hFdCngDec->msCurrentMinOut, + hFdCngDec->msCurrentMinSubWindow, + hFdCngDec->msLocalMinFlag, + hFdCngDec->msNewMinFlag, + hFdCngDec->msPeriodogBuf, + &( hFdCngDec->msPeriodogBufPtr ), + hFdCngDec->hFdCngCom, + 0, + 0, + 0 ); +#else minimum_statistics( npart, nFFTpart, @@ -1302,6 +1329,7 @@ void perform_noise_estimation_dec_fx( hFdCngDec->msPeriodogBuf, &( hFdCngDec->msPeriodogBufPtr ), hFdCngDec->hFdCngCom ); +#endif /* Expand MS outputs */ expand_range( hFdCngDec->msLogNoiseEst, hFdCngDec->msNoiseEst, &hFdCngDec->msNoiseEst_exp, npart ); @@ -2099,7 +2127,12 @@ void perform_noise_estimation_dec_ivas_fx( hFdCngDec->msPeriodogBuf, &( hFdCngDec->msPeriodogBufPtr ), hFdCngDec->hFdCngCom, - DEC, element_mode ); + DEC, element_mode +#ifdef FIX_2485_HARMONIZE_minimum_statistics + , + 1 +#endif + ); FOR( i = 0; i < hFdCngDec->npart_shaping; i++ ) { diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c index 378e0f9c643563e5d7d1466023ecaa3ef0530954..0ef2f8a13f4433b722b55cdd89f85dcf5d130973 100644 --- a/lib_enc/fd_cng_enc_fx.c +++ b/lib_enc/fd_cng_enc_fx.c @@ -405,6 +405,7 @@ void resetFdCngEnc_fx( return; } +#ifndef FIX_2485_HARMONIZE_perform_noise_estimation_enc /* perform_noise_estimation_enc_fx @@ -565,6 +566,7 @@ void perform_noise_estimation_enc_fx( return; } +#endif /*FIX_2485_HARMONIZE_perform_noise_estimation_enc*/ /* AdjustFirstSID_fx @@ -1741,7 +1743,7 @@ Word16 cng_energy_ivas_fx( return enr; } - +#ifndef FIX_2485_HARMONIZE_perform_noise_estimation_enc void perform_noise_estimation_enc_ivas_fx( Word32 *band_energies, /* i : energy in critical bands without minimum noise floor MODE2_E_MIN band_energies_exp*/ Word16 band_energies_exp, @@ -1931,6 +1933,293 @@ void perform_noise_estimation_enc_ivas_fx( return; } +#endif /*FIX_2485_HARMONIZE_perform_noise_estimation_enc*/ + +#ifdef FIX_2485_HARMONIZE_perform_noise_estimation_enc +void perform_noise_estimation_enc_fx( + Word32 *band_energies, /* i : energy in critical bands without minimum noise floor MODE2_E_MIN band_energies_exp*/ + Word16 band_energies_exp, + Word32 *enerBuffer, /* enerBuffer_exp */ + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables */ + const Word32 input_Fs, /* i : input sampling rate Q0*/ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + int element_mode /* i : is element EVS or IVAS */ +) +{ + if ( element_mode == 0 ) + { + (void) input_Fs; + (void) hCPE; + } + + Word16 i, j, s, s1, s2; + Word16 numBands; + Word16 nFFTpart = hFdCngEnc->hFdCngCom->nFFTpart; /* Q0 */ + move16(); + Word16 numCoreBands = hFdCngEnc->hFdCngCom->numCoreBands; /* Q0 */ + move16(); + Word16 regularStopBand = hFdCngEnc->hFdCngCom->regularStopBand; + move16(); + Word16 numSlots = hFdCngEnc->hFdCngCom->numSlots; /* Q0 */ + move16(); + Word16 nCLDFBpart = hFdCngEnc->hFdCngCom->nCLDFBpart; /* Q0 */ + move16(); + assert( numSlots == 16 ); + Word32 *periodog = hFdCngEnc->hFdCngCom->periodog; /* exp(peridog_exp) */ + Word32 *ptr_per_fx = periodog; + Word32 *msPeriodog_fx = hFdCngEnc->msPeriodog_fx; + Word32 tmp; + + /* preemphasis compensation and grouping of per bin energies into msPeriodog */ + FOR( i = 0; i < nFFTpart; i++ ) + { + tmp = L_add( L_shr( band_energies[i], 1 ), L_shr( band_energies[i + NB_BANDS], 1 ) ); /* exp(band_energies_exp) */ + msPeriodog_fx[i] = Mpy_32_16_1( tmp, preemphCompensation_fx[i] ); /* exp(band_energies_exp + 4) */ + move32(); + } + + /* exponent for fft part of msPeriodog */ + hFdCngEnc->msPeriodog_fx_exp_fft = add( band_energies_exp, PREEMPH_COMPENSATION_EXP ); + move16(); + + numBands = sub( regularStopBand, numCoreBands ); /* Q0 */ + + /* Adjust to the desired time resolution by averaging the periodograms over the CLDFB time slots */ + IF( element_mode > 0 ) /*IVAS: more precission*/ + { + Word16 max_exp = -31; + move16(); + Word16 periodog_exp[PERIODOGLEN]; + Word64 periodog_64; + Word32 scaleEB_fx = 0; + move32(); + i = 0; + move16(); + + test(); + IF( hCPE != NULL && hCPE->hStereoDft != NULL ) + { + SWITCH( input_Fs ) + { + case 8000: + scaleEB_fx = 251648; // Q35 + move32(); + BREAK; + case 16000: + scaleEB_fx = 62912; // Q35 + move32(); + BREAK; + case 32000: + scaleEB_fx = 15728; // Q35 + move32(); + BREAK; + case 48000: + scaleEB_fx = 6991; // Q35 + move32(); + BREAK; + default: + assert( 0 && "invalid sample rate" ); + } + } + ELSE + { + Word32 numSlots_inv_fx = 1073741824; // Q34 of .0625 + move32(); + scaleEB_fx = Mpy_32_32( numSlots_inv_fx, L_deposit_l( hFdCngEnc->hFdCngCom->scalingFactor ) ); // Q34 + Q30 - Q31 = Q33 + scaleEB_fx = L_shl( scaleEB_fx, 2 ); // Q35 + } + + FOR( j = numCoreBands; j < regularStopBand; j++ ) + { + periodog_64 = W_mult_32_32( enerBuffer[j], scaleEB_fx ); + Word16 scale = W_norm( periodog_64 ); + *ptr_per_fx = W_extract_h( W_shl( periodog_64, scale ) ); + move32(); + periodog_exp[i] = sub( Q31, add( add( sub( Q31, enerBuffer_exp ), 35 - 31 ), scale ) ); + move16(); + if ( *ptr_per_fx ) + { + max_exp = s_max( max_exp, periodog_exp[i] ); + } + ptr_per_fx++; + i++; + } + + /* exponent for cldfb part of msPeriodog */ + FOR( i = 0; i < numBands; i++ ) + { + periodog[i] = L_shr( periodog[i], sub( max_exp, periodog_exp[i] ) ); + move16(); + } + hFdCngEnc->hFdCngCom->exp_cldfb_periodog = max_exp; + move16(); + } + ELSE /*EVS_MONO*/ + { + IF( numBands > 0 ) + { + /* Adjust to the desired time resolution by averaging the periodograms over the CLDFB time slots */ + FOR( j = numCoreBands; j < regularStopBand; j++ ) + { + *ptr_per_fx = Mpy_32_16_1( enerBuffer[j], hFdCngEnc->hFdCngCom->scalingFactor ); /* exp(enerBuffer_exp) */ + move32(); + + ptr_per_fx++; + } + + /* exponent for cldfb part of msPeriodog */ + hFdCngEnc->hFdCngCom->exp_cldfb_periodog = add( sub( enerBuffer_exp, 4 ), CLDFBscalingFactor_EXP ); + } + } + + IF( numBands > 0 ) + { + ///* Adjust CLDFB filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + bandcombinepow( + periodog, + hFdCngEnc->hFdCngCom->exp_cldfb_periodog, + numBands, + hFdCngEnc->hFdCngCom->CLDFBpart, + nCLDFBpart, + hFdCngEnc->hFdCngCom->CLDFBpsize_inv, + &msPeriodog_fx[nFFTpart], + &hFdCngEnc->msPeriodog_fx_exp_cldfb ); + + ///* find common exponent for fft part and cldfb part of msperiodog */ + s1 = L_norm_arr( msPeriodog_fx, nFFTpart ); + s2 = L_norm_arr( &msPeriodog_fx[nFFTpart], nCLDFBpart ); + + s = s_max( sub( hFdCngEnc->msPeriodog_fx_exp_fft, s1 ), sub( hFdCngEnc->msPeriodog_fx_exp_cldfb, s2 ) ); + s1 = sub( s, hFdCngEnc->msPeriodog_fx_exp_fft ); + s2 = sub( s, hFdCngEnc->msPeriodog_fx_exp_cldfb ); + + hFdCngEnc->msPeriodog_fx_exp_fft = s; + move16(); + hFdCngEnc->msPeriodog_fx_exp_cldfb = s; + move16(); + + FOR( i = 0; i < nFFTpart; i++ ) + { + msPeriodog_fx[i] = L_shr( msPeriodog_fx[i], s1 ); // hFdCngEnc->msPeriodog_fx_exp_fft + move32(); + } + + FOR( i = 0; i < nCLDFBpart; i++ ) + { + msPeriodog_fx[nFFTpart + i] = L_shr( msPeriodog_fx[nFFTpart + i], s2 ); /* hFdCngEnc->msPeriodog_fx_exp_fft */ + move32(); + } + } + /* exponent for entire msPeriodog vector */ + hFdCngEnc->msPeriodog_fx_exp = hFdCngEnc->msPeriodog_fx_exp_fft; + move16(); + + /* Compress MS inputs */ + compress_range( msPeriodog_fx, hFdCngEnc->msPeriodog_fx_exp, hFdCngEnc->msLogPeriodog_fx, hFdCngEnc->hFdCngCom->npart ); + + /* Call the minimum statistics routine for noise estimation */ +#ifdef FIX_2485_HARMONIZE_minimum_statistics + minimum_statistics_fx( + hFdCngEnc->hFdCngCom->npart, + nFFTpart, + hFdCngEnc->hFdCngCom->psize_norm, + hFdCngEnc->msLogPeriodog_fx, + ( element_mode == 0 ) ? ( (void *) hFdCngEnc->msNoiseFloor_fx ) : ( (void *) hFdCngEnc->msNoiseFloor_32fx ), + ( element_mode == 0 ) ? ( (void *) hFdCngEnc->msLogNoiseEst_fx ) : ( (void *) hFdCngEnc->msLogNoiseEst_32fx ), + hFdCngEnc->msAlpha_fx, + hFdCngEnc->msPsd_fx, + hFdCngEnc->msPsdFirstMoment_fx, + hFdCngEnc->msPsdSecondMoment_fx, + hFdCngEnc->msMinBuf_fx, + hFdCngEnc->msBminWin_fx, + hFdCngEnc->msBminSubWin_fx, + hFdCngEnc->msCurrentMin_fx, + hFdCngEnc->msCurrentMinOut_fx, + hFdCngEnc->msCurrentMinSubWindow_fx, + hFdCngEnc->msLocalMinFlag, + hFdCngEnc->msNewMinFlag, + hFdCngEnc->msPeriodogBuf_fx, + &( hFdCngEnc->msPeriodogBufPtr ), + hFdCngEnc->hFdCngCom, + ENC, + ( hCPE == NULL ) ? 0 : hCPE->element_mode, + element_mode ); + + + /* Expand MS outputs */ + IF( element_mode > 0 ) + { + expand_range_fx( hFdCngEnc->msLogNoiseEst_32fx, hFdCngEnc->msNoiseEst_fx, &hFdCngEnc->msNoiseEst_fx_exp, hFdCngEnc->hFdCngCom->npart ); + } + ELSE + { + expand_range( hFdCngEnc->msLogNoiseEst_fx, hFdCngEnc->msNoiseEst_fx, &hFdCngEnc->msNoiseEst_fx_exp, hFdCngEnc->hFdCngCom->npart ); + } +#else + IF( element_mode > 0 ) + { + minimum_statistics_fx( + hFdCngEnc->hFdCngCom->npart, + nFFTpart, + hFdCngEnc->hFdCngCom->psize_norm, + hFdCngEnc->msLogPeriodog_fx, + hFdCngEnc->msNoiseFloor_32fx, /*32bit*/ + hFdCngEnc->msLogNoiseEst_32fx, /*32bit*/ + hFdCngEnc->msAlpha_fx, + hFdCngEnc->msPsd_fx, + hFdCngEnc->msPsdFirstMoment_fx, + hFdCngEnc->msPsdSecondMoment_fx, + hFdCngEnc->msMinBuf_fx, + hFdCngEnc->msBminWin_fx, + hFdCngEnc->msBminSubWin_fx, + hFdCngEnc->msCurrentMin_fx, + hFdCngEnc->msCurrentMinOut_fx, + hFdCngEnc->msCurrentMinSubWindow_fx, + hFdCngEnc->msLocalMinFlag, + hFdCngEnc->msNewMinFlag, + hFdCngEnc->msPeriodogBuf_fx, + &( hFdCngEnc->msPeriodogBufPtr ), + hFdCngEnc->hFdCngCom, + ENC, + ( hCPE == NULL ) ? 0 : hCPE->element_mode ); + + /* Expand MS outputs */ + expand_range_fx( hFdCngEnc->msLogNoiseEst_32fx, hFdCngEnc->msNoiseEst_fx, &hFdCngEnc->msNoiseEst_fx_exp, hFdCngEnc->hFdCngCom->npart ); + } + ELSE + { + minimum_statistics( + hFdCngEnc->hFdCngCom->npart, + nFFTpart, + hFdCngEnc->hFdCngCom->psize_norm, + hFdCngEnc->msLogPeriodog_fx, + hFdCngEnc->msNoiseFloor_fx, /*16bit*/ + hFdCngEnc->msLogNoiseEst_fx, /*16bit*/ + hFdCngEnc->msAlpha_fx, + hFdCngEnc->msPsd_fx, + hFdCngEnc->msPsdFirstMoment_fx, + hFdCngEnc->msPsdSecondMoment_fx, + hFdCngEnc->msMinBuf_fx, + hFdCngEnc->msBminWin_fx, + hFdCngEnc->msBminSubWin_fx, + hFdCngEnc->msCurrentMin_fx, + hFdCngEnc->msCurrentMinOut_fx, + hFdCngEnc->msCurrentMinSubWindow_fx, + hFdCngEnc->msLocalMinFlag, + hFdCngEnc->msNewMinFlag, + hFdCngEnc->msPeriodogBuf_fx, + &( hFdCngEnc->msPeriodogBufPtr ), + hFdCngEnc->hFdCngCom ); + + /* Expand MS outputs */ + expand_range( hFdCngEnc->msLogNoiseEst_fx, hFdCngEnc->msNoiseEst_fx, &hFdCngEnc->msNoiseEst_fx_exp, hFdCngEnc->hFdCngCom->npart ); + } +#endif /*FIX_2485_HARMONIZE_minimum_statistics*/ + + return; +} +#endif /*FIX_2485_HARMONIZE_perform_noise_estimation_enc*/ /*-------------------------------------------------------------------* diff --git a/lib_enc/ivas_core_pre_proc_front_fx.c b/lib_enc/ivas_core_pre_proc_front_fx.c index 9b2631128e995c86deeb58bc50589ab77d8968a2..a2b66f8fe9df3cfb8dd291f3c4e450dfeee051ff 100644 --- a/lib_enc/ivas_core_pre_proc_front_fx.c +++ b/lib_enc/ivas_core_pre_proc_front_fx.c @@ -860,7 +860,11 @@ void pre_proc_front_ivas_fx( test(); IF( EQ_16( element_mode, IVAS_CPE_TD ) && lr_vad_enabled && band_energies_LR_fx != NULL ) { +#ifdef FIX_2485_HARMONIZE_perform_noise_estimation_enc + perform_noise_estimation_enc_fx( band_energies_LR_fx, sub( Q31, band_energies_LR_fx_q ), enerBuffer_fx, *enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE, st->element_mode ); +#else perform_noise_estimation_enc_ivas_fx( band_energies_LR_fx, sub( Q31, band_energies_LR_fx_q ), enerBuffer_fx, *enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE ); +#endif } ELSE { @@ -871,8 +875,11 @@ void pre_proc_front_ivas_fx( st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog = sub( st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog, norm ); move16(); } - +#ifdef FIX_2485_HARMONIZE_perform_noise_estimation_enc + perform_noise_estimation_enc_fx( band_energies_fx, sub( Q31, q_band_energies ), enerBuffer_fx, *enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE, st->element_mode ); +#else perform_noise_estimation_enc_ivas_fx( band_energies_fx, sub( Q31, q_band_energies ), enerBuffer_fx, *enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE ); +#endif } } } diff --git a/lib_enc/pre_proc_fx.c b/lib_enc/pre_proc_fx.c index 7ee3143b61037f43ca0e17b27ecb2ea8051bbc32..020d0e8a36dea72bf45c245f4470eafc50c54460 100644 --- a/lib_enc/pre_proc_fx.c +++ b/lib_enc/pre_proc_fx.c @@ -323,7 +323,11 @@ void pre_proc_fx( resetFdCngEnc_fx( st ); +#ifdef FIX_2485_HARMONIZE_perform_noise_estimation_enc + perform_noise_estimation_enc_fx( st->band_energies, st->band_energies_exp, enerBuffer, enerBuffer_exp, st->hFdCngEnc, 0, NULL, EVS_MONO ); +#else perform_noise_estimation_enc_fx( st->band_energies, st->band_energies_exp, enerBuffer, enerBuffer_exp, st->hFdCngEnc ); +#endif /*-----------------------------------------------------------------* * Select SID or FRAME_NO_DATA frame if DTX enabled diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index ffcfbff2081ebcb5af61dcc7aa0c5ce0f66524df..ce0a8aa5e71d252e17b026bba7dfa2e48e714c0b 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -1598,6 +1598,18 @@ void configureFdCngEnc_fx( ); /* Perform noise estimation */ +#ifdef FIX_2485_HARMONIZE_perform_noise_estimation_enc +void perform_noise_estimation_enc_fx( + Word32 *band_energies, /* i : energy in critical bands without minimum noise floor MODE2_E_MIN band_energies_exp*/ + Word16 band_energies_exp, + Word32 *enerBuffer, /* enerBuffer_exp */ + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables */ + const Word32 input_Fs, /* i : input sampling rate Q0*/ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + int element_mode /* i : is element EVS or IVAS */ +); +#else void perform_noise_estimation_enc_fx( Word32 *band_energies, /* i : energy in critical bands without minimum noise floor MODE2_E_MIN exp_band_energies*/ Word16 exp_band_energies, @@ -1615,6 +1627,7 @@ void perform_noise_estimation_enc_ivas_fx( const Word32 input_Fs, /* i : input sampling rate Q0*/ CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ ); +#endif /* Adjust the noise estimator at the beginning of each CNG phase (encoder-side) */ Word16 AdjustFirstSID_fx(