Commit abd4aa4c authored by Sandesh Venkatesh's avatar Sandesh Venkatesh
Browse files

Fix for 3GPP issue 1371: Energy burst in MDCT-Stereo coded item at 48kbps

Link #1371
Restricting the Q-factor of spectrum and mdst_spectrum to Q-factor 9 before enc_ste_pre_mdct to avoid truncation of the spectrums resolved the issue
parent 7f488e0a
Loading
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
@@ -1556,27 +1556,30 @@ void ivas_mdct_core_whitening_enc_fx(
                }
                IF( EQ_16( hTcxEnc0->transform_type[n], TCX_5 ) )
                {
                    Word16 length;
                    Word16 length, len_sbfr;
                    const Word16 tcx5SizeFB = sts[1]->hTcxCfg->tcx5SizeFB;
                    move16();
                    /* length = max(nSampCore / (2 * NB_DIV), L_subframeTCX / (2 * NB_DIV),  NB_DIV = 2 */
                    length = shr( s_max( nSampCore, L_subframeTCX ), 2 );
                    len_sbfr = shr( hTcxEnc0->L_frameTCX, shift );
                    assert( hTcxEnc0->L_frameTCX == hTcxEnc1->L_frameTCX );
                    exp_max = s_max( hTcxEnc0->spectrum_e[n], hTcxEnc1->spectrum_e[n] );
                    exp_max = s_max( exp_max, mdst_spectrum_e[0][n] );
                    exp_max = s_max( exp_max, mdst_spectrum_e[1][n] );

                    // calculate the headroom available
                    exp_com = s_min( L_norm_arr( hTcxEnc1->spectrum_fx[n], length ), L_norm_arr( hTcxEnc0->spectrum_fx[n], length ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[0][n], length ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[1][n], length ) );
                    exp_com = s_min( L_norm_arr( hTcxEnc1->spectrum_fx[n], len_sbfr ), L_norm_arr( hTcxEnc0->spectrum_fx[n], len_sbfr ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[0][n], len_sbfr ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[1][n], len_sbfr ) );

                    q_com = sub( s_min( Q31, add( sub( Q31, exp_max ), exp_com ) ), 6 ); // 6 guarded bits
                    q_com = s_max( q_com, 9 );                                           // Keep the Q-factor at least 9 to avoid precision loss inside enc_ste_pre_mdct.
                    exp_com = sub( Q31, q_com );

                    Scale_sig32( hTcxEnc0->spectrum_fx[n], shr( hTcxEnc0->L_frameTCX, shift ) /* hTcxEnc0->L_frameTCX/nSubframes */, sub( hTcxEnc0->spectrum_e[n], exp_com ) ); // hTcxEnc0->spectrum_e
                    Scale_sig32( hTcxEnc1->spectrum_fx[n], shr( hTcxEnc1->L_frameTCX, shift ) /* hTcxEnc1->L_frameTCX/nSubframes */, sub( hTcxEnc1->spectrum_e[n], exp_com ) ); // hTcxEnc1->spectrum_e
                    Scale_sig32( mdst_spectrum_fx[0][n], shr( hTcxEnc0->L_frameTCX, shift ) /* hTcxEnc0->L_frameTCX/nSubframes */, sub( mdst_spectrum_e[0][n], exp_com ) );     // mdst_spectrum_e
                    Scale_sig32( mdst_spectrum_fx[1][n], shr( hTcxEnc1->L_frameTCX, shift ) /* hTcxEnc1->L_frameTCX/nSubframes */, sub( mdst_spectrum_e[1][n], exp_com ) );     // mdst_spectrum_e
                    scale_sig32( hTcxEnc0->spectrum_fx[n], len_sbfr /* hTcxEnc0->L_frameTCX/nSubframes */, sub( hTcxEnc0->spectrum_e[n], exp_com ) ); // hTcxEnc0->spectrum_e
                    scale_sig32( hTcxEnc1->spectrum_fx[n], len_sbfr /* hTcxEnc1->L_frameTCX/nSubframes */, sub( hTcxEnc1->spectrum_e[n], exp_com ) ); // hTcxEnc1->spectrum_e
                    scale_sig32( mdst_spectrum_fx[0][n], len_sbfr /* hTcxEnc0->L_frameTCX/nSubframes */, sub( mdst_spectrum_e[0][n], exp_com ) );     // mdst_spectrum_e
                    scale_sig32( mdst_spectrum_fx[1][n], len_sbfr /* hTcxEnc1->L_frameTCX/nSubframes */, sub( mdst_spectrum_e[1][n], exp_com ) );     // mdst_spectrum_e

                    Word16 q_com_orig = q_com;
                    move16();
@@ -1600,17 +1603,18 @@ void ivas_mdct_core_whitening_enc_fx(
                    exp_max = sub( Q31, q_com );
                    move16();

                    exp_com = s_min( L_norm_arr( hTcxEnc1->spectrum_fx[n], shr( hTcxEnc1->L_frameTCX, shift ) /* hTcxEnc1->L_frameTCX/nSubframes */ ), L_norm_arr( hTcxEnc0->spectrum_fx[n], shr( hTcxEnc0->L_frameTCX, shift ) /* hTcxEnc0->L_frameTCX/nSubframes */ ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[0][n], shr( hTcxEnc0->L_frameTCX, shift ) /* hTcxEnc0->L_frameTCX/nSubframes */ ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[1][n], shr( hTcxEnc1->L_frameTCX, shift ) /* hTcxEnc1->L_frameTCX/nSubframes */ ) );
                    exp_com = s_min( L_norm_arr( hTcxEnc1->spectrum_fx[n], len_sbfr /* hTcxEnc1->L_frameTCX/nSubframes */ ), L_norm_arr( hTcxEnc0->spectrum_fx[n], len_sbfr /* hTcxEnc0->L_frameTCX/nSubframes */ ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[0][n], len_sbfr /* hTcxEnc0->L_frameTCX/nSubframes */ ) );
                    exp_com = s_min( exp_com, L_norm_arr( mdst_spectrum_fx[1][n], len_sbfr /* hTcxEnc1->L_frameTCX/nSubframes */ ) );

                    q_com = sub( s_min( Q31, add( q_com, exp_com ) ), 6 );
                    q_com = s_max( q_com, 9 ); // Keep the Q-factor at least 9 to avoid precision loss inside enc_ste_pre_mdct.
                    exp_com = sub( Q31, q_com );

                    Scale_sig32( hTcxEnc0->spectrum_fx[n], shr( hTcxEnc0->L_frameTCX, shift ) /* hTcxEnc0->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) ); // exp_max
                    Scale_sig32( hTcxEnc1->spectrum_fx[n], shr( hTcxEnc1->L_frameTCX, shift ) /* hTcxEnc1->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) ); // exp_max
                    Scale_sig32( mdst_spectrum_fx[0][n], shr( hTcxEnc0->L_frameTCX, shift ) /* hTcxEnc0->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) );   // exp_max
                    Scale_sig32( mdst_spectrum_fx[1][n], shr( hTcxEnc1->L_frameTCX, shift ) /* hTcxEnc1->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) );   // exp_max
                    scale_sig32( hTcxEnc0->spectrum_fx[n], len_sbfr /* hTcxEnc0->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) ); // exp_max
                    scale_sig32( hTcxEnc1->spectrum_fx[n], len_sbfr /* hTcxEnc1->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) ); // exp_max
                    scale_sig32( mdst_spectrum_fx[0][n], len_sbfr /* hTcxEnc0->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) );   // exp_max
                    scale_sig32( mdst_spectrum_fx[1][n], len_sbfr /* hTcxEnc1->L_frameTCX/nSubframes */, sub( exp_max, exp_com ) );   // exp_max

                    q_com_orig = q_com;
                    move16();