diff --git a/lib_com/options.h b/lib_com/options.h index 2c69ef155a9b17d6608ff0687d69e2ab1921e3cd..1d158b6cd10a599b49b2d63fa34d88da4164249c 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -106,6 +106,7 @@ #define NONBE_FIX_849_OMASA_BFI_CRASH /* VA: issue 849: fix OMASA 2TC and FEC crashes */ #define NONBE_FIX_738_QUATERNION_SLERP_PRECISION /* Quaternion slerp changes*/ #define IVAS_FLOAT_FIXED +#define IVAS_FLOAT_FIXED_CONVERSIONS /* Temporary macro to keep track of intermediate flt to fixed and fixed to flt conversions */ #ifdef IVAS_FLOAT_FIXED #define MSAN_FIX #define FIX_818_COMPLEXITY_IMPROV /* Fix for issue 818 */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index f755d1f63d8ad676b8641c18d928e754aace0b7a..971c05ca2e0054b9e401f9829c6e91f00bd11a1d 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -7707,6 +7707,36 @@ void FEC_scale_syn_fx( const Word16 force_scaling /* i: force scaling */ ); +void FEC_scale_syn_ivas_fx( + const Word16 L_frame, /* i : length of the frame */ + Word16 *update_flg, /* o: flag indicating re-synthesis after scaling*/ + Word16 clas, /* i/o: frame classification */ + const Word16 last_good, /* i: last good frame classification */ + Word16 *synth, /* i/o: synthesized speech at Fs = 12k8 Hz */ + const Word16 *pitch, /* i: pitch values for each subframe */ + Word32 L_enr_old, /* i: energy at the end of previous frame */ + Word32 L_enr_q, /* i: transmitted energy for current frame */ + const Word16 coder_type, /* i: coder type */ + const Word16 LSF_Q_prediction, /* i : LSF prediction mode */ + Word16 *scaling_flag, /* i/o: flag to indicate energy control of syn */ + Word32 *lp_ener_FEC_av, /* i/o: averaged voiced signal energy */ + Word32 *lp_ener_FEC_max, /* i/o: averaged voiced signal energy */ + const Word16 bfi, /* i: current frame BFI */ + const Word32 total_brate, /* i: total bitrate */ + const Word16 prev_bfi, /* i: previous frame BFI */ + const Word32 last_core_brate, /* i: previous frame core bitrate */ + Word16 *exc, /* i/o: excitation signal without enhancement */ + Word16 *exc2, /* i/o: excitation signal with enhancement */ + Word16 Aq[], /* i/o: LP filter coefs (can be modified if BR) */ + Word16 *old_enr_LP, /* i/o: LP filter E of last good voiced frame */ + const Word16 *mem_tmp, /* i: temp. initial synthesis filter states */ + Word16 *mem_syn, /* o: initial synthesis filter states */ + Word16 Q_exc, + Word16 Q_syn, + const Word16 avoid_lpc_burst_on_recovery, /* i : if true the excitation energy is limited if LP has big gain */ + const Word16 force_scaling /* i: force scaling */ +); + #ifdef IVAS_FLOAT_FIXED // LD_music_post_filter_fx.c void LD_music_post_filter_fx( diff --git a/lib_dec/FEC_scale_syn_fx.c b/lib_dec/FEC_scale_syn_fx.c index 7aa2056a21d49f6bba43882295e221e66ec410b0..7d29586b69403dfb99dd770de85dd18dcb83c6cc 100644 --- a/lib_dec/FEC_scale_syn_fx.c +++ b/lib_dec/FEC_scale_syn_fx.c @@ -174,6 +174,633 @@ void FEC_scale_syn_fx( frame_ener_fx( L_frame, clas, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_enr2 /*Q0*/, 1, Q_syn, 3, 0 ); + + test(); + test(); + IF( bfi || ( EQ_32( total_brate, ACELP_7k20 ) ) || ( EQ_32( total_brate, ACELP_8k00 ) ) ) + { + /* previous frame erased and no TC frame */ + IF( *scaling_flag > 0 ) + { + /*enr2 += 0.01f;*/ + L_enr2 = L_max( L_enr2, 1 ); /* L_enr2 is in Q0 */ + + IF( bfi ) /* In all bad frames, limit the gain to 1 */ + { + /* gain2 = (float)sqrt( enr_old / enr2 );*/ + L_tmp = Sqrt_Ratio32( L_enr_old, 0, L_enr2, 0, &exp2 ); +#ifdef BASOP_NOGLOB + gain2 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#else + gain2 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#endif + + /*if( gain2 > 1.0f )gain2 = 1.0f;*/ + gain2 = s_min( gain2, 16384 ); + + /* find the energy/gain at the beginning of the frame */ + frame_ener_fx( L_frame, clas, synth, pitch[0], &L_enr1 /*Q0*/, 1, Q_syn, 3, 0 ); + + /*enr1 += 0.1f;*/ + L_enr1 = L_max( L_enr1, 1 ); /* L_enr2 is in Q0 */ + + /*gain1 = (float)sqrt( enr_old / enr1 );*/ + L_tmp = Sqrt_Ratio32( L_enr_old, 0, L_enr1, 0, &exp2 ); +#ifdef BASOP_NOGLOB + gain1 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#else + gain1 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#endif + + /*if( gain1 > 1.0f )gain1 = 1.0f;*/ + gain1 = s_min( gain1, 16384 ); + } + ELSE /* good frame */ + { + IF( L_enr_q == 0 ) /* If E info (FEC protection bits) is not available in the bitstream */ + { + L_enr_q = L_enr2; + set16_fx( h1, 0, L_FRAME / 2 ); + h1[0] = 1024; + move16(); + /*syn_filt( Aq+(3*(M+1)), M, h1, h1, L_FRAME/2, h1+(M+1), 0 );*/ + E_UTIL_synthesis( 1, Aq + ( 3 * ( M + 1 ) ), h1, h1, L_FRAME / 2, h1 + ( M + 1 ), 0, M ); + + /*Compute tilt */ + /*rr0 = dotp( h1, h1, L_FRAME/2-1 ) + 0.1f;*/ + /*rr1 = dotp( h1, h1+1, L_FRAME/2-1 );*/ + /*tilt = rr1 / rr0;*/ +#ifdef BASOP_NOGLOB + tilt = extract_h( L_shl_sat( get_gain( h1 + 1, h1, L_FRAME / 2 - 1 ), 15 ) ); +#else + tilt = extract_h( L_shl( get_gain( h1 + 1, h1, L_FRAME / 2 - 1 ), 15 ) ); +#endif + pitch_dist = 0; + move16(); + L_mean_pitch = L_mult( pitch[0], 8192 ); + FOR( k = 0; k < ( NB_SUBFR - 1 ); k++ ) + { + pitch_dist = add( pitch_dist, abs_s( sub( pitch[k + 1], pitch[k] ) ) ); + L_mean_pitch = L_mac( L_mean_pitch, pitch[k + 1], 8192 ); + } + /*pitch_dist /= (float)(NB_SUBFR-1); */ + pitch_dist = mult_r( shl( pitch_dist, 4 ), 10923 ); + /*mean_pitch /= (float)(NB_SUBFR);*/ + mean_pitch = extract_h( L_shl( L_mean_pitch, 4 ) ); + + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( GT_16( tilt, 22938 ) ) && /* HF resonnant filter */ + ( ( GT_16( pitch_dist, 8 << 4 ) ) || ( LT_16( mean_pitch, PIT_MIN << 4 ) ) ) && /* pitch unstable or very short */ + ( ( prev_bfi ) || ( ( EQ_16( coder_type, GENERIC ) ) && ( EQ_16( LSF_Q_prediction, AUTO_REGRESSIVE ) ) ) ) ) + { + /*if( enr_q > scaling * enr_old ){enr_q = scaling * enr_old;}*/ +#ifdef BASOP_NOGLOB + L_enr_q = L_min( L_enr_q, L_shl_sat( Mult_32_16( L_enr_old, scaling ), 1 ) ); /* scaling in Q14*/ +#else + L_enr_q = L_min( L_enr_q, L_shl( Mult_32_16( L_enr_old, scaling ), 1 ) ); /* scaling in Q14*/ +#endif + } + ELSE + { + ener_max = *lp_ener_FEC_max; + move32(); + test(); + if ( EQ_16( clas, VOICED_TRANSITION ) || ( GE_16( clas, INACTIVE_CLAS ) ) ) + { + ener_max = *lp_ener_FEC_av; + move32(); + } + /*if( enr_old > ener_max )ener_max = enr_old;*/ + ener_max = L_max( ener_max, L_enr_old ); + + /*if( enr_q > scaling * ener_max ){enr_q = scaling * ener_max;}*/ +#ifdef BASOP_NOGLOB + L_enr_q = L_min( L_enr_q, L_shl_sat( Mult_32_16( ener_max, scaling ), 1 ) ); /* scaling in Q14*/ +#else + L_enr_q = L_min( L_enr_q, L_shl( Mult_32_16( ener_max, scaling ), 1 ) ); /* scaling in Q14*/ +#endif + } + } + /*gain2 = (float)sqrt( enr_q / enr2 );*/ + L_enr_q = L_max( L_enr_q, 1 ); /* L_enr2 is in Q0 */ + L_tmp = Sqrt_Ratio32( L_enr_q, 0, L_enr2, 0, &exp2 ); + gain2 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ + + /*-----------------------------------------------------------------* + * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s) + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && ( clas == UNVOICED_CLAS || EQ_16( clas, INACTIVE_CLAS ) ) ) || + EQ_32( last_core_brate, SID_1k75 ) || EQ_32( last_core_brate, SID_2k40 ) || last_core_brate == FRAME_NO_DATA ) && + prev_bfi ) + { + /* voiced -> unvoiced signal transition */ + /* CNG -> active signal transition */ + gain1 = gain2; + move16(); + } + ELSE + { + /* find the energy at the beginning of the frame */ + frame_ener_fx( L_frame, clas, synth, pitch[0], &L_enr1 /*Q0*/, 1, Q_syn, 3, 0 ); + + /*enr1 += 0.1f;*/ + L_enr1 = L_max( L_enr1, 1 ); /* L_enr1 is in Q0 */ + + /*gain1 = (float)sqrt( enr_old / enr1 );*/ + L_tmp = Sqrt_Ratio32( L_enr_old, 0, L_enr1, 0, &exp2 ); +#ifdef BASOP_NOGLOB + gain1 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#else + gain1 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#endif + + /*if( gain1 > 1.2f )gain1 = 1.2f;*/ + /* prevent clipping */ + gain1 = s_min( gain1, 19661 ); + + /* prevent amplifying the unvoiced or inactive part of the frame in case an offset is followed by an onset */ + test(); + test(); + if ( EQ_16( clas, ONSET ) && GT_16( gain1, gain2 ) && prev_bfi ) + { + gain1 = gain2; + move16(); + } + } + + L_enr2 = L_enr_q; + move32(); /* Set the end frame energy to the scaled energy, to be used in the lp_ener_FEC */ + } + + /*------------------------------------------------------------------------------* + * Smooth the energy evolution by exponentially evolving from gain1 to gain2 + *------------------------------------------------------------------------------*/ + + /*gain2 *= ( 1.0f - AGC );*/ + L_tmp = L_mult( gain2, (Word16) ( 32768 - AGC_FX ) ); + FOR( i = 0; i < L_frame; i++ ) + { + /*gain1 = gain1 * AGC + gain2;*/ + gain1 = mac_r( L_tmp, gain1, AGC_FX ); /* in Q14 */ + /*exc[i] *= gain1;*/ + exc[i] = mac_r( L_mult( exc[i], gain1 ), exc[i], gain1 ); + move16(); + /*exc2[i] *= gain1;*/ +#ifdef BASOP_NOGLOB + exc2[i] = mac_r_sat( L_mult( exc2[i], gain1 ), exc2[i], gain1 ); +#else + exc2[i] = mac_r( L_mult( exc2[i], gain1 ), exc2[i], gain1 ); +#endif + move16(); + } + /* smoothing is done in excitation domain, so redo synthesis */ + Copy( mem_tmp, mem_syn, M ); + syn_12k8_fx( L_frame, Aq, exc2, synth, mem_syn, 1, Q_exc, Q_syn ); + *update_flg = 1; + move16(); + } + } + ELSE + { + /* previous frame erased and no TC frame */ + test(); + IF( prev_bfi && NE_16( coder_type, TRANSITION ) ) + { + IF( L_enr_q == 0 ) + { + L_enr_q = L_max( 1, L_enr2 ); /* sets to 'L_enr2' in 1 clock */ + set16_fx( h1, 0, L_FRAME / 2 ); + h1[0] = 1024; + move16(); + /*syn_filt( Aq+(3*(M+1)), M, h1, h1, L_FRAME/2, h1+(M+1), 0 );*/ + E_UTIL_synthesis( 1, Aq + ( 3 * ( M + 1 ) ), h1, h1, L_FRAME / 2, h1 + ( M + 1 ), 0, M ); + /*Compute tilt */ + /*rr0 = dotp( h1, h1, L_FRAME/2-1 ) + 0.1f;*/ + /*rr1 = dotp( h1, h1+1, L_FRAME/2-1 );*/ + /*tilt = rr1 / rr0;*/ +#ifdef BASOP_NOGLOB + tilt = extract_h( L_shl_sat( get_gain( h1 + 1, h1, L_FRAME / 2 - 1 ), 15 ) ); +#else + tilt = extract_h( L_shl( get_gain( h1 + 1, h1, L_FRAME / 2 - 1 ), 15 ) ); +#endif + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( ( EQ_32( total_brate, ACELP_13k20 ) ) || ( EQ_32( total_brate, ACELP_12k85 ) ) || ( EQ_32( total_brate, ACELP_12k15 ) ) || ( EQ_32( total_brate, ACELP_11k60 ) ) || + ( EQ_32( total_brate, ACELP_9k60 ) ) ) && + ( GT_16( tilt, 22938 ) ) && /* HF resonnant filter */ + ( ( ( clas == UNVOICED_CLAS ) ) || ( EQ_16( clas, INACTIVE_CLAS ) ) ) ) ) /* unvoiced classification */ + { + /*if( enr_q > scaling * enr_old )enr_q = scaling * enr_old;*/ +#ifdef BASOP_NOGLOB + L_enr_q = L_min( L_enr_q, L_shl_sat( Mult_32_16( L_enr_old, scaling ), 1 ) ); /* scaling in Q14*/ +#else + L_enr_q = L_min( L_enr_q, L_shl( Mult_32_16( L_enr_old, scaling ), 1 ) ); /* scaling in Q14*/ +#endif + } + ELSE IF( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) + { + /* Voiced-voiced recovery */ + test(); +#ifdef BASOP_NOGLOB + IF( *old_enr_LP != 0 && GT_16( enr_LP, shl_sat( *old_enr_LP, 1 ) ) ) +#else + IF( *old_enr_LP != 0 && GT_16( enr_LP, shl( *old_enr_LP, 1 ) ) ) +#endif + { + /* enr_q /= enr_LP */ + exp = norm_l( L_enr_q ); + tmp = extract_h( L_shl( L_enr_q, exp ) ); + + exp2 = norm_s( enr_LP ); + tmp2 = shl( enr_LP, exp2 ); + + exp = sub( exp2, exp ); + + tmp3 = sub( tmp, tmp2 ); + IF( tmp3 > 0 ) + { + tmp = shr( tmp, 1 ); + exp = add( exp, 1 ); + } + tmp = div_s( tmp, tmp2 ); + + /* L_enr_q *= 2 * *old_enr_LP */ + L_enr_q = L_shl( L_mult( tmp, shl( *old_enr_LP, 1 ) ), exp ); + } + + ELSE + { + test(); + IF( avoid_lpc_burst_on_recovery && GT_16( enr_LP, 160 ) ) + { + exp = norm_s( enr_LP ); + tmp = shl( enr_LP, exp ); + + exp2 = 7; + move16(); + tmp2 = 160 << 7; /* 160 = 20.0f in Q3 */ + move16(); + exp = sub( exp2, exp ); + + IF( GT_16( tmp, tmp2 ) ) + { + tmp = shr( tmp, 1 ); + exp = add( exp, 1 ); + } + tmp = div_s( tmp, tmp2 ); /* tmp*2^exp = enr_LP/20.0 */ + L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* L_tmp*2^exp = sqrt(20.0/enr_LP) */ + L_enr_q = L_shl( Mpy_32_32( L_enr_q, L_tmp ), exp ); + } + } + } + + test(); + test(); + test(); + test(); + IF( ( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) || force_scaling ) + { + + IF( GT_32( L_enr_q, L_enr_old ) ) /* Prevent energy to increase on voiced */ + { + L_enr_q = L_add( Mpy_32_16_1( L_enr_old, 32767 - SCLSYN_LAMBDA ), Mpy_32_16_1( L_enr_q, SCLSYN_LAMBDA ) ); + } + } + } + + L_enr_q = L_max( 1, L_enr_q ); + + /* gain2 = (float)sqrt( enr_q / enr2 );*/ + exp = norm_l( L_enr_q ); + tmp = extract_h( L_shl( L_enr_q, exp ) ); + + exp2 = norm_l( L_enr2 ); + tmp2 = extract_h( L_shl( L_enr2, exp2 ) ); + + exp2 = sub( exp, exp2 ); /* Denormalize and substract */ + + tmp3 = sub( tmp2, tmp ); + IF( tmp3 > 0 ) + { + tmp2 = shr( tmp2, 1 ); + exp2 = add( exp2, 1 ); + } + + tmp = div_s( tmp2, tmp ); + + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp2 ); +#ifdef BASOP_NOGLOB + gain2 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#else + gain2 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#endif + /*-----------------------------------------------------------------* + * Clipping of the smoothing gain at the frame end + *-----------------------------------------------------------------*/ + + gain2 = s_min( gain2, 19661 ); /* Gain modification clipping */ + if ( LT_32( L_enr_q, 2 ) ) + { + gain2 = s_min( gain2, 16384 ); /* Gain modification clipping */ + } + + /*-----------------------------------------------------------------* + * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s) + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16( clas, SIN_ONSET ) ) /* slow increase */ + { + gain1 = shr( gain2, 1 ); + } + /*------------------------------------------------------------* + * voiced->unvoiced transition recovery + *------------------------------------------------------------*/ + ELSE IF( ( GE_16( last_good, VOICED_TRANSITION ) && LT_16( last_good, INACTIVE_CLAS ) && ( clas == UNVOICED_CLAS || EQ_16( clas, INACTIVE_CLAS ) ) ) || /* voiced->unvoiced transition recovery */ + EQ_32( last_core_brate, SID_1k75 ) || EQ_32( last_core_brate, SID_2k40 ) || last_core_brate == FRAME_NO_DATA ) /* CNG -> active signal transition */ + { + gain1 = gain2; + move16(); + } + ELSE + { + /*--------------------------------------------------------* + * Find the energy at the beginning of the frame + *--------------------------------------------------------*/ + tmp = frame_ener_fx( L_frame, clas, synth, pitch[0], &L_enr1, 0, Q_syn, 3, 0 ); + + /*gain1 = (float)sqrt( enr_old / enr1 );*/ + exp = norm_l( L_enr_old ); + tmp = extract_h( L_shl( L_enr_old, exp ) ); + exp2 = norm_l( L_enr1 ); + tmp2 = extract_h( L_shl( L_enr1, exp2 ) ); + + exp2 = sub( exp, exp2 ); /* Denormalize and substract */ + + tmp3 = sub( tmp2, tmp ); + + IF( tmp3 > 0 ) + { + tmp2 = shr( tmp2, 1 ); + exp2 = add( exp2, 1 ); + } + + tmp = div_s( tmp2, tmp ); + + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp2 ); +#ifdef BASOP_NOGLOB + gain1 = round_fx_sat( L_shl_sat( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#else + gain1 = round_fx( L_shl( L_tmp, sub( exp2, 1 ) ) ); /* in Q14 */ +#endif + /* exp2 is always <= 1 */ + + gain1 = s_min( gain1, 19661 ); + + test(); + test(); + if ( avoid_lpc_burst_on_recovery && ( GT_16( enr_LP, 160 ) ) && ( LE_16( enr_LP, shl_sat( *old_enr_LP, 1 ) ) ) ) + { + gain1 = s_min( gain1, 16384 ); + } + + /*--------------------------------------------------------* + * Prevent a catastrophy in case of offset followed by onset + *--------------------------------------------------------*/ + test(); + if ( ( EQ_16( clas, ONSET ) ) && ( GT_16( gain1, gain2 ) ) ) + { + gain1 = gain2; + move16(); + } + } + /*-----------------------------------------------------------------* + * Smooth the energy evolution by exponentially evolving from + * gain1 to gain2 + *-----------------------------------------------------------------*/ + + L_tmp = L_mult( gain2, (Word16) ( 32768 - AGC_FX ) ); + + FOR( i = 0; i < L_frame; i++ ) + { + gain1 = mac_r( L_tmp, gain1, AGC_FX ); /* in Q14 */ +#ifdef BASOP_NOGLOB + exc[i] = mac_r_sat( L_mult_sat( exc[i], gain1 ), exc[i], gain1 ); + move16(); + exc2[i] = mac_r_sat( L_mult_sat( exc2[i], gain1 ), exc2[i], gain1 ); +#else + exc[i] = mac_r( L_mult( exc[i], gain1 ), exc[i], gain1 ); + move16(); + exc2[i] = mac_r( L_mult( exc2[i], gain1 ), exc2[i], gain1 ); +#endif + move16(); + } + + Copy( mem_tmp, mem_syn, M ); + syn_12k8_fx( L_frame, Aq, exc2, synth, mem_syn, 1, Q_exc, Q_syn ); + *update_flg = 1; + move16(); + } + } + /*-----------------------------------------------------------------* + * Update low-pass filtered energy for voiced frames + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( !bfi && ( GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) ) + { + IF( EQ_16( clas, VOICED_TRANSITION ) ) + { + L_enr2_av = L_enr2; + move32(); + frame_ener_fx( L_frame, VOICED_CLAS, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_ener2_max /*Q0*/, 1, Q_syn, 3, 0 ); + } + ELSE + { + L_ener2_max = L_enr2; + move32(); + frame_ener_fx( L_frame, UNVOICED_CLAS, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_enr2_av /*Q0*/, 1, Q_syn, 3, 0 ); + } + + /**lp_ener_FEC_av = 0.2f * enr2_av + 0.8f * *lp_ener_FEC_av; move32();*/ + *lp_ener_FEC_av = Madd_32_16( Mult_32_16( *lp_ener_FEC_av, 31130 ), L_enr2_av, 1638 ); + move32(); + /**lp_ener_FEC_max = 0.2f * enr2_max + 0.8f * *lp_ener_FEC_max; move32();*/ + *lp_ener_FEC_max = Madd_32_16( Mult_32_16( *lp_ener_FEC_max, 31130 ), L_ener2_max, 1638 ); + move32(); + } + + /*-----------------------------------------------------------------* + * Update the LP filter energy for voiced frames + *-----------------------------------------------------------------*/ + test(); + if ( GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) + { + *old_enr_LP = enr_LP; + move16(); + } + + return; +} + +void FEC_scale_syn_ivas_fx( + const Word16 L_frame, /* i : length of the frame */ + Word16 *update_flg, /* o: flag indicating re-synthesis after scaling*/ + Word16 clas, /* i/o: frame classification */ + const Word16 last_good, /* i: last good frame classification */ + Word16 *synth, /* i/o: synthesized speech at Fs = 12k8 Hz */ + const Word16 *pitch, /* i: pitch values for each subframe */ + Word32 L_enr_old, /* i: energy at the end of previous frame */ + Word32 L_enr_q, /* i: transmitted energy for current frame */ + const Word16 coder_type, /* i: coder type */ + const Word16 LSF_Q_prediction, /* i : LSF prediction mode */ + Word16 *scaling_flag, /* i/o: flag to indicate energy control of syn */ + Word32 *lp_ener_FEC_av, /* i/o: averaged voiced signal energy */ + Word32 *lp_ener_FEC_max, /* i/o: averaged voiced signal energy */ + const Word16 bfi, /* i: current frame BFI */ + const Word32 total_brate, /* i: total bitrate */ + const Word16 prev_bfi, /* i: previous frame BFI */ + const Word32 last_core_brate, /* i: previous frame core bitrate */ + Word16 *exc, /* i/o: excitation signal without enhancement */ + Word16 *exc2, /* i/o: excitation signal with enhancement */ + Word16 Aq[], /* i/o: LP filter coefs (can be modified if BR) */ + Word16 *old_enr_LP, /* i/o: LP filter E of last good voiced frame */ + const Word16 *mem_tmp, /* i: temp. initial synthesis filter states */ + Word16 *mem_syn, /* o: initial synthesis filter states */ + Word16 Q_exc, + Word16 Q_syn, + const Word16 avoid_lpc_burst_on_recovery, /* i : if true the excitation energy is limited if LP has big gain */ + const Word16 force_scaling /* i: force scaling */ +) +{ + Word16 i; + Word32 L_enr1, L_enr2; + Word16 gain1, gain2, enr_LP; + Word16 tmp, tmp2, exp, exp2; + Word16 tmp3; + Word32 L_tmp; + Word16 scaling; + Word32 ener_max, L_enr2_av, L_ener2_max; + Word16 h1[L_FRAME / 2], tilt, pitch_dist, mean_pitch; + Word16 k; + Word32 L_mean_pitch; + + enr_LP = 0; + move16(); + gain2 = 0; + move16(); + gain1 = 0; + move16(); + *update_flg = 0; + move16(); + L_enr_old = L_max( 1, L_enr_old ); /* to avoid division by zero (*L_enr_old is always >= 0) */ + scaling = 16384; + move16(); /* Q14*/ + + /*-----------------------------------------------------------------* + * Find the synthesis filter impulse response on voiced + *-----------------------------------------------------------------*/ + test(); + IF( GE_16( clas, VOICED_TRANSITION ) && LT_16( clas, INACTIVE_CLAS ) ) + { + IF( EQ_16( L_frame, L_FRAME ) ) + { + enr_LP = Enr_1_Az_fx( Aq + ( NB_SUBFR - 1 ) * ( M + 1 ), L_SUBFR ); + } + ELSE /* L_frame == L_FRAME16k */ + { + enr_LP = Enr_1_Az_fx( Aq + ( NB_SUBFR16k - 1 ) * ( M + 1 ), L_SUBFR ); /*Q3*/ + } + } + + /*-----------------------------------------------------------------* + * Define when to scale the synthesis + *-----------------------------------------------------------------*/ + + IF( bfi ) + { + *scaling_flag = 1; + move16(); /* Always check synthesis on bad frames */ + } + ELSE IF( prev_bfi ) + { + test(); + IF( ( EQ_16( LSF_Q_prediction, AUTO_REGRESSIVE ) ) || ( EQ_16( LSF_Q_prediction, MOVING_AVERAGE ) ) ) + { + *scaling_flag = 2; + move16(); /* Decoded LSFs affected */ + } + ELSE IF( NE_16( coder_type, TRANSITION ) ) + { + *scaling_flag = 1; + move16(); /* SN, but not TC mode - LSF still affected by the interpolation */ + } + ELSE + { + *scaling_flag = 0; + move16(); /* LSF still possibly affected due to interpolation */ + } + scaling = 24576; /*1.5 Q14*/ + move16(); + } + ELSE + { + test(); + IF( ( EQ_16( LSF_Q_prediction, AUTO_REGRESSIVE ) ) && ( EQ_16( *scaling_flag, 2 ) ) ) + { + *scaling_flag = 2; + move16(); /* Continue with energy control till the end of AR prediction */ + } + ELSE IF( *scaling_flag > 0 ) + { + ( *scaling_flag ) = sub( *scaling_flag, 1 ); /* If scaling flag was equal to 2, add one control frame to account for the LSF interpolation */ + move16(); + } + scaling = 32767; /*2.0 Q14*/ + move16(); + } + + /*-----------------------------------------------------------------* + * Find the energy/gain at the end of the frame + *-----------------------------------------------------------------*/ + IF( LT_16( getScaleFactor16( synth, L_frame ), 2 ) ) + { + Scale_sig( synth, L_frame, -1 ); + frame_ener_fx( L_frame, clas, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_enr2 /*Q0*/, 1, sub( Q_syn, 1 ), 3, 0 ); + Scale_sig( synth, L_frame, 1 ); + } + ELSE + { + frame_ener_fx( L_frame, clas, synth, pitch[sub( shr( L_frame, 6 ), 1 )], &L_enr2 /*Q0*/, 1, Q_syn, 3, 0 ); + } + test(); test(); IF( bfi || ( EQ_32( total_brate, ACELP_7k20 ) ) || ( EQ_32( total_brate, ACELP_8k00 ) ) ) diff --git a/lib_dec/acelp_core_dec_ivas_fx.c b/lib_dec/acelp_core_dec_ivas_fx.c index 8eb83ce1ab41d7043a5116ab9dee5b43c9ad4287..7ba65505a9ab9c6ca9cfb109b3603aef6edaefd9 100644 --- a/lib_dec/acelp_core_dec_ivas_fx.c +++ b/lib_dec/acelp_core_dec_ivas_fx.c @@ -1246,9 +1246,9 @@ ivas_error acelp_core_dec_ivas_fx( move16(); Copy_Scale_sig( pitch_buf_fx, pitch_buf_tmp, NB_SUBFR16k, -Q6 ); - FEC_scale_syn_fx( st->L_frame, &update_flg, st->clas_dec, st->last_good, psyn_fx, pitch_buf_tmp, st->enr_old_fx, enr_q_fx, st->coder_type, LSF_Q_prediction, - &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, st->total_brate, st->prev_bfi, st->last_core_brate, - exc_fx, exc2_fx, Aq_fx, &st->old_enr_LP, mem_tmp_fx, st->mem_syn2_fx, st->Q_exc, st->Q_syn, avoid_lpc_burst_on_recovery, 0 ); + FEC_scale_syn_ivas_fx( st->L_frame, &update_flg, st->clas_dec, st->last_good, psyn_fx, pitch_buf_tmp, st->enr_old_fx, enr_q_fx, st->coder_type, LSF_Q_prediction, + &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, st->total_brate, st->prev_bfi, st->last_core_brate, + exc_fx, exc2_fx, Aq_fx, &st->old_enr_LP, mem_tmp_fx, st->mem_syn2_fx, st->Q_exc, st->Q_syn, avoid_lpc_burst_on_recovery, 0 ); test(); test(); test(); @@ -1399,9 +1399,9 @@ ivas_error acelp_core_dec_ivas_fx( { Copy_Scale_sig( pitch_buf_fx, pitch_buf_tmp, NB_SUBFR16k, -Q6 ); - FEC_scale_syn_fx( st->L_frame, &update_flg, st->clas_dec, st->last_good, psyn_fx, pitch_buf_tmp, st->enr_old_fx, enr_q_fx, st->coder_type, LSF_Q_prediction, - &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, st->total_brate, st->prev_bfi, st->last_core_brate, - exc_fx, exc2_fx, Aq_fx, &st->old_enr_LP, mem_tmp_fx, st->mem_syn2_fx, st->Q_exc, st->Q_syn, avoid_lpc_burst_on_recovery, 0 ); + FEC_scale_syn_ivas_fx( st->L_frame, &update_flg, st->clas_dec, st->last_good, psyn_fx, pitch_buf_tmp, st->enr_old_fx, enr_q_fx, st->coder_type, LSF_Q_prediction, + &st->scaling_flag, &st->lp_ener_FEC_av, &st->lp_ener_FEC_max, st->bfi, st->total_brate, st->prev_bfi, st->last_core_brate, + exc_fx, exc2_fx, Aq_fx, &st->old_enr_LP, mem_tmp_fx, st->mem_syn2_fx, st->Q_exc, st->Q_syn, avoid_lpc_burst_on_recovery, 0 ); } /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 0514559ae550af7e9e67dc368266211043f6e7aa..e2d9831546369937efb8eea67c2b03ec27a9b123 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -3200,7 +3200,7 @@ void ivas_param_mc_dec_digest_tc_fx( { FOR( i = 0; i < imult1616( nchan_transport, nchan_transport ); i++ ) { - if ( is_next_band ) + if ( is_next_band == 0 ) { cx_fx[i] = L_shr( cx_fx[i], sub( max_e, cx_buff_e[is_next_band][i] ) ); } @@ -5386,6 +5386,8 @@ static void ivas_param_mc_get_mixing_matrices_fx( Word16 Cy_e, Cx_e; Word16 Cy_full_e; + Word16 new_e = 0; + move16(); set_zero_fx( Cproto_fx, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); set_zero_fx( mat_mult_buffer1_fx, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); @@ -5532,9 +5534,6 @@ static void ivas_param_mc_get_mixing_matrices_fx( Copy32( Cy_state_fx, Cy_old_state_fx, imult1616( nY_cov, nY_cov ) ); - Word16 new_e = 0; - move16(); - hParamMC->h_output_synthesis_cov_state.cx_old_e[param_band_idx] = Cx_state_e; move16(); hParamMC->h_output_synthesis_cov_state.cy_old_e[param_band_idx] = Cy_state_e; @@ -5546,6 +5545,7 @@ static void ivas_param_mc_get_mixing_matrices_fx( { new_e = hParamMC->h_output_synthesis_cov_state.cx_old_e[param_band_idx]; move16(); + BREAK; } } @@ -5561,6 +5561,7 @@ static void ivas_param_mc_get_mixing_matrices_fx( { new_e = hParamMC->h_output_synthesis_cov_state.cy_old_e[param_band_idx]; move16(); + BREAK; } } diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index e3b5c8cee963689215ad6c8cbf5c33bac3b74fb0..255ad1b24a97d3a0f139657b3bd6f144e05673db 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -3575,6 +3575,9 @@ ivas_error ivas_rend_crendProcess( return error; } } + + /* update combined orientation access index */ + ivas_combined_orientation_update_index( hCombinedOrientationData, subframe_len ); } ELSE {