diff --git a/lib_com/fft_fx.c b/lib_com/fft_fx.c index 31b11a9ea889f30a00fed73222a95cc33240856f..5ee5098797c3b57caf6c91e826bcc76dd1fdf850 100644 --- a/lib_com/fft_fx.c +++ b/lib_com/fft_fx.c @@ -7555,146 +7555,3 @@ void rfft_fx( return; } - -Word16 find_guarded_bits_fx( Word32 n ) -{ - // return n <= 1 ? 0 : n <= 2 ? 1 - // : n <= 4 ? 2 - // : n <= 8 ? 3 - // : n <= 16 ? 4 - // : n <= 32 ? 5 - // : n <= 64 ? 6 - // : n <= 128 ? 7 - // : n <= 256 ? 8 - // : n <= 512 ? 9 - // : n <= 1024 ? 10 - // : n <= 2048 ? 11 - // : n <= 4096 ? 12 - // : n <= 8192 ? 13 - // : n <= 16384 ? 14 - // : 15; - /*Word16 val = 0; - move32(); - test(); - WHILE( GT_32( n, L_shl( 1, val ) ) && LT_32( val, 16 ) ) - { - val = add( val, 1 ); - }*/ - IF( LE_32( n, 1 ) ) - { - return 0; - } - ELSE - { - - return sub( 31, norm_l( L_sub( n, 1 ) ) ); - } -} - -Word16 L_norm_arr( const Word32 *arr, Word16 size ) -{ - Word16 q = 31; - move16(); - FOR( Word16 i = 0; i < size; i++ ) - { - Word16 q_tst; - - q_tst = norm_l( arr[i] ); - if ( arr[i] != 0 ) - { - q = s_min( q, q_tst ); - } - } - - return q; -} - -Word16 norm_arr( Word16 *arr, Word16 size ) -{ - Word16 q = 15; - Word16 exp = 0; - move16(); - move16(); - FOR( Word16 i = 0; i < size; i++ ) - { - if ( arr[i] != 0 ) - { - exp = norm_s( arr[i] ); - } - if ( arr[i] != 0 ) - { - q = s_min( q, exp ); - } - } - return q; -} - -Word16 W_norm_arr( Word64 *arr, Word16 size ) -{ - Word16 q = 63; - Word16 exp = 0; - move16(); - move16(); - FOR( Word16 i = 0; i < size; i++ ) - { - if ( arr[i] != 0 ) - { - exp = W_norm( arr[i] ); - } - if ( arr[i] != 0 ) - { - q = s_min( q, exp ); - } - } - return q; -} - -Word16 get_min_scalefactor( Word32 x, Word32 y ) -{ - Word16 scf_y; - Word16 scf = Q31; - move16(); - - test(); - if ( x == 0 && y == 0 ) - { - scf = 0; - move16(); - } - - if ( x != 0 ) - { - scf = norm_l( x ); - } - - scf_y = norm_l( y ); - if ( y != 0 ) - { - scf = s_min( scf_y, scf ); - } - - return scf; -} - - -Flag is_zero_arr( Word32 *arr, Word16 size ) -{ - FOR( Word16 i = 0; i < size; i++ ) - IF( arr[i] != 0 ) - { - return 0; - } - - return 1; -} - -Flag is_zero_arr16( Word16 *arr, Word16 size ) -{ - FOR( Word16 i = 0; i < size; i++ ) - IF( arr[i] != 0 ) - { - return 0; - } - - return 1; -} diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 1452d8e2e13c2e4ba884bf130ab38d252b5a1d56..e60b8ac92164b06c2f70cff9de6bd9dc6427d9fd 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -1444,6 +1444,13 @@ void scale_sig32( const Word16 lg, /* i : size of x[] Q0 */ const Word16 exp0 /* i : exponent: x = round(x << exp) Qx xx exp */ ); + +void Scale_sig64( + Word64 x[], /* i/o: signal to scale Qx */ + Word16 len, /* i : size of x[] Q0 */ + Word16 exp /* i : exponent: x = round(x << exp) Qx exp */ +); + void scale_sig32_r( Word32 x[], /* i/o: signal to scale Qx */ const Word16 lg, /* i : size of x[] Q0 */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 9e5547c7d8c1f6c079e32d7262499f6ea611a0eb..5f0e172bf5059905e04bbb9a205c91e4d22fdf5f 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -4526,3 +4526,167 @@ void v_add_fixed_me( return; } + +Word16 find_guarded_bits_fx( Word32 n ) +{ + // return n <= 1 ? 0 : n <= 2 ? 1 + // : n <= 4 ? 2 + // : n <= 8 ? 3 + // : n <= 16 ? 4 + // : n <= 32 ? 5 + // : n <= 64 ? 6 + // : n <= 128 ? 7 + // : n <= 256 ? 8 + // : n <= 512 ? 9 + // : n <= 1024 ? 10 + // : n <= 2048 ? 11 + // : n <= 4096 ? 12 + // : n <= 8192 ? 13 + // : n <= 16384 ? 14 + // : 15; + /*Word16 val = 0; + move32(); + test(); + WHILE( GT_32( n, L_shl( 1, val ) ) && LT_32( val, 16 ) ) + { + val = add( val, 1 ); + }*/ + IF( LE_32( n, 1 ) ) + { + return 0; + } + ELSE + { + + return sub( 31, norm_l( L_sub( n, 1 ) ) ); + } +} + +Word16 L_norm_arr( const Word32 *arr, Word16 size ) +{ + Word16 q = 31; + move16(); + FOR( Word16 i = 0; i < size; i++ ) + { + Word16 q_tst; + + q_tst = norm_l( arr[i] ); + if ( arr[i] != 0 ) + { + q = s_min( q, q_tst ); + } + } + + return q; +} + +Word16 norm_arr( Word16 *arr, Word16 size ) +{ + Word16 q = 15; + Word16 exp = 0; + move16(); + move16(); + FOR( Word16 i = 0; i < size; i++ ) + { + if ( arr[i] != 0 ) + { + exp = norm_s( arr[i] ); + } + if ( arr[i] != 0 ) + { + q = s_min( q, exp ); + } + } + return q; +} + +Word16 W_norm_arr( Word64 *arr, Word16 size ) +{ + Word16 q = 63; + Word16 exp = 0; + move16(); + move16(); + FOR( Word16 i = 0; i < size; i++ ) + { + if ( arr[i] != 0 ) + { + exp = W_norm( arr[i] ); + } + if ( arr[i] != 0 ) + { + q = s_min( q, exp ); + } + } + return q; +} + +Word16 get_min_scalefactor( Word32 x, Word32 y ) +{ + Word16 scf_y; + Word16 scf = Q31; + move16(); + + test(); + if ( x == 0 && y == 0 ) + { + scf = 0; + move16(); + } + + if ( x != 0 ) + { + scf = norm_l( x ); + } + + scf_y = norm_l( y ); + if ( y != 0 ) + { + scf = s_min( scf_y, scf ); + } + + return scf; +} + + +Flag is_zero_arr( Word32 *arr, Word16 size ) +{ + FOR( Word16 i = 0; i < size; i++ ) + IF( arr[i] != 0 ) + { + return 0; + } + + return 1; +} + +Flag is_zero_arr16( Word16 *arr, Word16 size ) +{ + FOR( Word16 i = 0; i < size; i++ ) + IF( arr[i] != 0 ) + { + return 0; + } + + return 1; +} + +void Scale_sig64( + Word64 x[], /* i/o: signal to scale Qx */ + Word16 len, /* i : size of x[] Q0 */ + Word16 exp /* i : exponent: x = round(x << exp) Qx exp */ +) +{ + Word16 i; + assert( exp <= 63 && exp >= -63 ); + IF( exp == 0 ) + { + return; + } + + FOR( i = 0; i < len; i++ ) + { + /* saturation can occur here */ + x[i] = W_shl( x[i], exp ); + move64(); + } +} diff --git a/lib_enc/ivas_stereo_mdct_core_enc_fx.c b/lib_enc/ivas_stereo_mdct_core_enc_fx.c index 1346d634be51cb97cd2db41f3358a933674b211e..91b8726f0e181dd4aede46b0dc821b0d7b3f1250 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc_fx.c +++ b/lib_enc/ivas_stereo_mdct_core_enc_fx.c @@ -135,10 +135,8 @@ void stereo_mdct_core_enc_fx( { Word32 orig_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* MDCT output (L/R). */ Word32 *orig_spectrum_fx[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ - Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; - Word32 powerSpec_fx_tmp[CPE_CHANNELS][N_MAX]; /* This 32 bit buffer is created to preserve the precision for original separate Q calculation of powerSpec_fx buffer ( Related to 3gpp issue #1192 ) */ - Word32 *p_powerSpec_fx[CPE_CHANNELS]; - Word16 exp_powerSpec[CPE_CHANNELS][N_MAX + L_MDCT_OVLP_MAX]; + Word64 powerSpec64[CPE_CHANNELS][N_MAX]; + Word16 exp_powerSpec64[CPE_CHANNELS][NB_DIV]; Word32 powerSpecMsInv_long_fx[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ Word32 *powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV]; Word32 quantized_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ @@ -153,7 +151,7 @@ void stereo_mdct_core_enc_fx( Word32 *p_mdst_spectrum_long_fx[CPE_CHANNELS]; Word32 mdst_spectrum_long_fx[CPE_CHANNELS][N_MAX]; Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; - Word16 q_powSpec[MCT_MAX_CHANNELS], q_powSpecMsInv[MCT_MAX_CHANNELS], q_spec, tmp_s; + Word16 q_powSpecMsInv[MCT_MAX_CHANNELS], q_spec, tmp_s; Word16 tmp_q_powSpec[N_MAX], tmp_q_powSpecInv[N_MAX], *tmp_q_psi[2]; Word64 W_tmp; Encoder_State *st, **sts; @@ -184,12 +182,11 @@ void stereo_mdct_core_enc_fx( p_orig_spectrum_long_fx[ch] = orig_spectrum_long_fx[ch]; orig_spectrum_fx[ch][0] = orig_spectrum_long_fx[ch]; orig_spectrum_fx[ch][1] = orig_spectrum_long_fx[ch] + N_TCX10_MAX; - set16_fx( exp_powerSpec[ch], 0, N_MAX + L_MDCT_OVLP_MAX ); + set16_fx( exp_powerSpec64[ch], 0, NB_DIV ); } set16_fx( tmp_q_powSpecInv, 63, N_MAX ); set16_fx( tmp_q_powSpec, 63, N_MAX ); - set16_fx( q_powSpec, 31, MCT_MAX_CHANNELS ); set16_fx( q_powSpecMsInv, 31, MCT_MAX_CHANNELS ); tmp_q_psi[0] = tmp_q_powSpecInv; @@ -264,11 +261,10 @@ void stereo_mdct_core_enc_fx( inv_spectrum_fx[ch][1] = quantized_spectrum_fx[ch][1]; mdst_spectrum_fx[ch][0] = mdst_spectrum_long_fx[ch]; mdst_spectrum_fx[ch][1] = mdst_spectrum_long_fx[ch] + N_TCX10_MAX; + set64_fx( powerSpec64[ch], 0, N_MAX ); set32_fx( powerSpecMsInv_long_fx[ch], 0, N_MAX ); set32_fx( quantized_spectrum_long_fx[ch], 0, N_MAX ); set32_fx( mdst_spectrum_long_fx[ch], 0, N_MAX ); - set32_fx( powerSpec_fx[ch], 0, N_MAX ); - set32_fx( powerSpec_fx_tmp[ch], 0, N_MAX ); set32_fx( powerSpecMsInv_long_fx[ch], 0, N_MAX ); sts[ch]->hTcxEnc->tns_ms_flag[0] = 0; move16(); @@ -383,7 +379,7 @@ void stereo_mdct_core_enc_fx( } } - q_spec = sub( add( hdrm_min, q_spec ), 2 ); /* 2 guard bits to avoid over-flows (1 for stereo_coder_tcx_fx and other for power spectrum calculation )*/ + q_spec = sub( add( hdrm_min, q_spec ), 1 ); /* 1 guard bit to avoid over-flows in stereo_coder_tcx_fx */ FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -407,7 +403,8 @@ void stereo_mdct_core_enc_fx( /*--------------------------------------------------------------* * Power spectrum calculation *---------------------------------------------------------------*/ - Word16 length; + Word16 length, exp, shift1, shift2, norm; + Word32 mdct, mdst; FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -437,17 +434,13 @@ void stereo_mdct_core_enc_fx( IF( sts[ch]->hTcxEnc->tns_ms_flag[n] ) { + exp = add( s_max( mdst_spectrum_e[ch][n], sts[ch]->hTcxEnc->spectrum_e[n] ), 1 ); + shift1 = sub( mdst_spectrum_e[ch][n], exp ); + shift2 = sub( sts[ch]->hTcxEnc->spectrum_e[n], exp ); + /* power spectrum: MDCT^2 + MDST^2 */ FOR( i = 0; i < L_subframeTCX; i++ ) { - W_tmp = W_mac_32_32( W_mult_32_32( mdst_spectrum_fx[ch][n][i], mdst_spectrum_fx[ch][n][i] ), sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ); /* 2*q_spec+1 */ - tmp_s = W_norm( W_tmp ); - W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ - powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ - tmp_q_powSpec[( i + ( n * L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 - move32(); - move16(); - W_tmp = W_mac_32_32( W_mult_32_32( inv_mdst_spectrum_fx[ch][n][i], inv_mdst_spectrum_fx[ch][n][i] ), inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ); /* 2*q_spec+1 */ tmp_s = W_norm( W_tmp ); W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ @@ -455,7 +448,14 @@ void stereo_mdct_core_enc_fx( tmp_q_psi[n][i] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 move32(); move16(); + + mdst = L_shl( mdst_spectrum_fx[ch][n][i], shift1 ); // exp: exp + mdct = L_shl( sts[ch]->hTcxEnc->spectrum_fx[n][i], shift2 ); // exp: exp + powerSpec64[ch][i + n * L_subframeTCX] = W_mac_32_32( W_mult_32_32( mdct, mdct ), mdst, mdst ); // exp: 2*exp + move64(); } + exp_powerSpec64[ch][n] = shl( exp, 1 ); + move16(); } ELSE { @@ -493,53 +493,31 @@ void stereo_mdct_core_enc_fx( } /* power spectrum: MDCT^2 + MDST^2 */ - W_tmp = W_mult_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][0], sts[ch]->hTcxEnc->spectrum_fx[n][0] ); /* 2*q_spec+1 */ - tmp_s = W_norm( W_tmp ); - W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ - powerSpec_fx[ch][n * L_subframeTCX] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ - tmp_q_powSpec[n * L_subframeTCX] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 - move32(); - move16(); + mdct = L_shr( sts[ch]->hTcxEnc->spectrum_fx[n][0], 1 ); // exp: sts[ch]->hTcxEnc->spectrum_e[n]+1 + powerSpec64[ch][n * L_subframeTCX] = W_mult_32_32( mdct, mdct ); // exp: 2(sts[ch]->hTcxEnc->spectrum_e[n]+1) + move64(); FOR( i = 1; i < L_subframeTCX - 1; i++ ) { - Word32 mdst_fx = L_sub( sts[ch]->hTcxEnc->spectrum_fx[n][i + 1], sts[ch]->hTcxEnc->spectrum_fx[n][i - 1] ); /* An MDST estimate q_spec*/ - - W_tmp = W_mac_32_32( W_mult_32_32( mdst_fx, mdst_fx ), sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ); /* 2*q_spec+1 */ - tmp_s = W_norm( W_tmp ); - W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ - powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ - tmp_q_powSpec[( i + ( n * L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 - move32(); - move16(); + mdct = L_shr( sts[ch]->hTcxEnc->spectrum_fx[n][i], 1 ); // exp: sts[ch]->hTcxEnc->spectrum_e[n]+1 + mdst = L_sub( L_shr( sts[ch]->hTcxEnc->spectrum_fx[n][i + 1], 1 ), L_shr( sts[ch]->hTcxEnc->spectrum_fx[n][i - 1], 1 ) ); // exp: sts[ch]->hTcxEnc->spectrum_e[n]+1 + powerSpec64[ch][i + n * L_subframeTCX] = W_mac_32_32( W_mult_32_32( mdct, mdct ), mdst, mdst ); // exp: 2(sts[ch]->hTcxEnc->spectrum_e[n]+1) + move64(); } - W_tmp = W_mult_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1], sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1] ); /* 2*q_spec+1 */ - tmp_s = W_norm( W_tmp ); - W_tmp = W_shl( W_tmp, tmp_s ); /* 2*q_spec+1+tmp_s */ - powerSpec_fx[ch][( ( L_subframeTCX - 1 ) + ( n * L_subframeTCX ) )] = W_extract_h( W_tmp ); /* 2*q_spec+1+tmp_s-32 */ - tmp_q_powSpec[( ( L_subframeTCX - 1 ) + ( n * L_subframeTCX ) )] = sub( add( imult1616( q_spec, 2 ), tmp_s ), 31 ); // Q = 2 * q_spec + 1 + tmp_s - 32 - move32(); + mdct = L_shr( sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1], 1 ); // exp: sts[ch]->hTcxEnc->spectrum_e[n]+1 + powerSpec64[ch][L_subframeTCX - 1 + n * L_subframeTCX] = W_mult_32_32( mdct, mdct ); // exp: 2(sts[ch]->hTcxEnc->spectrum_e[n]+1) + move64(); + + exp_powerSpec64[ch][n] = shl( add( sts[ch]->hTcxEnc->spectrum_e[n], 1 ), 1 ); move16(); } } /* Aligning the Q-factors */ { - q_powSpec[ch] = Q31; q_powSpecMsInv[ch] = Q31; move16(); - move16(); - FOR( i = 0; i < N_MAX; i++ ) - { - IF( powerSpec_fx[ch][i] != 0 ) - { - q_powSpec[ch] = s_min( q_powSpec[ch], tmp_q_powSpec[i] ); - move16(); - exp_powerSpec[ch][i] = sub( Q31, tmp_q_powSpec[i] ); - move16(); - } - } FOR( n = 0; n < nSubframes; n++ ) { FOR( i = 0; i < L_subframeTCX; i++ ) @@ -551,16 +529,11 @@ void stereo_mdct_core_enc_fx( } } } - FOR( n = 0; n < nSubframes; n++ ) { FOR( i = 0; i < L_subframeTCX; i++ ) { powerSpecMsInv_fx[ch][n][i] = L_shr_sat( powerSpecMsInv_fx[ch][n][i], sub( tmp_q_psi[n][i], q_powSpecMsInv[ch] ) ); - /* Here precision is preserved for powerSpec_fx buffer by storing the fixed Q copy of same buffer in powerSpec_fx_tmp buffer */ - /* powerSpec_fx implementation has separate Q for each index, powerSpec_fx_tmp has all indices in same Q beyond this point */ - powerSpec_fx_tmp[ch][( i + ( n * L_subframeTCX ) )] = L_shr( powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )], sub( tmp_q_powSpec[i + ( n * L_subframeTCX )], q_powSpec[ch] ) ); /* q_powSpec */ - move32(); move32(); } } @@ -596,8 +569,9 @@ void stereo_mdct_core_enc_fx( * and quantization (0: tonal, 1: noise-like). * * Detect low pass if present. * *-----------------------------------------------------------*/ - ComputeSpectrumNoiseMeasure_fx( powerSpec_fx_tmp[ch], L_subframeTCX, i_mult( st->hTcxEnc->nmStartLine, idiv1616( L_subframeTCX, st->hTcxEnc->L_frameTCX ) ), - NE_32( imult3216( st->last_sr_core, st->L_frame ), imult3216( st->sr_core, st->L_frame_past ) ) || NE_16( st->last_core, TCX_20_CORE ), st->hTcxEnc->memQuantZeros, L_subframeTCX ); + ComputeSpectrumNoiseMeasure_ivas_fx( powerSpec64[ch], L_subframeTCX, i_mult( st->hTcxEnc->nmStartLine, idiv1616( L_subframeTCX, st->hTcxEnc->L_frameTCX ) ), + NE_32( imult3216( st->last_sr_core, st->L_frame ), imult3216( st->sr_core, st->L_frame_past ) ) || NE_16( st->last_core, TCX_20_CORE ), + st->hTcxEnc->memQuantZeros, L_subframeTCX ); } st->hTcxEnc->measuredBwRatio = ONE_IN_Q14; /* No bandwidth limit for the noise filling Q14*/ @@ -630,8 +604,48 @@ void stereo_mdct_core_enc_fx( IF( ( NE_16( hStereoMdct->mdct_stereo_mode[n], hStereoMdct->IGFStereoMode[n] ) || EQ_16( hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) ) && !hStereoMdct->isSBAStereoMode ) { IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS]; - p_powerSpec_fx[0] = powerSpec_fx_tmp[0]; - p_powerSpec_fx[1] = powerSpec_fx_tmp[1]; + Word32 powerSpec_fx[CPE_CHANNELS][N_MAX], *p_powerSpec_fx[CPE_CHANNELS]; + Word16 q_powSpec[CPE_CHANNELS]; + p_powerSpec_fx[0] = powerSpec_fx[0]; + p_powerSpec_fx[1] = powerSpec_fx[1]; + { + /* Copy powerSpec values from 64 bit buffer to 32 bit buffer */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + Word16 n1, nsub = 1; + length = sts[ch]->hTcxEnc->L_frameTCX; + move16(); + move16(); + IF( NE_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + length = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 ); + nsub = NB_DIV; + move16(); + } + IF( EQ_16( sts[ch]->last_core, ACELP_CORE ) ) + { + length = add( length, shr( length, 2 ) ); + } + exp = sub( exp_powerSpec64[ch][0], W_norm_arr( powerSpec64[ch], length ) ); + IF( EQ_16( nsub, 2 ) ) + { + exp = s_max( exp, sub( exp_powerSpec64[ch][1], W_norm_arr( powerSpec64[ch] + length, length ) ) ); + } + FOR( n1 = 0; n1 < nsub; n1++ ) + { + shift1 = sub( sub( exp_powerSpec64[ch][n1], exp ), 32 ); + FOR( i = 0; i < length; i++ ) + { + /* This doesn't result in saturation */ + powerSpec_fx[ch][i + n1 * length] = W_shl_sat_l( powerSpec64[ch][i + n1 * length], shift1 ); // exp: exp + move32(); + } + } + set32_fx( powerSpec_fx[ch] + length, 0, sub( N_MAX, length ) ); + q_powSpec[ch] = sub( 31, exp ); // exp: exp + move16(); + } + } hIGFEnc[0] = sts[0]->hIGFEnc; hIGFEnc[1] = sts[1]->hIGFEnc; @@ -677,6 +691,42 @@ void stereo_mdct_core_enc_fx( } ELSE { + Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; // each value has a different exponent + Word16 exp_powerSpec[CPE_CHANNELS][N_MAX + L_MDCT_OVLP_MAX]; + { + /* Copy powerSpec values from 64 bit buffer to 32 bit buffer */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + Word16 n1, nsub; + nsub = 1; + length = sts[ch]->hTcxEnc->L_frameTCX; + move16(); + move16(); + IF( NE_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + length = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 ); + nsub = NB_DIV; + move16(); + } + IF( EQ_16( sts[ch]->last_core, ACELP_CORE ) ) + { + length = add( length, shr( length, 2 ) ); + } + FOR( n1 = 0; n1 < nsub; n1++ ) + { + FOR( i = 0; i < length; i++ ) + { + norm = W_norm( powerSpec64[ch][i + n1 * length] ); + powerSpec_fx[ch][i + n1 * length] = W_extract_h( W_shl( powerSpec64[ch][i + n1 * length], norm ) ); // exp = exp_powerSpec64[ch][n1]-norm + exp_powerSpec[ch][i + n1 * length] = sub( exp_powerSpec64[ch][n1], norm ); + move32(); + move16(); + } + } + set32_fx( powerSpec_fx[ch] + length, 0, sub( N_MAX, length ) ); + set16_fx( exp_powerSpec[ch] + length, 0, sub( N_MAX + L_MDCT_OVLP_MAX, length ) ); + } + } FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; @@ -703,6 +753,42 @@ void stereo_mdct_core_enc_fx( } ELSE { + Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; // each value has a different exponent + Word16 exp_powerSpec[CPE_CHANNELS][N_MAX + L_MDCT_OVLP_MAX]; + { + /* Copy powerSpec values from 64 bit buffer to 32 bit buffer */ + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + Word16 n1, nsub; + nsub = 1; + length = sts[ch]->hTcxEnc->L_frameTCX; + move16(); + move16(); + IF( NE_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) ) + { + length = shr( sts[ch]->hTcxEnc->L_frameTCX, 1 ); + nsub = NB_DIV; + move16(); + } + IF( EQ_16( sts[ch]->last_core, ACELP_CORE ) ) + { + length = add( length, shr( length, 2 ) ); + } + FOR( n1 = 0; n1 < nsub; n1++ ) + { + FOR( i = 0; i < length; i++ ) + { + norm = W_norm( powerSpec64[ch][i + n1 * length] ); + powerSpec_fx[ch][i + n1 * length] = W_extract_h( W_shl( powerSpec64[ch][i + n1 * length], norm ) ); // exp = exp_powerSpec64[ch][n1]-norm + exp_powerSpec[ch][i + n1 * length] = sub( exp_powerSpec64[ch][n1], norm ); + move32(); + move16(); + } + } + set32_fx( powerSpec_fx[ch] + length, 0, sub( N_MAX, length ) ); + set16_fx( exp_powerSpec[ch] + length, 0, sub( N_MAX + L_MDCT_OVLP_MAX, length ) ); + } + } FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index 51e9849c7d6654a2e70aa872e4da3f61d42bdccf..d6532b207ae1558aa79c20ed75f88e56466df7d5 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -1498,6 +1498,14 @@ void ComputeSpectrumNoiseMeasure_fx( const Word32 *powerSpec, Word8 *noiseFlags, Word16 lowpassLine ); +void ComputeSpectrumNoiseMeasure_ivas_fx( Word64 *powerSpec, /* Qx */ + Word16 L_frame, /* Q0 */ + Word16 startLine, /* Q0 */ + Word8 resetMemory, /* Q0 */ + Word8 *noiseFlags, /* Q0 */ + Word16 lowpassLine /* Q0 */ +); + void lpc_quantization_fx( Encoder_State *st, const Word16 lsp[], /* Q15 */ diff --git a/lib_enc/tcx_utils_enc_fx.c b/lib_enc/tcx_utils_enc_fx.c index ad1720665dd6cc3d17842d06a682ae0d895ea4d0..46f83c094bb944d1d67d9c28e25c3322ca1c6a75 100644 --- a/lib_enc/tcx_utils_enc_fx.c +++ b/lib_enc/tcx_utils_enc_fx.c @@ -172,6 +172,117 @@ void ComputeSpectrumNoiseMeasure_fx( const Word32 *powerSpec, } } +void ComputeSpectrumNoiseMeasure_ivas_fx( Word64 *powerSpec, /* Qx */ + Word16 L_frame, /* Q0 */ + Word16 startLine, /* Q0 */ + Word8 resetMemory, /* Q0 */ + Word8 *noiseFlags, /* Q0 */ + Word16 lowpassLine /* Q0 */ +) +{ + Word16 i, lastTone, j, exp; + Word32 c; + Word64 s, temp; + + IF( resetMemory != 0 ) + { + FOR( i = 0; i < lowpassLine; i++ ) + { + noiseFlags[i] = 0; + move16(); + } + } + + FOR( i = lowpassLine; i < L_frame; i++ ) + { + noiseFlags[i] = 1; + move16(); + } + + test(); + IF( powerSpec != NULL && LT_16( add( startLine, 6 ), L_frame ) ) + { + lastTone = 0; + move16(); + + /* noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ + i = sub( startLine, 1 ); + /* s = powerSpec[i - 7] + powerSpec[i - 6] + powerSpec[i - 5] + + powerSpec[i - 4] + powerSpec[i - 3] + powerSpec[i - 2] + + powerSpec[i - 1] + powerSpec[i] + powerSpec[i + 1] + + powerSpec[i + 2] + powerSpec[i + 3] + powerSpec[i + 4] + + powerSpec[i + 5] + powerSpec[i + 6] + powerSpec[i + 7]; */ + + s = powerSpec[i - 7]; // Qx + move64(); + FOR( j = -6; j < 8; j++ ) + { + s = W_add( s, powerSpec[i + j] ); // Qx + } + + FOR( i = i + 1; i < lowpassLine - 7; i++ ) + { + /* c = powerSpec[i - 1] + powerSpec[i] + powerSpec[i + 1]; */ + temp = W_add( W_add( powerSpec[i - 1], powerSpec[i] ), powerSpec[i + 1] ); + exp = W_norm( temp ); + c = W_extract_h( W_shl( temp, exp ) ); // Qx+exp-32 + + /* s += powerSpec[i + 7] - powerSpec[i - 8]; */ + s = W_sub( s, powerSpec[i - 8] ); // Qx + s = W_add( s, powerSpec[i + 7] ); // Qx + + /* ( 1.75f - 0.5f * noiseFlags[i] ) * c */ + temp = W_mult_32_32( c, L_msu0( 28672 /* 1.75 in Q14*/, 8192 /* 0.5 in Q14 */, noiseFlags[i] ) ); // Qx+exp-32+14+1 = Qx+exp-17 + + IF( GE_64( W_shl( s, sub( exp, Q17 ) ), temp ) /* s >= ( 1.75f - 0.5f * noiseFlags[i] ) * c */ ) // Qx+exp-17 + { + noiseFlags[i] = 1; + move16(); + } + ELSE + { + noiseFlags[i] = 0; + lastTone = i; + move16(); + move16(); + } + } + + /* lower L_frame*startRatio lines are tonal (0), upper 7 lines are processed separately */ + FOR( ; i < lowpassLine - 1; i++ ) + { + /* c = powerSpec[i - 1] + powerSpec[i] + powerSpec[i + 1]; */ + temp = W_add( W_add( powerSpec[i - 1], powerSpec[i] ), powerSpec[i + 1] ); + exp = W_norm( temp ); + c = W_extract_h( W_shl( temp, exp ) ); // Qx+exp-32 + + /* ( 1.75f - 0.5f * noiseFlags[i] ) * c */ + temp = W_mult_32_32( c, L_msu0( 28672 /* 1.75 in Q14*/, 8192 /* 0.5 in Q14 */, noiseFlags[i] ) ); // Qx+exp-32+14+1 = Qx+exp-17 + + IF( GE_64( W_shl( s, sub( exp, Q17 ) ), temp ) /* s >= ( 1.75f - 0.5f * noiseFlags[i] ) * c */ ) // Qx+exp-17 + { + noiseFlags[i] = 1; + move16(); + } + ELSE + { + noiseFlags[i] = 0; + lastTone = i; + move16(); + move16(); + } + } + noiseFlags[i] = 1; /* uppermost line is defined as noise-like (1) */ + move16(); + + if ( lastTone > 0 ) /* spread uppermost tonal line one line upward */ + { + noiseFlags[lastTone + 1] = 0; + move16(); + } + } +} + static void detectLowpassFac( const Word32 *powerSpec, Word16 powerSpec_e, Word16 L_frame, Word8 rectWin, Word16 *pLpFac, Word16 lowpassLine ) { Word16 i, tmp;