diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 278efc10b4a29fc94122959c1609d3eca836ad17..53194fbebc16e2c07c10c0931787284168a349c2 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -6797,6 +6797,14 @@ void init_tcx_cfg_fx( Decoder_State *stdec ); +void generate_comfort_noise_dec_hf_ivas_fx( + Word32 **bufferReal, /* o : matrix to real part of input bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + const Word16 cng_coh_flag /* i : CNG Flag for coherence handling */ + ); + /* Generate the comfort noise based on the target noise level */ void generate_masking_noise(Word16 *timeDomainBuffer, /* i/o: time-domain signal */ Word16 Q, diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c index e405bfb8d8717925b5315a619b03494d96232dd5..86f3132e656b30d7badd3a3a00e776e392894790 100644 --- a/lib_dec/acelp_core_dec.c +++ b/lib_dec/acelp_core_dec.c @@ -45,6 +45,10 @@ #include "ivas_prot.h" #include "ivas_rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#endif +#include "math.h" /*-------------------------------------------------------------------* * acelp_core_dec() @@ -1623,8 +1627,29 @@ ivas_error acelp_core_dec( /* check if the CLDFB works on the right sample rate */ if ( ( st->cldfbAna->no_channels * st->cldfbAna->no_col ) != st->L_frame ) { +#ifdef IVAS_FLOAT_FIXED + Word16 old_len_ana, old_len_bpf; + Word16 new_len; + + // The following lines are to calculate the length of the buffers before and + // after calling the function for fixed pt conversion. The calculations are taken + // based on the logic used in resampleCldfb_ivas_fx + old_len_ana = st->cldfbAna->p_filter_length - st->cldfbAna->no_channels; + old_len_bpf = st->cldfbBPF->p_filter_length - st->cldfbBPF->no_channels; + new_len = 9 * (int16_t)(st->L_frame * FRAMES_PER_SEC * INV_CLDFB_BANDWIDTH + 0.5f); + + floatToFixed_arrL(st->cldfbAna->cldfb_state, st->cldfbAna->cldfb_state_fx, Q11, old_len_ana); + floatToFixed_arrL(st->cldfbBPF->cldfb_state, st->cldfbBPF->cldfb_state_fx, Q10, old_len_bpf); + + resampleCldfb_ivas_fx( st->cldfbAna, st->L_frame * FRAMES_PER_SEC ); + resampleCldfb_ivas_fx( st->cldfbBPF, st->L_frame * FRAMES_PER_SEC ); + + fixedToFloat_arrL(st->cldfbAna->cldfb_state_fx, st->cldfbAna->cldfb_state, Q11, new_len); + fixedToFloat_arrL(st->cldfbBPF->cldfb_state_fx, st->cldfbBPF->cldfb_state, Q10, new_len); +#else resampleCldfb_ivas( st->cldfbAna, st->L_frame * FRAMES_PER_SEC ); resampleCldfb_ivas( st->cldfbBPF, st->L_frame * FRAMES_PER_SEC ); +#endif if ( st->ini_frame > 0 ) { @@ -1655,6 +1680,41 @@ ivas_error acelp_core_dec( if ( !( st->element_mode == IVAS_CPE_MDCT && st->bpf_off ) ) { +#ifdef IVAS_FLOAT_FIXED + ///////////////////////////////////////////////////////////////////////////// + Word16 pst_old_syn_exp; + Word16 tmp_syn_exp; + Word16 tmp_syn_fx[1]; // temporary. just one element because retro_interp4_5 only accesses syn[0] + + // Get exponents. + f2me_buf_16(st->hBPF->pst_old_syn, st->hBPF->pst_old_syn_fx, &pst_old_syn_exp, NBPSF_PIT_MAX); + f2me_16(syn[0], &tmp_syn_fx[0], &tmp_syn_exp); + tmp_syn_exp = s_max(tmp_syn_exp, pst_old_syn_exp); // max exp btween syn and pst_old_syn + + // Float to fix + for (i = 0; i < NBPSF_PIT_MAX; i++) + { + st->hBPF->pst_old_syn_fx[i] = (Word16)(st->hBPF->pst_old_syn[i] * pow(2, 15 - tmp_syn_exp)); + } + tmp_syn_fx[0] = (Word16)(syn[0] * pow(2, 15 - tmp_syn_exp)); + ///////////////////////////////////////////////////////////////////////////// + + test(); + IF ( NE_16( st->L_frame, st->last_L_frame ) && NE_16( st->last_codec_mode, MODE2 ) ) + { + IF ( EQ_16( st->L_frame, L_FRAME ) ) + { + retro_interp5_4_fx( st->hBPF->pst_old_syn_fx ); + } + ELSE IF ( EQ_16( st->L_frame, L_FRAME16k ) ) + { + retro_interp4_5_fx( tmp_syn_fx, st->hBPF->pst_old_syn_fx ); + } + } + + // Fixed to float + me2f_buf_16(st->hBPF->pst_old_syn_fx, tmp_syn_exp, st->hBPF->pst_old_syn, NBPSF_PIT_MAX); +#else if ( st->L_frame != st->last_L_frame && st->last_codec_mode != MODE2 ) { if ( st->L_frame == L_FRAME ) @@ -1666,7 +1726,7 @@ ivas_error acelp_core_dec( retro_interp4_5( syn, st->hBPF->pst_old_syn ); } } - +#endif /* bass post-filter */ bass_psfilter( st->hBPF, st->Opt_AMR_WB, syn, st->L_frame, pitch_buf, st->bpf_off, st->stab_fac, &st->stab_fac_smooth, st->coder_type, bpf_error_signal ); } @@ -1709,7 +1769,28 @@ ivas_error acelp_core_dec( /*WB/SWB-FD_CNG*/ if ( ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && ( st->cng_type == FD_CNG ) && ( st->hFdCngDec->hFdCngCom->numCoreBands < st->cldfbSyn->no_channels ) ) { +#ifdef IVAS_FLOAT_FIXED + /* Float to fixed */ + f2me_buf(st->hFdCngDec->hFdCngCom->cngNoiseLevel_flt, st->hFdCngDec->hFdCngCom->cngNoiseLevel, &st->hFdCngDec->hFdCngCom->cngNoiseLevelExp, FFTCLDFBLEN); + + // NOTE: this should be removed later. + st->hFdCngDec->hFdCngCom->q_cngNoiseLevel = 31 - st->hFdCngDec->hFdCngCom->cngNoiseLevelExp; + + Word16 tmpBufferScale = 0; + generate_comfort_noise_dec_hf_ivas_fx( realBuffer_fx, imagBuffer_fx, /*realBuffer, imagBuffer,*/ &tmpBufferScale, st->hFdCngDec->hFdCngCom, st->cng_ism_flag ); + + /* Fixed to float */ + FOR(i = 0; i < st->hFdCngDec->hFdCngCom->numSlots; i++) + { + FOR(Word16 j = st->hFdCngDec->hFdCngCom->numCoreBands; j < st->hFdCngDec->hFdCngCom->regularStopBand; j++) + { + realBuffer[i][j] = me2f(realBuffer_fx[i][j], tmpBufferScale + 15); + imagBuffer[i][j] = me2f(imagBuffer_fx[i][j], tmpBufferScale + 15); + } + } +#else generate_comfort_noise_dec_hf_flt( realBuffer, imagBuffer, st->hFdCngDec->hFdCngCom, st->cng_ism_flag ); +#endif if ( st->hFdCngDec->hFdCngCom->regularStopBand < st->cldfbSyn->no_channels ) { diff --git a/lib_dec/fd_cng_dec_fx.c b/lib_dec/fd_cng_dec_fx.c index fb73cffdfca59f55350079e9932de64243d82b47..4bf768279b1ab096199ab1caf8aefef62bfc1f1e 100644 --- a/lib_dec/fd_cng_dec_fx.c +++ b/lib_dec/fd_cng_dec_fx.c @@ -3547,6 +3547,135 @@ generate_comfort_noise_dec_hf ( } +void generate_comfort_noise_dec_hf_ivas_fx( + Word32 **bufferReal, /* o : matrix to real part of input bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */ + const Word16 cng_coh_flag /* i : CNG Flag for coherence handling */ +) +{ + Word16 i, j, s, sc, sn; + Word16 scaleCLDFB; + Word32 sqrtNoiseLevel; + Word16 randGaussExp; + Word16 cngNoiseLevelExp; + Word16 *seed; + Word16 *seed2; + Word16 c1, c2; + Word32 *ptr_level; + Word32 *cngNoiseLevel; + Word32 tmp1, tmp2; + + cngNoiseLevel = hFdCngCom->cngNoiseLevel + hFdCngCom->stopFFTbin - hFdCngCom->startBand; + cngNoiseLevelExp = hFdCngCom->cngNoiseLevelExp; + move16(); + ptr_level = cngNoiseLevel; + + seed = &( hFdCngCom->seed ); + + /* scaleCLDFB: CLDFBinvScalingFactor_EXP + 1 */ + scaleCLDFB = mult( hFdCngCom->invScalingFactor, CLDFB_SCALING ); + + seed2 = &( hFdCngCom->seed ); + + c1 = 0; + move16(); + c2 = 0; + move16(); + sc = 0; + move16(); + + IF( cng_coh_flag ) + { + seed2 = &( hFdCngCom->seed2 ); + + s = 0; + move16(); + + c1 = Sqrt16( hFdCngCom->coherence_fx, &s ); + c1 = shl( c1, s ); // Q15 + + s = 0; + move16(); + c2 = Sqrt16( sub( MAX16B, hFdCngCom->coherence_fx ), &s ); + c2 = shl( c2, s ); // Q15 + } + + sn = 0; + move16(); + IF( s_and( cngNoiseLevelExp, 1 ) != 0 ) + { + sn = add( sn, 1 ); + cngNoiseLevelExp = add( cngNoiseLevelExp, sn ); + move16(); + } + + randGaussExp = CNG_RAND_GAUSS_SHIFT; + move16(); + + /* + 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 + */ + IF( LT_16( hFdCngCom->numCoreBands, hFdCngCom->regularStopBand ) ) + { + sc = add( shr( add( cngNoiseLevelExp, CLDFBinvScalingFactor_EXP + 1 - 1 ), 1 ), randGaussExp ); + move16(); + assert( ( ( cngNoiseLevelExp + CLDFBinvScalingFactor_EXP + 1 - 1 ) & 1 ) == 0 ); + + FOR( j = hFdCngCom->numCoreBands; j < hFdCngCom->regularStopBand; j++ ) + { + FOR( i = 0; i < hFdCngCom->numSlots; i++ ) + { + /* scaleCLDFB: CLDFBinvScalingFactor_EXP + 1 */ + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32( L_shr( Mpy_32_16_1( *ptr_level, scaleCLDFB ), sn ), &s ); + + IF( cng_coh_flag ) + { + tmp1 = rand_gauss( seed ); + move16(); + tmp2 = rand_gauss( seed2 ); + move16(); + + bufferReal[i][j] = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + bufferReal[i][j] = L_shl( Mpy_32_32( bufferReal[i][j], sqrtNoiseLevel ), s ); + move32(); + + tmp1 = rand_gauss( seed ); + move16(); + tmp2 = rand_gauss( seed2 ); + move16(); + + bufferImag[i][j] = L_add( Mpy_32_16_1( tmp1, c1 ), Mpy_32_16_1( tmp2, c2 ) ); + move32(); + bufferImag[i][j] = L_shl( Mpy_32_32( bufferImag[i][j], sqrtNoiseLevel ), s ); + move32(); + } + ELSE + { + /* Real part in CLDFB band */ + bufferReal[i][j] = L_shl( Mpy_32_32( rand_gauss( seed ), sqrtNoiseLevel ), s ); + move32(); + + /* Imaginary part in CLDFB band */ + bufferImag[i][j] = L_shl( Mpy_32_32( rand_gauss( seed ), sqrtNoiseLevel ), s ); + move32(); + } + } + ptr_level = ptr_level + 1; + } + *bufferScale = sub( sc, 15 ); + } + + return; +} + + + /* generate_masking_noise