From 49860cd71d6f2aebadb7fcf801b01ef993066901 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 14 Nov 2025 16:12:48 +0000 Subject: [PATCH 01/24] Optimize ivas_filter_process_fx part 1. --- lib_com/ivas_filters_fx.c | 97 +++++++++++++++++++++++++++++ lib_com/ivas_prot_fx.h | 7 +++ lib_com/ivas_stat_com.h | 4 ++ lib_com/ivas_transient_det_fx.c | 77 ++++++++++++++++++++++- lib_com/ivas_transient_det_fx.py | 98 ++++++++++++++++++++++++++++++ lib_com/options.h | 6 ++ lib_dec/ivas_ism_metadata_dec_fx.c | 2 +- 7 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 lib_com/ivas_transient_det_fx.py diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 02e7b272a..e3920d649 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -43,6 +43,7 @@ *------------------------------------------------------------------------------------------*/ static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); +static void ivas_iir_2_filter_fixed_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); /*-----------------------------------------------------------------------------------------* @@ -145,6 +146,10 @@ void ivas_filters_init_fx( move16(); } +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->q_diff = 0; +#endif + return; } @@ -285,3 +290,95 @@ static void ivas_iir_2_filter_fx( return; } + +void ivas_filter_process_fixed_fx( + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ + const Word16 length, /* i : filter order */ + Word16 *q_in_out ) +{ + SWITCH( filter_state->order ) + { + case IVAS_FILTER_ORDER_1: + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_in_out ); + /* Scale pIn_Out_fx back to input Q */ + BREAK; + case IVAS_FILTER_ORDER_4: + /* biquad-1 */ + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_in_out ); + /* biquad-2 */ + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q_in_out ); + /* Scale pIn_Out_fx back to input Q */ + BREAK; + default: + BREAK; + } + + return; +} + +static void ivas_iir_2_filter_fixed_fx( + ivas_filters_process_state_t *filter_state, + Word32 *pIn_Out_fx, // Q(31-*pIn_Out_e) + const Word16 length, + const Word16 stage, + Word16 *q_in_out ) +{ + Word16 i, j; + + Word32 *pIn_fx = pIn_Out_fx; + Word32 *pOut_fx = pIn_Out_fx; + Word32 tmp_pIn_buf_i_fx; + Word16 tmp_pIn_buf_i_e; + + Word32 L_tmp_prod, L_tmp; + Word16 L_prod_e, L_tmp_e; + + Word16 exp; + Word16 q_in = *q_in_out; + Word16 q_out = add( filter_state->q_diff, q_in ); + *q_in_out = q_out; + + FOR( i = 0; i < length; i++ ) + { + tmp_pIn_buf_i_fx = pIn_fx[i]; + move32(); + tmp_pIn_buf_i_e = q_in; + move16(); + + L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][0], pIn_fx[i] ); // Q31 -(q_in+ filter_state->num_e[stage][0]) + L_prod_e = add( q_in, filter_state->num_e[stage][0] ); + + pOut_fx[i] = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][0], filter_state->state_e[stage][0], L_tmp_prod, L_prod_e, &exp ); // Q31 - pIn_Out_e[i] + move32(); + + FOR( j = 1; j < filter_state->filt_len; j++ ) + { + L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][j], tmp_pIn_buf_i_fx ); // Q31-L_prod_e + L_prod_e = add( filter_state->num_e[stage][j], tmp_pIn_buf_i_e ); + + L_tmp = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][j], filter_state->state_e[stage][j], L_tmp_prod, L_prod_e, &L_tmp_e ); // Q31 - L_tmp_e + + L_tmp_prod = Mpy_32_32( filter_state->den_fx[stage][j], pOut_fx[i] ); // Q31 - ( pIn_Out_e[i]+filter_state->den_e[stage][j] ) + L_prod_e = add( exp, filter_state->den_e[stage][j] ); + + filter_state->state_fx[stage][j - 1] = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, L_negate( L_tmp_prod ), L_prod_e, &filter_state->state_e[stage][j - 1] ); // Q31 - filter_state->state_e[stage][j - 1] + move32(); + /*In case when exponent is less than -31 the value is very small and negligible hence resetting it to zero to avoid exponent overflow*/ + IF( LT_16( filter_state->state_e[stage][j - 1], -31 ) ) + { + filter_state->state_fx[stage][j - 1] = 0; + move32(); + filter_state->state_e[stage][j - 1] = 0; + move16(); + } + } + + + Word16 shift = ( 31 - exp ) - q_out; + pOut_fx[i] = L_shr_r_sat( pOut_fx[i], shift ); + move32(); + } + + return; +} diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index b75b38137..07f738592 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3817,6 +3817,13 @@ void ivas_filter_process_exp_fx( Word16 *pIn_Out_e ); +void ivas_filter_process_fixed_fx( + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ + const Word16 length, /* i : filter order */ + Word16 *q_in_out +); + ivas_error ivas_osba_enc_open_fx( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 65a081c9c..117325fff 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -661,6 +661,10 @@ typedef struct ivas_filters_process_state_t Word16 den_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 state_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; +#ifdef OPT_2239_IVAS_FILTER_PROCESS + Word16 q_diff; // q_diff = q_out - q_in -> q_out = q_diff + q_in +#endif + } ivas_filters_process_state_t; diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index 39dee9314..4239c7c1b 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -382,7 +382,6 @@ void ivas_td_decorr_get_ducking_gains_fx( { Word16 i; Word32 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; - Word16 e_fast_e[L_FRAME48k], e_slow_e[L_FRAME48k]; Word32 in_duck_gain = hTranDet->in_duck_gain; /*Q30*/ move32(); Word32 out_duck_gain = hTranDet->out_duck_gain; /*Q30*/ @@ -396,6 +395,80 @@ void ivas_td_decorr_get_ducking_gains_fx( Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ + +#ifdef OPT_2239_IVAS_FILTER_PROCESS + /* env hpf */ + Word16 q_fast = Q11; + + ivas_filter_process_fixed_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, &q_fast ); + + Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; + Word16 env_eps_q = Q31; + + Word16 q_diff = sub( q_fast, env_eps_q ); + q_fast = s_min( q_fast, env_eps_q ); + + if ( q_diff >= 0 ) + { + for ( i = 0; i < frame_len; i++ ) + { + e_fast_fx[i] = L_add( L_abs( L_shr( e_fast_fx[i], q_diff ) ), env_eps_fx ); + move32(); + e_slow_fx[i] = e_fast_fx[i]; + move32(); + } + } + else + { + env_eps_fx = L_shl( env_eps_fx, q_diff ); + for ( i = 0; i < frame_len; i++ ) + { + e_fast_fx[i] = L_add( L_abs( e_fast_fx[i] ), env_eps_fx ); + move32(); + e_slow_fx[i] = e_fast_fx[i]; + move32(); + } + } + + Word16 q_slow = q_fast; + + /* env fast*/ + ivas_filter_process_fixed_fx( &hTranDet->env_fast, e_fast_fx, frame_len, &q_fast ); + + /* env slow */ + ivas_filter_process_fixed_fx( &hTranDet->env_slow, e_slow_fx, frame_len, &q_slow ); + + + IF( tdet_flag ) + { + FOR( i = 0; i < frame_len; i++ ) + { + in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, e_slow_fx[i], 31 - q_slow, e_fast_fx[i], 31 - q_fast, duck_mult_fac ); /*Q30*/ + pIn_duck_gains[i] = in_duck_gain; /*Q30*/ + move32(); + } + hTranDet->in_duck_gain = in_duck_gain; /*Q30*/ + move32(); + } + ELSE + { + FOR( i = 0; i < frame_len; i++ ) + { + in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, e_slow_fx[i], 31 - q_slow, e_fast_fx[i], 31 - q_fast, duck_mult_fac ); /*Q30*/ + pIn_duck_gains[i] = in_duck_gain; /*Q30*/ + move32(); + out_duck_gain = ivas_calc_duck_gain_fx( out_duck_gain, out_duck_coeff, e_fast_fx[i], 31 - q_fast, e_slow_fx[i], 31 - q_slow, duck_mult_fac ); /*Q30*/ + pOut_duck_gains[i] = out_duck_gain; /*Q30*/ + move32(); + } + hTranDet->in_duck_gain = in_duck_gain; /*Q30*/ + move32(); + hTranDet->out_duck_gain = out_duck_gain; /*Q30*/ + move32(); + } +#else + Word16 e_fast_e[L_FRAME48k], e_slow_e[L_FRAME48k]; + set16_fx( e_fast_e, 31 - Q11, L_FRAME48k ); /* env hpf */ @@ -446,6 +519,8 @@ void ivas_td_decorr_get_ducking_gains_fx( hTranDet->out_duck_gain = out_duck_gain; /*Q30*/ move32(); } +#endif + return; } diff --git a/lib_com/ivas_transient_det_fx.py b/lib_com/ivas_transient_det_fx.py new file mode 100644 index 000000000..e5b298998 --- /dev/null +++ b/lib_com/ivas_transient_det_fx.py @@ -0,0 +1,98 @@ +import numpy as np +from scipy import signal +import matplotlib.pyplot as plt + +def generate_biquad_butterworth_coeffs(cutoff_freq, fs, order=2, ftype='lowpass', output='ba'): + Wn = cutoff_freq + if output == 'sos': + sos_coeffs = signal.butter(order, Wn, btype=ftype, analog=False, output='sos', fs=fs) + return sos_coeffs + elif output == 'ba': + b_coeffs, a_coeffs = signal.butter(order, Wn, btype=ftype, analog=False, output='ba', fs=fs) + return b_coeffs, a_coeffs + else: + raise ValueError("Output format must be 'sos' or 'ba'") + +def plot_biquad_frequency_response(b, a, fs): + w, h = signal.freqz(b, a, fs=fs) + magnitude_db = 20 * np.log10(np.abs(h)) + phase_degrees = np.unwrap(np.angle(h)) * 180 / np.pi + + fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, tight_layout=True) + + ax1.plot(w, magnitude_db, 'b') + ax1.set_ylabel('Magnitude (dB)', color='b') + ax1.set_xlabel('Frequency (Hz)') + ax1.grid() + + ax2.plot(w, phase_degrees, 'g') + ax2.set_ylabel('Phase (degrees)', color='g') + ax2.set_xlabel('Frequency (Hz)') + ax2.grid() + + plt.show() + +def max_abs_output_biquad(b, a, n_samples=10000): + if a[0] != 1.0: + b = np.array(b) / a[0] + a = np.array(a) / a[0] + a[0] = 1.0 + + impulse_input = np.zeros(n_samples) + impulse_input[0] = 1.0 + + impulse_response = signal.lfilter(b, a, impulse_input) + + max_gain = np.sum(np.abs(impulse_response)) + + return max_gain + +# sampling_rate = 44100.0 # Hz +# cutoff_frequency = 5000.0 # Hz +# b_coeffs,a_coeffs = generate_biquad_butterworth_coeffs(cutoff_frequency, sampling_rate) +# plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) + +# # Calculate the maximum gain +# gain = max_abs_output_biquad(b_coeffs, a_coeffs) +# print(f"Numerator coefficients (b): {b_coeffs}") +# print(f"Denominator coefficients (a): {a_coeffs}") +# print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") + + +IVAS_C_HPF_48k = 0.675231906655777 +IVAS_C_HPF_32k = 0.554854910159853 +IVAS_C_HPF_16k = 0.307863971328499 + +IVAS_C_FAST_48k = 0.995842001845110 +IVAS_C_FAST_32k = 0.993769490623395 +IVAS_C_FAST_16k = 0.987577800493881 + +IVAS_C_SLOW_48k = 0.999739617238810 +IVAS_C_SLOW_32k = 0.999609451284012 +IVAS_C_SLOW_16k = 0.999219055096324 + +#env_hpf +sampling_rate = 48000.0 # Hz +b_coeffs = [ +IVAS_C_HPF_48k, -IVAS_C_HPF_48k, 0.0 ] +a_coeffs = [ 1.0, -IVAS_C_HPF_48k, 0.0 ] +plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) +gain = max_abs_output_biquad(b_coeffs, a_coeffs) +print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") + +#env_fast +sampling_rate = 48000.0 # Hz +b_coeffs = [ 1.0 - IVAS_C_FAST_48k, 0.0, 0.0 ] +a_coeffs = [ 1.0, -IVAS_C_FAST_48k, 0.0 ] +plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) +gain = max_abs_output_biquad(b_coeffs, a_coeffs) +print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") + +#env_slow +sampling_rate = 48000.0 # Hz +b_coeffs = [ 1.0 - IVAS_C_SLOW_48k, 0.0, 0.0 ] +a_coeffs = [ 1.0, -IVAS_C_SLOW_48k, 0.0 ] +plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) +gain = max_abs_output_biquad(b_coeffs, a_coeffs) +print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") + + diff --git a/lib_com/options.h b/lib_com/options.h index b1d98931d..0b6813e1e 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -167,4 +167,10 @@ /* #################### End BASOP porting switches ############################ */ +/* #################### Start BASOP optimization switches ############################ */ + +#define OPT_2239_IVAS_FILTER_PROCESS /* Dolby: Issue 2239, optimize ivas_filter_process_fx. */ + +/* #################### End BASOP optimization switches ############################ */ + #endif diff --git a/lib_dec/ivas_ism_metadata_dec_fx.c b/lib_dec/ivas_ism_metadata_dec_fx.c index 54cc5da15..4d3c06b9c 100644 --- a/lib_dec/ivas_ism_metadata_dec_fx.c +++ b/lib_dec/ivas_ism_metadata_dec_fx.c @@ -30,7 +30,6 @@ *******************************************************************************************************/ -#include "move.h" #include #include "options.h" #include "ivas_cnst.h" @@ -40,6 +39,7 @@ #include "ivas_stat_enc.h" #include #include "wmc_auto.h" +#include "move.h" #include "ivas_prot_fx.h" -- GitLab From 2cf229bed52c15b143f6807d6db4950898d39012 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Mon, 17 Nov 2025 16:34:09 +0000 Subject: [PATCH 02/24] Optimize ivas_filter_process_fx part 2. --- lib_com/ivas_filters_fx.c | 133 ++++++++++++++++++++++++-------- lib_com/ivas_prot_fx.h | 8 +- lib_com/ivas_stat_com.h | 4 + lib_com/ivas_transient_det_fx.c | 39 ++++++++++ 4 files changed, 148 insertions(+), 36 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index e3920d649..7768de77f 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -93,6 +93,10 @@ void ivas_filters_init_fx( move16(); move16(); move16(); + + filter_state->state64_fx[0][0] = 0; + filter_state->state64_fx[0][1] = 0; + filter_state->state64_fx[0][2] = 0; } ELSE { @@ -144,6 +148,13 @@ void ivas_filters_init_fx( move16(); move16(); move16(); + + filter_state->state64_fx[0][0] = 0; + filter_state->state64_fx[0][1] = 0; + filter_state->state64_fx[0][2] = 0; + filter_state->state64_fx[1][0] = 0; + filter_state->state64_fx[1][1] = 0; + filter_state->state64_fx[1][2] = 0; } #ifdef OPT_2239_IVAS_FILTER_PROCESS @@ -293,22 +304,18 @@ static void ivas_iir_2_filter_fx( void ivas_filter_process_fixed_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ + Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ const Word16 length, /* i : filter order */ - Word16 *q_in_out ) + Word16 *q_factor ) { SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_in_out ); - /* Scale pIn_Out_fx back to input Q */ + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_factor ); BREAK; case IVAS_FILTER_ORDER_4: - /* biquad-1 */ - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_in_out ); - /* biquad-2 */ - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q_in_out ); - /* Scale pIn_Out_fx back to input Q */ + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_factor ); + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q_factor ); BREAK; default: BREAK; @@ -317,66 +324,128 @@ void ivas_filter_process_fixed_fx( return; } +#if 0 +static void __check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ); + +static void __check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ) +{ + Word16 cq, eq, shift, q_diff; + Word64 cfx, efx; + + shift = W_norm( computed_fx ); + cfx = W_shl( computed_fx, shift ); + cq = add( computed_q, shift ); + + shift = W_norm( expected_fx ); + efx = W_shl( expected_fx, shift ); + eq = add( expected_q, shift ); + + q_diff = cq - eq; + shift = abs( q_diff ); + if ( q_diff >= 0 ) + { + cfx = shift < 64 ? W_shr( cfx, shift ) : 0; + } + else + { + efx = shift < 64 ? W_shr( efx, shift ) : 0; + } + Word64 error = llabs( cfx - efx ); + if ( error > ( ( (Word64) 1 ) << 60 ) ) + { + assert( false ); + } +} + +Word64 __to_state64( Word16 q, Word32 state_fx, Word16 state_e ) +{ + Word16 q_diff = q - ( 31 - state_e ); + Word64 state; + if ( q_diff <= -32 ) + state = 0; + else + state = W_shl( (Word64) state_fx, q_diff ); + // __check( state, q, state_fx, 31 - state_e ); + return state; +} +#endif + static void ivas_iir_2_filter_fixed_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, // Q(31-*pIn_Out_e) const Word16 length, const Word16 stage, - Word16 *q_in_out ) + Word16 *q_factor ) { Word16 i, j; Word32 *pIn_fx = pIn_Out_fx; Word32 *pOut_fx = pIn_Out_fx; Word32 tmp_pIn_buf_i_fx; - Word16 tmp_pIn_buf_i_e; Word32 L_tmp_prod, L_tmp; Word16 L_prod_e, L_tmp_e; - Word16 exp; - Word16 q_in = *q_in_out; - Word16 q_out = add( filter_state->q_diff, q_in ); - *q_in_out = q_out; + Word16 q_in, q_out; + Word16 e_in, e_out; + q_in = *q_factor; + *q_factor = q_out = q_in + filter_state->q_diff; + + // Word64 shift, tmp_prod, tmp, out64; FOR( i = 0; i < length; i++ ) { tmp_pIn_buf_i_fx = pIn_fx[i]; move32(); - tmp_pIn_buf_i_e = q_in; + e_in = 31 - q_in; move16(); - L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][0], pIn_fx[i] ); // Q31 -(q_in+ filter_state->num_e[stage][0]) - L_prod_e = add( q_in, filter_state->num_e[stage][0] ); + L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][0], pIn_fx[i] ); // Q31 -(pIn_Out_e[i]+ filter_state->num_e[stage][0]) + L_prod_e = add( 31 - q_in, filter_state->num_e[stage][0] ); + + // shift = 31 - filter_state->num_e[stage][0] + q_in - ( q_out + 32 ); + // tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], pIn_fx[i] ), shift ); + // __check( tmp_prod, q_out + 32, L_tmp_prod, 31 - L_prod_e ); - pOut_fx[i] = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][0], filter_state->state_e[stage][0], L_tmp_prod, L_prod_e, &exp ); // Q31 - pIn_Out_e[i] + e_out = 31 - q_in; + pOut_fx[i] = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][0], filter_state->state_e[stage][0], L_tmp_prod, L_prod_e, &e_out ); // Q31 - pIn_Out_e[i] move32(); + // out64 = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + // __check( out64, q_out + 32, pOut_fx[i], 31 - e_out ); + // pOut_fx[i] = (Word32)(out64 >> 32); + FOR( j = 1; j < filter_state->filt_len; j++ ) { L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][j], tmp_pIn_buf_i_fx ); // Q31-L_prod_e - L_prod_e = add( filter_state->num_e[stage][j], tmp_pIn_buf_i_e ); + L_prod_e = add( filter_state->num_e[stage][j], e_in ); + + // shift = 31 - filter_state->num_e[stage][j] + q_in - ( q_out + 32 ); + // tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], tmp_pIn_buf_i_fx ), shift ); + // __check( tmp_prod, q_out + 32, L_tmp_prod, 31 - L_prod_e ); L_tmp = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][j], filter_state->state_e[stage][j], L_tmp_prod, L_prod_e, &L_tmp_e ); // Q31 - L_tmp_e + // tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + // __check( tmp, q_out + 32, L_tmp, 31 - L_tmp_e ); + L_tmp_prod = Mpy_32_32( filter_state->den_fx[stage][j], pOut_fx[i] ); // Q31 - ( pIn_Out_e[i]+filter_state->den_e[stage][j] ) - L_prod_e = add( exp, filter_state->den_e[stage][j] ); + L_prod_e = add( e_out, filter_state->den_e[stage][j] ); + + // shift = 31 - filter_state->den_e[stage][j] + q_out - ( q_out + 32 ); + // tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], pOut_fx[i] ), shift ); + // __check( tmp_prod, q_out + 32, L_tmp_prod, 31 - L_prod_e ); filter_state->state_fx[stage][j - 1] = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, L_negate( L_tmp_prod ), L_prod_e, &filter_state->state_e[stage][j - 1] ); // Q31 - filter_state->state_e[stage][j - 1] move32(); - /*In case when exponent is less than -31 the value is very small and negligible hence resetting it to zero to avoid exponent overflow*/ - IF( LT_16( filter_state->state_e[stage][j - 1], -31 ) ) - { - filter_state->state_fx[stage][j - 1] = 0; - move32(); - filter_state->state_e[stage][j - 1] = 0; - move16(); - } - } + // filter_state->state64_fx[stage][j - 1] = W_add( tmp, tmp_prod ); + // __check( filter_state->state64_fx[stage][j - 1], q_out + 32, filter_state->state_fx[stage][j - 1], 31 - filter_state->state_e[stage][j - 1] ); + + // filter_state->state64_fx[stage][j - 1] = __to_state64( q_out + 32, filter_state->state_fx[stage][j - 1], filter_state->state_e[stage][j - 1] ); + } - Word16 shift = ( 31 - exp ) - q_out; - pOut_fx[i] = L_shr_r_sat( pOut_fx[i], shift ); + pOut_fx[i] = L_shr_r_sat( pOut_fx[i], sub( sub( 31, q_out ), e_out ) ); // Q(31-pIn_Out_e[i]) -> Q(q_factor) move32(); } diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 07f738592..9f91e6c9b 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3818,10 +3818,10 @@ void ivas_filter_process_exp_fx( ); void ivas_filter_process_fixed_fx( - ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ - const Word16 length, /* i : filter order */ - Word16 *q_in_out + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word32 *pIn_Out_fx, /* i : signal subject to filtering */ + const Word16 length, /* i : filter order */ + Word16 *q_factor ); ivas_error ivas_osba_enc_open_fx( diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 117325fff..4f7f2bb66 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -663,6 +663,7 @@ typedef struct ivas_filters_process_state_t #ifdef OPT_2239_IVAS_FILTER_PROCESS Word16 q_diff; // q_diff = q_out - q_in -> q_out = q_diff + q_in + Word32 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #endif } ivas_filters_process_state_t; @@ -677,6 +678,9 @@ typedef struct ivas_trans_det_state_t ivas_filters_process_state_t env_hpf; ivas_filters_process_state_t env_fast; ivas_filters_process_state_t env_slow; + ivas_filters_process_state_t test_env_hpf; + ivas_filters_process_state_t test_env_fast; + ivas_filters_process_state_t test_env_slow; Word32 in_duck_coeff; Word32 out_duck_coeff; Word32 in_duck_gain; diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index 4239c7c1b..c81f3d3f6 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -225,6 +225,9 @@ static void ivas_transient_det_init( ivas_filters_init_fx( &hTranDet->env_hpf, (const Word32 *) filt_coeff_arr_fx[0], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); ivas_filters_init_fx( &hTranDet->env_fast, (const Word32 *) filt_coeff_arr_fx[1], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); ivas_filters_init_fx( &hTranDet->env_slow, (const Word32 *) filt_coeff_arr_fx[2], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); + ivas_filters_init_fx( &hTranDet->test_env_hpf, (const Word32 *) filt_coeff_arr_fx[0], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); + ivas_filters_init_fx( &hTranDet->test_env_fast, (const Word32 *) filt_coeff_arr_fx[1], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); + ivas_filters_init_fx( &hTranDet->test_env_slow, (const Word32 *) filt_coeff_arr_fx[2], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); hTranDet->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC; /*Q29*/ move32(); @@ -372,6 +375,31 @@ static Word32 ivas_calc_duck_gain_fx( * Calculate in/out ducking gains *-----------------------------------------------------------------------------------------*/ +#ifndef OPT_2239_IVAS_FILTER_PROCESS +static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ); + +static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ) +{ + Word32 cfx, efx; + Word16 q_diff = computed_q - expected_q; + if ( q_diff >= 0 ) + { + cfx = L_shr( computed_fx, +q_diff ); + efx = expected_fx; + } + else + { + cfx = computed_fx; + efx = L_shr( expected_fx, -q_diff ); + } + Word32 error = abs( cfx - efx ); + if ( error >= ( 1 << 22 ) ) + { + assert( false ); + } +} +#endif + void ivas_td_decorr_get_ducking_gains_fx( ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ Word32 *pIn_pcm, /*Q11*/ @@ -475,6 +503,17 @@ void ivas_td_decorr_get_ducking_gains_fx( ivas_filter_process_exp_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, e_fast_e ); + // Word32 test_e_fast_fx[L_FRAME48k]; + // Word16 q_fast = Q11; + // Copy32( pIn_pcm, test_e_fast_fx, frame_len ); /*Q11*/ + // ivas_filter_process_fixed_fx( &hTranDet->test_env_hpf, test_e_fast_fx, frame_len, &q_fast ); + + // for ( i = 0; i < frame_len; i++ ) + // { + // check(test_e_fast_fx[i],q_fast,e_fast_fx[i],31-e_fast_e[i]); + // } + + FOR( i = 0; i < frame_len; i++ ) { // e_fast_fx[i] = L_add( L_abs( e_fast_fx[i] ), L_shr( IVAS_TDET_PARM_ENV_EPS_fx, q_factor_diff ) ); /*Q14*/ -- GitLab From 43a92380470d8539d72a70a7465d37499c2ba92e Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Tue, 18 Nov 2025 07:53:39 +0000 Subject: [PATCH 03/24] Optimize ivas_filter_process_fx part 3. --- lib_com/ivas_filters_fx.c | 188 ++++++++++++-------------------- lib_com/ivas_prot_fx.h | 2 +- lib_com/ivas_stat_com.h | 6 +- lib_com/ivas_transient_det_fx.c | 94 ++++++++++++---- 4 files changed, 151 insertions(+), 139 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 7768de77f..cdbb937cc 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -43,7 +43,7 @@ *------------------------------------------------------------------------------------------*/ static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); -static void ivas_iir_2_filter_fixed_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); +static void ivas_iir_2_filter_fixed_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); /*-----------------------------------------------------------------------------------------* @@ -79,6 +79,12 @@ void ivas_filters_init_fx( move32(); move16(); move16(); +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->num_q[IVAS_FILTER_STAGE_0][i] = Q30; + filter_state->den_q[IVAS_FILTER_STAGE_0][i] = Q30; + move16(); + move16(); +#endif } filter_state->state_fx[0][0] = 0; @@ -94,15 +100,27 @@ void ivas_filters_init_fx( move16(); move16(); - filter_state->state64_fx[0][0] = 0; - filter_state->state64_fx[0][1] = 0; - filter_state->state64_fx[0][2] = 0; +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; + move64(); + move64(); + move64(); + filter_state->state64_q[IVAS_FILTER_STAGE_0] = Q30; + move16(); +#endif } ELSE { filter_state->filt_len = IVAS_BIQUAD_FILT_LEN; move16(); +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->state64_q[IVAS_FILTER_STAGE_0] = 63; + filter_state->state64_q[IVAS_FILTER_STAGE_1] = 63; +#endif + FOR( i = 0; i < IVAS_BIQUAD_FILT_LEN; i++ ) { @@ -122,6 +140,24 @@ void ivas_filters_init_fx( move16(); move16(); move16(); +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->num_q[IVAS_FILTER_STAGE_0][i] = sub( 31, filt_coeff_e[i + 0 * IVAS_BIQUAD_FILT_LEN] ); + filter_state->den_q[IVAS_FILTER_STAGE_0][i] = sub( 31, filt_coeff_e[i + 1 * IVAS_BIQUAD_FILT_LEN] ); + filter_state->num_q[IVAS_FILTER_STAGE_1][i] = sub( 31, filt_coeff_e[i + 2 * IVAS_BIQUAD_FILT_LEN] ); + filter_state->den_q[IVAS_FILTER_STAGE_1][i] = sub( 31, filt_coeff_e[i + 3 * IVAS_BIQUAD_FILT_LEN] ); + move16(); + move16(); + move16(); + move16(); + filter_state->state64_q[IVAS_FILTER_STAGE_0] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_0], filter_state->num_q[IVAS_FILTER_STAGE_0][i] ); + filter_state->state64_q[IVAS_FILTER_STAGE_0] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_0], filter_state->den_q[IVAS_FILTER_STAGE_0][i] ); + filter_state->state64_q[IVAS_FILTER_STAGE_1] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_1], filter_state->num_q[IVAS_FILTER_STAGE_1][i] ); + filter_state->state64_q[IVAS_FILTER_STAGE_1] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_1], filter_state->den_q[IVAS_FILTER_STAGE_1][i] ); + move16(); + move16(); + move16(); + move16(); +#endif } filter_state->state_fx[0][0] = 0; @@ -149,17 +185,21 @@ void ivas_filters_init_fx( move16(); move16(); - filter_state->state64_fx[0][0] = 0; - filter_state->state64_fx[0][1] = 0; - filter_state->state64_fx[0][2] = 0; - filter_state->state64_fx[1][0] = 0; - filter_state->state64_fx[1][1] = 0; - filter_state->state64_fx[1][2] = 0; - } - #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->q_diff = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][2] = 0; + move64(); + move64(); + move64(); + move64(); + move64(); + move64(); #endif + } return; } @@ -306,16 +346,16 @@ void ivas_filter_process_fixed_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ const Word16 length, /* i : filter order */ - Word16 *q_factor ) + Word16 q ) { SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_factor ); + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); BREAK; case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q_factor ); - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q_factor ); + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); BREAK; default: BREAK; @@ -324,129 +364,43 @@ void ivas_filter_process_fixed_fx( return; } -#if 0 -static void __check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ); - -static void __check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ) -{ - Word16 cq, eq, shift, q_diff; - Word64 cfx, efx; - - shift = W_norm( computed_fx ); - cfx = W_shl( computed_fx, shift ); - cq = add( computed_q, shift ); - - shift = W_norm( expected_fx ); - efx = W_shl( expected_fx, shift ); - eq = add( expected_q, shift ); - - q_diff = cq - eq; - shift = abs( q_diff ); - if ( q_diff >= 0 ) - { - cfx = shift < 64 ? W_shr( cfx, shift ) : 0; - } - else - { - efx = shift < 64 ? W_shr( efx, shift ) : 0; - } - Word64 error = llabs( cfx - efx ); - if ( error > ( ( (Word64) 1 ) << 60 ) ) - { - assert( false ); - } -} - -Word64 __to_state64( Word16 q, Word32 state_fx, Word16 state_e ) -{ - Word16 q_diff = q - ( 31 - state_e ); - Word64 state; - if ( q_diff <= -32 ) - state = 0; - else - state = W_shl( (Word64) state_fx, q_diff ); - // __check( state, q, state_fx, 31 - state_e ); - return state; -} -#endif - static void ivas_iir_2_filter_fixed_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, // Q(31-*pIn_Out_e) const Word16 length, const Word16 stage, - Word16 *q_factor ) + Word16 q ) { Word16 i, j; - Word32 *pIn_fx = pIn_Out_fx; - Word32 *pOut_fx = pIn_Out_fx; - Word32 tmp_pIn_buf_i_fx; - - Word32 L_tmp_prod, L_tmp; - Word16 L_prod_e, L_tmp_e; - - Word16 q_in, q_out; - Word16 e_in, e_out; - q_in = *q_factor; - *q_factor = q_out = q_in + filter_state->q_diff; - - // Word64 shift, tmp_prod, tmp, out64; + Word64 shift, tmp_prod, tmp; + Word32 in, out; FOR( i = 0; i < length; i++ ) { - tmp_pIn_buf_i_fx = pIn_fx[i]; + in = pIn_Out_fx[i]; move32(); - e_in = 31 - q_in; - move16(); - - L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][0], pIn_fx[i] ); // Q31 -(pIn_Out_e[i]+ filter_state->num_e[stage][0]) - L_prod_e = add( 31 - q_in, filter_state->num_e[stage][0] ); - // shift = 31 - filter_state->num_e[stage][0] + q_in - ( q_out + 32 ); - // tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], pIn_fx[i] ), shift ); - // __check( tmp_prod, q_out + 32, L_tmp_prod, 31 - L_prod_e ); + shift = filter_state->num_q[stage][0] + q - filter_state->state64_q[stage]; + tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); - e_out = 31 - q_in; - pOut_fx[i] = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][0], filter_state->state_e[stage][0], L_tmp_prod, L_prod_e, &e_out ); // Q31 - pIn_Out_e[i] + shift = sub( filter_state->state64_q[stage], q ); + pIn_Out_fx[i] = out = W_shr( W_add( filter_state->state64_fx[stage][0], tmp_prod ), shift ); move32(); - // out64 = W_add( filter_state->state64_fx[stage][0], tmp_prod ); - // __check( out64, q_out + 32, pOut_fx[i], 31 - e_out ); - // pOut_fx[i] = (Word32)(out64 >> 32); - FOR( j = 1; j < filter_state->filt_len; j++ ) { - L_tmp_prod = Mpy_32_32( filter_state->num_fx[stage][j], tmp_pIn_buf_i_fx ); // Q31-L_prod_e - L_prod_e = add( filter_state->num_e[stage][j], e_in ); - - // shift = 31 - filter_state->num_e[stage][j] + q_in - ( q_out + 32 ); - // tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], tmp_pIn_buf_i_fx ), shift ); - // __check( tmp_prod, q_out + 32, L_tmp_prod, 31 - L_prod_e ); - - L_tmp = BASOP_Util_Add_Mant32Exp( filter_state->state_fx[stage][j], filter_state->state_e[stage][j], L_tmp_prod, L_prod_e, &L_tmp_e ); // Q31 - L_tmp_e - - // tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - // __check( tmp, q_out + 32, L_tmp, 31 - L_tmp_e ); + shift = filter_state->num_q[stage][j] + q - filter_state->state64_q[stage]; + tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); - L_tmp_prod = Mpy_32_32( filter_state->den_fx[stage][j], pOut_fx[i] ); // Q31 - ( pIn_Out_e[i]+filter_state->den_e[stage][j] ) - L_prod_e = add( e_out, filter_state->den_e[stage][j] ); + tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - // shift = 31 - filter_state->den_e[stage][j] + q_out - ( q_out + 32 ); - // tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], pOut_fx[i] ), shift ); - // __check( tmp_prod, q_out + 32, L_tmp_prod, 31 - L_prod_e ); + shift = filter_state->den_q[stage][j] + q - filter_state->state64_q[stage]; + tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); - filter_state->state_fx[stage][j - 1] = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, L_negate( L_tmp_prod ), L_prod_e, &filter_state->state_e[stage][j - 1] ); // Q31 - filter_state->state_e[stage][j - 1] + filter_state->state64_fx[stage][j - 1] = W_add( tmp, W_neg( tmp_prod ) ); move32(); - - // filter_state->state64_fx[stage][j - 1] = W_add( tmp, tmp_prod ); - // __check( filter_state->state64_fx[stage][j - 1], q_out + 32, filter_state->state_fx[stage][j - 1], 31 - filter_state->state_e[stage][j - 1] ); - - // filter_state->state64_fx[stage][j - 1] = __to_state64( q_out + 32, filter_state->state_fx[stage][j - 1], filter_state->state_e[stage][j - 1] ); } - - pOut_fx[i] = L_shr_r_sat( pOut_fx[i], sub( sub( 31, q_out ), e_out ) ); // Q(31-pIn_Out_e[i]) -> Q(q_factor) - move32(); } return; diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 9f91e6c9b..ddcb33fef 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3821,7 +3821,7 @@ void ivas_filter_process_fixed_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ const Word16 length, /* i : filter order */ - Word16 *q_factor + Word16 q ); ivas_error ivas_osba_enc_open_fx( diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 4f7f2bb66..97a4f58a8 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -662,8 +662,10 @@ typedef struct ivas_filters_process_state_t Word16 state_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #ifdef OPT_2239_IVAS_FILTER_PROCESS - Word16 q_diff; // q_diff = q_out - q_in -> q_out = q_diff + q_in - Word32 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word64 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 num_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 den_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 state64_q[IVAS_FILTER_MAX_STAGES]; #endif } ivas_filters_process_state_t; diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index c81f3d3f6..b287701e1 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -375,7 +375,6 @@ static Word32 ivas_calc_duck_gain_fx( * Calculate in/out ducking gains *-----------------------------------------------------------------------------------------*/ -#ifndef OPT_2239_IVAS_FILTER_PROCESS static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ); static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ) @@ -393,12 +392,11 @@ static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Wo efx = L_shr( expected_fx, -q_diff ); } Word32 error = abs( cfx - efx ); - if ( error >= ( 1 << 22 ) ) + if ( error > ( 1 << 16 ) ) { assert( false ); } } -#endif void ivas_td_decorr_get_ducking_gains_fx( ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ @@ -424,11 +422,11 @@ void ivas_td_decorr_get_ducking_gains_fx( Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ -#ifdef OPT_2239_IVAS_FILTER_PROCESS +#if 0 // def OPT_2239_IVAS_FILTER_PROCESS /* env hpf */ Word16 q_fast = Q11; - ivas_filter_process_fixed_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, &q_fast ); + ivas_filter_process_fixed_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, q_fast ); Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; Word16 env_eps_q = Q31; @@ -436,9 +434,9 @@ void ivas_td_decorr_get_ducking_gains_fx( Word16 q_diff = sub( q_fast, env_eps_q ); q_fast = s_min( q_fast, env_eps_q ); - if ( q_diff >= 0 ) + IF( q_diff >= 0 ) { - for ( i = 0; i < frame_len; i++ ) + FOR( i = 0; i < frame_len; i++ ) { e_fast_fx[i] = L_add( L_abs( L_shr( e_fast_fx[i], q_diff ) ), env_eps_fx ); move32(); @@ -446,10 +444,10 @@ void ivas_td_decorr_get_ducking_gains_fx( move32(); } } - else + ELSE { env_eps_fx = L_shl( env_eps_fx, q_diff ); - for ( i = 0; i < frame_len; i++ ) + FOR( i = 0; i < frame_len; i++ ) { e_fast_fx[i] = L_add( L_abs( e_fast_fx[i] ), env_eps_fx ); move32(); @@ -461,10 +459,10 @@ void ivas_td_decorr_get_ducking_gains_fx( Word16 q_slow = q_fast; /* env fast*/ - ivas_filter_process_fixed_fx( &hTranDet->env_fast, e_fast_fx, frame_len, &q_fast ); + ivas_filter_process_fixed_fx( &hTranDet->env_fast, e_fast_fx, frame_len, q_fast ); /* env slow */ - ivas_filter_process_fixed_fx( &hTranDet->env_slow, e_slow_fx, frame_len, &q_slow ); + ivas_filter_process_fixed_fx( &hTranDet->env_slow, e_slow_fx, frame_len, q_slow ); IF( tdet_flag ) @@ -503,15 +501,17 @@ void ivas_td_decorr_get_ducking_gains_fx( ivas_filter_process_exp_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, e_fast_e ); - // Word32 test_e_fast_fx[L_FRAME48k]; - // Word16 q_fast = Q11; - // Copy32( pIn_pcm, test_e_fast_fx, frame_len ); /*Q11*/ - // ivas_filter_process_fixed_fx( &hTranDet->test_env_hpf, test_e_fast_fx, frame_len, &q_fast ); + // ==================================================================================================== + Word32 test_e_fast_fx[L_FRAME48k]; + Word16 q_fast = Q11; + Copy32( pIn_pcm, test_e_fast_fx, frame_len ); /*Q11*/ + ivas_filter_process_fixed_fx( &hTranDet->test_env_hpf, test_e_fast_fx, frame_len, q_fast ); - // for ( i = 0; i < frame_len; i++ ) - // { - // check(test_e_fast_fx[i],q_fast,e_fast_fx[i],31-e_fast_e[i]); - // } + for ( i = 0; i < frame_len; i++ ) + { + check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); + } + // ==================================================================================================== FOR( i = 0; i < frame_len; i++ ) @@ -525,12 +525,68 @@ void ivas_td_decorr_get_ducking_gains_fx( move16(); } + // ==================================================================================================== + Word32 test_e_slow_fx[L_FRAME48k]; + Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; + Word16 env_eps_q = Q31; + + Word16 q_diff = sub( q_fast, env_eps_q ); + q_fast = s_min( q_fast, env_eps_q ); + + if ( q_diff >= 0 ) + { + for ( i = 0; i < frame_len; i++ ) + { + test_e_fast_fx[i] = L_add( L_abs( L_shr( test_e_fast_fx[i], q_diff ) ), env_eps_fx ); + move32(); + test_e_slow_fx[i] = test_e_fast_fx[i]; + move32(); + } + } + else + { + env_eps_fx = L_shl( env_eps_fx, q_diff ); + for ( i = 0; i < frame_len; i++ ) + { + test_e_fast_fx[i] = L_add( L_abs( test_e_fast_fx[i] ), env_eps_fx ); + move32(); + test_e_slow_fx[i] = test_e_fast_fx[i]; + move32(); + } + } + + Word16 q_slow = q_fast; + + for ( i = 0; i < frame_len; i++ ) + { + check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); + } + // ==================================================================================================== + /* env fast*/ ivas_filter_process_exp_fx( &hTranDet->env_fast, e_fast_fx, frame_len, e_fast_e ); + // ==================================================================================================== + ivas_filter_process_fixed_fx( &hTranDet->test_env_fast, test_e_fast_fx, frame_len, q_fast ); + + for ( i = 0; i < frame_len; i++ ) + { + check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); + } + // ==================================================================================================== + /* env slow */ ivas_filter_process_exp_fx( &hTranDet->env_slow, e_slow_fx, frame_len, e_slow_e ); + // ==================================================================================================== + ivas_filter_process_fixed_fx( &hTranDet->test_env_slow, test_e_slow_fx, frame_len, q_slow ); + + for ( i = 0; i < frame_len; i++ ) + { + check( test_e_slow_fx[i], q_slow, e_slow_fx[i], 31 - e_slow_e[i] ); + } + // ==================================================================================================== + IF( tdet_flag ) { FOR( i = 0; i < frame_len; i++ ) -- GitLab From b71eba63d77a8a60d25d61f0c7da02b132999922 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Tue, 18 Nov 2025 12:16:27 +0000 Subject: [PATCH 04/24] Fix MSVC build failure. --- lib_com/ivas_filters_fx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index cdbb937cc..3f1bc8b54 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -371,9 +371,9 @@ static void ivas_iir_2_filter_fixed_fx( const Word16 stage, Word16 q ) { - Word16 i, j; + Word16 i, j, shift; - Word64 shift, tmp_prod, tmp; + Word64 tmp_prod, tmp; Word32 in, out; FOR( i = 0; i < length; i++ ) -- GitLab From 596469bc5e3be33594a953e1ec09eae792042660 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Tue, 18 Nov 2025 12:45:41 +0000 Subject: [PATCH 05/24] Fix MSVC build failure. --- lib_com/ivas_filters_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 3f1bc8b54..ab1b4ce96 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -385,7 +385,7 @@ static void ivas_iir_2_filter_fixed_fx( tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); shift = sub( filter_state->state64_q[stage], q ); - pIn_Out_fx[i] = out = W_shr( W_add( filter_state->state64_fx[stage][0], tmp_prod ), shift ); + pIn_Out_fx[i] = out = W_extract_l( W_shr( W_add( filter_state->state64_fx[stage][0], tmp_prod ), shift ) ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) -- GitLab From 4e772bc17205d7b722ab3789bb6cf65dac1da028 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Tue, 18 Nov 2025 13:36:02 +0000 Subject: [PATCH 06/24] Switch to optimized version. --- lib_com/ivas_transient_det_fx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index b287701e1..2bcb1b7cb 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -375,6 +375,7 @@ static Word32 ivas_calc_duck_gain_fx( * Calculate in/out ducking gains *-----------------------------------------------------------------------------------------*/ +#if 0 static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ); static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ) @@ -397,6 +398,7 @@ static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Wo assert( false ); } } +#endif void ivas_td_decorr_get_ducking_gains_fx( ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ @@ -422,7 +424,7 @@ void ivas_td_decorr_get_ducking_gains_fx( Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ -#if 0 // def OPT_2239_IVAS_FILTER_PROCESS +#ifdef OPT_2239_IVAS_FILTER_PROCESS /* env hpf */ Word16 q_fast = Q11; -- GitLab From f7c6386563d9bf50976039562df983e9deb4e4d3 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Tue, 18 Nov 2025 13:38:59 +0000 Subject: [PATCH 07/24] Remove ivas_transient_det_fx.py. --- lib_com/ivas_transient_det_fx.py | 98 -------------------------------- 1 file changed, 98 deletions(-) delete mode 100644 lib_com/ivas_transient_det_fx.py diff --git a/lib_com/ivas_transient_det_fx.py b/lib_com/ivas_transient_det_fx.py deleted file mode 100644 index e5b298998..000000000 --- a/lib_com/ivas_transient_det_fx.py +++ /dev/null @@ -1,98 +0,0 @@ -import numpy as np -from scipy import signal -import matplotlib.pyplot as plt - -def generate_biquad_butterworth_coeffs(cutoff_freq, fs, order=2, ftype='lowpass', output='ba'): - Wn = cutoff_freq - if output == 'sos': - sos_coeffs = signal.butter(order, Wn, btype=ftype, analog=False, output='sos', fs=fs) - return sos_coeffs - elif output == 'ba': - b_coeffs, a_coeffs = signal.butter(order, Wn, btype=ftype, analog=False, output='ba', fs=fs) - return b_coeffs, a_coeffs - else: - raise ValueError("Output format must be 'sos' or 'ba'") - -def plot_biquad_frequency_response(b, a, fs): - w, h = signal.freqz(b, a, fs=fs) - magnitude_db = 20 * np.log10(np.abs(h)) - phase_degrees = np.unwrap(np.angle(h)) * 180 / np.pi - - fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, tight_layout=True) - - ax1.plot(w, magnitude_db, 'b') - ax1.set_ylabel('Magnitude (dB)', color='b') - ax1.set_xlabel('Frequency (Hz)') - ax1.grid() - - ax2.plot(w, phase_degrees, 'g') - ax2.set_ylabel('Phase (degrees)', color='g') - ax2.set_xlabel('Frequency (Hz)') - ax2.grid() - - plt.show() - -def max_abs_output_biquad(b, a, n_samples=10000): - if a[0] != 1.0: - b = np.array(b) / a[0] - a = np.array(a) / a[0] - a[0] = 1.0 - - impulse_input = np.zeros(n_samples) - impulse_input[0] = 1.0 - - impulse_response = signal.lfilter(b, a, impulse_input) - - max_gain = np.sum(np.abs(impulse_response)) - - return max_gain - -# sampling_rate = 44100.0 # Hz -# cutoff_frequency = 5000.0 # Hz -# b_coeffs,a_coeffs = generate_biquad_butterworth_coeffs(cutoff_frequency, sampling_rate) -# plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) - -# # Calculate the maximum gain -# gain = max_abs_output_biquad(b_coeffs, a_coeffs) -# print(f"Numerator coefficients (b): {b_coeffs}") -# print(f"Denominator coefficients (a): {a_coeffs}") -# print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") - - -IVAS_C_HPF_48k = 0.675231906655777 -IVAS_C_HPF_32k = 0.554854910159853 -IVAS_C_HPF_16k = 0.307863971328499 - -IVAS_C_FAST_48k = 0.995842001845110 -IVAS_C_FAST_32k = 0.993769490623395 -IVAS_C_FAST_16k = 0.987577800493881 - -IVAS_C_SLOW_48k = 0.999739617238810 -IVAS_C_SLOW_32k = 0.999609451284012 -IVAS_C_SLOW_16k = 0.999219055096324 - -#env_hpf -sampling_rate = 48000.0 # Hz -b_coeffs = [ +IVAS_C_HPF_48k, -IVAS_C_HPF_48k, 0.0 ] -a_coeffs = [ 1.0, -IVAS_C_HPF_48k, 0.0 ] -plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) -gain = max_abs_output_biquad(b_coeffs, a_coeffs) -print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") - -#env_fast -sampling_rate = 48000.0 # Hz -b_coeffs = [ 1.0 - IVAS_C_FAST_48k, 0.0, 0.0 ] -a_coeffs = [ 1.0, -IVAS_C_FAST_48k, 0.0 ] -plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) -gain = max_abs_output_biquad(b_coeffs, a_coeffs) -print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") - -#env_slow -sampling_rate = 48000.0 # Hz -b_coeffs = [ 1.0 - IVAS_C_SLOW_48k, 0.0, 0.0 ] -a_coeffs = [ 1.0, -IVAS_C_SLOW_48k, 0.0 ] -plot_biquad_frequency_response(b_coeffs, a_coeffs, sampling_rate) -gain = max_abs_output_biquad(b_coeffs, a_coeffs) -print(f"Maximum possible time-domain gain (L1 norm): {gain:.4f}") - - -- GitLab From af00b514184949ec4cf5a3494ab8bc21a4245029 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Tue, 18 Nov 2025 16:55:27 +0000 Subject: [PATCH 08/24] Implement ivas_iir_2_filter_fx64. --- lib_com/ivas_filters_fx.c | 93 +++++++++++++++-- lib_com/ivas_prot_fx.h | 9 +- lib_com/ivas_transient_det_fx.c | 174 ++++++++++++++++++-------------- 3 files changed, 190 insertions(+), 86 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index ab1b4ce96..93d36fcf5 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -43,8 +43,8 @@ *------------------------------------------------------------------------------------------*/ static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); -static void ivas_iir_2_filter_fixed_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); - +static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); +static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); /*-----------------------------------------------------------------------------------------* * Function ivas_filters_init() @@ -342,7 +342,7 @@ static void ivas_iir_2_filter_fx( return; } -void ivas_filter_process_fixed_fx( +void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ const Word16 length, /* i : filter order */ @@ -351,11 +351,11 @@ void ivas_filter_process_fixed_fx( SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); BREAK; case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - ivas_iir_2_filter_fixed_fx( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); BREAK; default: BREAK; @@ -364,17 +364,38 @@ void ivas_filter_process_fixed_fx( return; } -static void ivas_iir_2_filter_fixed_fx( +void ivas_filter_process_fx64( + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word64 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ + const Word16 length, /* i : filter order */ + Word16 q ) +{ + SWITCH( filter_state->order ) + { + case IVAS_FILTER_ORDER_1: + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + BREAK; + case IVAS_FILTER_ORDER_4: + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); + BREAK; + default: + BREAK; + } + + return; +} + +static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, - Word32 *pIn_Out_fx, // Q(31-*pIn_Out_e) + Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ) { - Word16 i, j, shift; - Word64 tmp_prod, tmp; Word32 in, out; + Word16 i, j, shift; FOR( i = 0; i < length; i++ ) { @@ -398,7 +419,57 @@ static void ivas_iir_2_filter_fixed_fx( shift = filter_state->den_q[stage][j] + q - filter_state->state64_q[stage]; tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); - filter_state->state64_fx[stage][j - 1] = W_add( tmp, W_neg( tmp_prod ) ); + filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + move32(); + } + } + + return; +} + +static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) +{ + Word32 var1_l; + Word64 var_out; + var1_l = W_extract_l( W_var1 ); // 1 + var_out = W_mult0_32_32( L_and( var1_l, 1 ), L_var2 ); // 2 + var_out = W_mac_32_32( var_out, L_lshr( var1_l, 1 ), L_var2 ); // 2 + var_out = W_mac_32_32( W_shr( var_out, 31 ), W_extract_h( W_var1 ), L_var2 ); // 3 + return var_out; +} + +static void ivas_iir_2_filter_fx64( + ivas_filters_process_state_t *filter_state, + Word64 *pIn_Out_fx, + const Word16 length, + const Word16 stage, + Word16 q ) +{ + Word64 tmp_prod, tmp, in, out; + Word16 i, j, shift; + + FOR( i = 0; i < length; i++ ) + { + in = pIn_Out_fx[i]; + move32(); + + shift = ( filter_state->num_q[stage][0] + q - 31 ) - q; + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); + + pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + move32(); + + FOR( j = 1; j < filter_state->filt_len; j++ ) + { + shift = ( filter_state->num_q[stage][j] + q - 31 ) - q; + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); + + tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + + shift = ( filter_state->den_q[stage][j] + q - 31 ) - q; + tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); + + filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); } } diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index ddcb33fef..d7d4fbdfc 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3817,13 +3817,20 @@ void ivas_filter_process_exp_fx( Word16 *pIn_Out_e ); -void ivas_filter_process_fixed_fx( +void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ const Word16 length, /* i : filter order */ Word16 q ); +void ivas_filter_process_fx64( + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word64 *pIn_Out_fx, /* i : signal subject to filtering */ + const Word16 length, /* i : filter order */ + Word16 q +); + ivas_error ivas_osba_enc_open_fx( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index 2bcb1b7cb..e5e0ebe1c 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -376,24 +376,24 @@ static Word32 ivas_calc_duck_gain_fx( *-----------------------------------------------------------------------------------------*/ #if 0 -static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ); +static void check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ); -static void check( Word32 computed_fx, Word16 computed_q, Word32 expected_fx, Word16 expected_q ) +static void check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ) { - Word32 cfx, efx; + Word64 cfx, efx; Word16 q_diff = computed_q - expected_q; if ( q_diff >= 0 ) { - cfx = L_shr( computed_fx, +q_diff ); + cfx = W_shr( computed_fx, +q_diff ); efx = expected_fx; } else { cfx = computed_fx; - efx = L_shr( expected_fx, -q_diff ); + efx = W_shr( expected_fx, -q_diff ); } - Word32 error = abs( cfx - efx ); - if ( error > ( 1 << 16 ) ) + Word64 error = llabs( cfx - efx ); + if ( error > ( (Word64) 1 << 16 ) ) { assert( false ); } @@ -409,7 +409,6 @@ void ivas_td_decorr_get_ducking_gains_fx( const Word16 tdet_flag /*Q0*/ ) { Word16 i; - Word32 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; Word32 in_duck_gain = hTranDet->in_duck_gain; /*Q30*/ move32(); Word32 out_duck_gain = hTranDet->out_duck_gain; /*Q30*/ @@ -421,17 +420,22 @@ void ivas_td_decorr_get_ducking_gains_fx( Word32 duck_mult_fac = hTranDet->duck_mult_fac; /*Q29*/ move32(); - Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ +#ifdef OPT_2239_IVAS_FILTER_PROCESS + Word64 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; + + for ( i = 0; i < frame_len; i++ ) + { + e_fast_fx[i] = ( (Word64) pIn_pcm[i] ) << 32; + } -#ifdef OPT_2239_IVAS_FILTER_PROCESS /* env hpf */ - Word16 q_fast = Q11; + Word16 q_fast = Q11 + 32; - ivas_filter_process_fixed_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, q_fast ); + ivas_filter_process_fx64( &hTranDet->env_hpf, e_fast_fx, frame_len, q_fast ); - Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; - Word16 env_eps_q = Q31; + Word64 env_eps_fx = ( (Word64) IVAS_TDET_PARM_ENV_EPS_fx ) << 32; + Word16 env_eps_q = Q31 + 32; Word16 q_diff = sub( q_fast, env_eps_q ); q_fast = s_min( q_fast, env_eps_q ); @@ -440,7 +444,7 @@ void ivas_td_decorr_get_ducking_gains_fx( { FOR( i = 0; i < frame_len; i++ ) { - e_fast_fx[i] = L_add( L_abs( L_shr( e_fast_fx[i], q_diff ) ), env_eps_fx ); + e_fast_fx[i] = W_add( W_abs( W_shr( e_fast_fx[i], q_diff ) ), env_eps_fx ); move32(); e_slow_fx[i] = e_fast_fx[i]; move32(); @@ -448,10 +452,10 @@ void ivas_td_decorr_get_ducking_gains_fx( } ELSE { - env_eps_fx = L_shl( env_eps_fx, q_diff ); + env_eps_fx = W_shl( env_eps_fx, q_diff ); FOR( i = 0; i < frame_len; i++ ) { - e_fast_fx[i] = L_add( L_abs( e_fast_fx[i] ), env_eps_fx ); + e_fast_fx[i] = W_add( W_abs( e_fast_fx[i] ), env_eps_fx ); move32(); e_slow_fx[i] = e_fast_fx[i]; move32(); @@ -461,18 +465,25 @@ void ivas_td_decorr_get_ducking_gains_fx( Word16 q_slow = q_fast; /* env fast*/ - ivas_filter_process_fixed_fx( &hTranDet->env_fast, e_fast_fx, frame_len, q_fast ); + ivas_filter_process_fx64( &hTranDet->env_fast, e_fast_fx, frame_len, q_fast ); /* env slow */ - ivas_filter_process_fixed_fx( &hTranDet->env_slow, e_slow_fx, frame_len, q_slow ); + ivas_filter_process_fx64( &hTranDet->env_slow, e_slow_fx, frame_len, q_slow ); IF( tdet_flag ) { FOR( i = 0; i < frame_len; i++ ) { - in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, e_slow_fx[i], 31 - q_slow, e_fast_fx[i], 31 - q_fast, duck_mult_fac ); /*Q30*/ - pIn_duck_gains[i] = in_duck_gain; /*Q30*/ + Word16 fast_e = W_norm( e_fast_fx[i] ); + Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); + fast_e = 31 - ( q_fast + fast_e - 32 ); + Word16 slow_e = W_norm( e_slow_fx[i] ); + Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); + slow_e = 31 - ( q_slow + slow_e - 32 ); + + in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, slow_fx, slow_e, fast_fx, fast_e, duck_mult_fac ); /*Q30*/ + pIn_duck_gains[i] = in_duck_gain; /*Q30*/ move32(); } hTranDet->in_duck_gain = in_duck_gain; /*Q30*/ @@ -482,11 +493,18 @@ void ivas_td_decorr_get_ducking_gains_fx( { FOR( i = 0; i < frame_len; i++ ) { - in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, e_slow_fx[i], 31 - q_slow, e_fast_fx[i], 31 - q_fast, duck_mult_fac ); /*Q30*/ - pIn_duck_gains[i] = in_duck_gain; /*Q30*/ + Word16 fast_e = W_norm( e_fast_fx[i] ); + Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); + fast_e = 31 - ( q_fast + fast_e - 32 ); + Word16 slow_e = W_norm( e_slow_fx[i] ); + Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); + slow_e = 31 - ( q_slow + slow_e - 32 ); + + in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, slow_fx, slow_e, fast_fx, fast_e, duck_mult_fac ); /*Q30*/ + pIn_duck_gains[i] = in_duck_gain; /*Q30*/ move32(); - out_duck_gain = ivas_calc_duck_gain_fx( out_duck_gain, out_duck_coeff, e_fast_fx[i], 31 - q_fast, e_slow_fx[i], 31 - q_slow, duck_mult_fac ); /*Q30*/ - pOut_duck_gains[i] = out_duck_gain; /*Q30*/ + out_duck_gain = ivas_calc_duck_gain_fx( out_duck_gain, out_duck_coeff, fast_fx, fast_e, slow_fx, slow_e, duck_mult_fac ); /*Q30*/ + pOut_duck_gains[i] = out_duck_gain; /*Q30*/ move32(); } hTranDet->in_duck_gain = in_duck_gain; /*Q30*/ @@ -495,6 +513,9 @@ void ivas_td_decorr_get_ducking_gains_fx( move32(); } #else + Word32 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; + Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ + Word16 e_fast_e[L_FRAME48k], e_slow_e[L_FRAME48k]; set16_fx( e_fast_e, 31 - Q11, L_FRAME48k ); @@ -504,10 +525,15 @@ void ivas_td_decorr_get_ducking_gains_fx( // ==================================================================================================== - Word32 test_e_fast_fx[L_FRAME48k]; - Word16 q_fast = Q11; - Copy32( pIn_pcm, test_e_fast_fx, frame_len ); /*Q11*/ - ivas_filter_process_fixed_fx( &hTranDet->test_env_hpf, test_e_fast_fx, frame_len, q_fast ); + Word64 test_e_fast_fx[L_FRAME48k]; + Word16 q_fast = Q11 + 32; + + for ( i = 0; i < frame_len; i++ ) + { + test_e_fast_fx[i] = (Word64) pIn_pcm[i] << 32; + } + + ivas_filter_process_fx64( &hTranDet->test_env_hpf, test_e_fast_fx, frame_len, q_fast ); for ( i = 0; i < frame_len; i++ ) { @@ -528,65 +554,65 @@ void ivas_td_decorr_get_ducking_gains_fx( } // ==================================================================================================== - Word32 test_e_slow_fx[L_FRAME48k]; - Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; - Word16 env_eps_q = Q31; - - Word16 q_diff = sub( q_fast, env_eps_q ); - q_fast = s_min( q_fast, env_eps_q ); - - if ( q_diff >= 0 ) - { - for ( i = 0; i < frame_len; i++ ) - { - test_e_fast_fx[i] = L_add( L_abs( L_shr( test_e_fast_fx[i], q_diff ) ), env_eps_fx ); - move32(); - test_e_slow_fx[i] = test_e_fast_fx[i]; - move32(); - } - } - else - { - env_eps_fx = L_shl( env_eps_fx, q_diff ); - for ( i = 0; i < frame_len; i++ ) - { - test_e_fast_fx[i] = L_add( L_abs( test_e_fast_fx[i] ), env_eps_fx ); - move32(); - test_e_slow_fx[i] = test_e_fast_fx[i]; - move32(); - } - } - - Word16 q_slow = q_fast; - - for ( i = 0; i < frame_len; i++ ) - { - check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); - } + // Word32 test_e_slow_fx[L_FRAME48k]; + // Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; + // Word16 env_eps_q = Q31; + + // Word16 q_diff = sub( q_fast, env_eps_q ); + // q_fast = s_min( q_fast, env_eps_q ); + + // if ( q_diff >= 0 ) + // { + // for ( i = 0; i < frame_len; i++ ) + // { + // test_e_fast_fx[i] = L_add( L_abs( L_shr( test_e_fast_fx[i], q_diff ) ), env_eps_fx ); + // move32(); + // test_e_slow_fx[i] = test_e_fast_fx[i]; + // move32(); + // } + // } + // else + // { + // env_eps_fx = L_shl( env_eps_fx, q_diff ); + // for ( i = 0; i < frame_len; i++ ) + // { + // test_e_fast_fx[i] = L_add( L_abs( test_e_fast_fx[i] ), env_eps_fx ); + // move32(); + // test_e_slow_fx[i] = test_e_fast_fx[i]; + // move32(); + // } + // } + + // Word16 q_slow = q_fast; + + // for ( i = 0; i < frame_len; i++ ) + // { + // check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); + // } // ==================================================================================================== /* env fast*/ ivas_filter_process_exp_fx( &hTranDet->env_fast, e_fast_fx, frame_len, e_fast_e ); // ==================================================================================================== - ivas_filter_process_fixed_fx( &hTranDet->test_env_fast, test_e_fast_fx, frame_len, q_fast ); + // ivas_filter_process_fx32( &hTranDet->test_env_fast, test_e_fast_fx, frame_len, q_fast ); - for ( i = 0; i < frame_len; i++ ) - { - check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); - } + // for ( i = 0; i < frame_len; i++ ) + // { + // check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); + // } // ==================================================================================================== /* env slow */ ivas_filter_process_exp_fx( &hTranDet->env_slow, e_slow_fx, frame_len, e_slow_e ); // ==================================================================================================== - ivas_filter_process_fixed_fx( &hTranDet->test_env_slow, test_e_slow_fx, frame_len, q_slow ); + // ivas_filter_process_fx32( &hTranDet->test_env_slow, test_e_slow_fx, frame_len, q_slow ); - for ( i = 0; i < frame_len; i++ ) - { - check( test_e_slow_fx[i], q_slow, e_slow_fx[i], 31 - e_slow_e[i] ); - } + // for ( i = 0; i < frame_len; i++ ) + // { + // check( test_e_slow_fx[i], q_slow, e_slow_fx[i], 31 - e_slow_e[i] ); + // } // ==================================================================================================== IF( tdet_flag ) -- GitLab From aa3187784ec6ab7e0d2d59a9499124206bcf3fbd Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 20 Nov 2025 12:57:43 +0000 Subject: [PATCH 09/24] Simplify ivas_td_decorr_get_ducking_gains_fx. --- lib_com/cnst.h | 2 + lib_com/ivas_transient_det_fx.c | 96 +++++++++------------------------ 2 files changed, 27 insertions(+), 71 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 03bcc42b8..a6a0258bf 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -99,6 +99,8 @@ #define Q30 30 #define Q31 31 +#define Q43 43 + /*----------------------------------------------------------------------------------* * one in Q *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index e5e0ebe1c..55e301e8b 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -43,8 +43,12 @@ * Local constants *------------------------------------------------------------------------------------------*/ -#define IVAS_TDET_PARM_ENV_EPS ( 1e-5f ) +#define IVAS_TDET_PARM_ENV_EPS ( 1e-5f ) +#ifdef OPT_2239_IVAS_FILTER_PROCESS +#define IVAS_TDET_PARM_ENV_EPS_fx ( ( (Word64) 21474 ) << 12 ) // Q11+32 +#else #define IVAS_TDET_PARM_ENV_EPS_fx 21474 // Q31 +#endif #define IVAS_TDET_DUCK_MULT_FAC ( 590558003 ) // Q29 #define IVAS_TDET_PARM_TRANS_THR ( 107374182 ) // Q30 @@ -375,31 +379,6 @@ static Word32 ivas_calc_duck_gain_fx( * Calculate in/out ducking gains *-----------------------------------------------------------------------------------------*/ -#if 0 -static void check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ); - -static void check( Word64 computed_fx, Word16 computed_q, Word64 expected_fx, Word16 expected_q ) -{ - Word64 cfx, efx; - Word16 q_diff = computed_q - expected_q; - if ( q_diff >= 0 ) - { - cfx = W_shr( computed_fx, +q_diff ); - efx = expected_fx; - } - else - { - cfx = computed_fx; - efx = W_shr( expected_fx, -q_diff ); - } - Word64 error = llabs( cfx - efx ); - if ( error > ( (Word64) 1 << 16 ) ) - { - assert( false ); - } -} -#endif - void ivas_td_decorr_get_ducking_gains_fx( ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ Word32 *pIn_pcm, /*Q11*/ @@ -423,64 +402,39 @@ void ivas_td_decorr_get_ducking_gains_fx( #ifdef OPT_2239_IVAS_FILTER_PROCESS Word64 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; - for ( i = 0; i < frame_len; i++ ) + FOR( i = 0; i < frame_len; i++ ) { - e_fast_fx[i] = ( (Word64) pIn_pcm[i] ) << 32; + e_fast_fx[i] = W_deposit32_h( pIn_pcm[i] ); /*Q43*/ + move64(); } - /* env hpf */ - Word16 q_fast = Q11 + 32; - - ivas_filter_process_fx64( &hTranDet->env_hpf, e_fast_fx, frame_len, q_fast ); - - Word64 env_eps_fx = ( (Word64) IVAS_TDET_PARM_ENV_EPS_fx ) << 32; - Word16 env_eps_q = Q31 + 32; + ivas_filter_process_fx64( &hTranDet->env_hpf, e_fast_fx, frame_len, Q43 ); - Word16 q_diff = sub( q_fast, env_eps_q ); - q_fast = s_min( q_fast, env_eps_q ); - - IF( q_diff >= 0 ) - { - FOR( i = 0; i < frame_len; i++ ) - { - e_fast_fx[i] = W_add( W_abs( W_shr( e_fast_fx[i], q_diff ) ), env_eps_fx ); - move32(); - e_slow_fx[i] = e_fast_fx[i]; - move32(); - } - } - ELSE + FOR( i = 0; i < frame_len; i++ ) { - env_eps_fx = W_shl( env_eps_fx, q_diff ); - FOR( i = 0; i < frame_len; i++ ) - { - e_fast_fx[i] = W_add( W_abs( e_fast_fx[i] ), env_eps_fx ); - move32(); - e_slow_fx[i] = e_fast_fx[i]; - move32(); - } + e_fast_fx[i] = W_add( W_abs( e_fast_fx[i] ), IVAS_TDET_PARM_ENV_EPS_fx ); + move64(); + e_slow_fx[i] = e_fast_fx[i]; + move64(); } - Word16 q_slow = q_fast; - /* env fast*/ - ivas_filter_process_fx64( &hTranDet->env_fast, e_fast_fx, frame_len, q_fast ); + ivas_filter_process_fx64( &hTranDet->env_fast, e_fast_fx, frame_len, Q43 ); /* env slow */ - ivas_filter_process_fx64( &hTranDet->env_slow, e_slow_fx, frame_len, q_slow ); - + ivas_filter_process_fx64( &hTranDet->env_slow, e_slow_fx, frame_len, Q43 ); IF( tdet_flag ) { FOR( i = 0; i < frame_len; i++ ) { Word16 fast_e = W_norm( e_fast_fx[i] ); - Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); - fast_e = 31 - ( q_fast + fast_e - 32 ); + Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); /*Q43 + fast_e - 32 = Q11 + fast_e*/ + fast_e = sub( 20, fast_e ); /*exp: 31 - (Q11 + fast_e) = 20 - fast_e*/ Word16 slow_e = W_norm( e_slow_fx[i] ); - Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); - slow_e = 31 - ( q_slow + slow_e - 32 ); + Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); /*Q43 + fast_e - 32 = Q11 + slow_e*/ + slow_e = sub( 20, slow_e ); /*exp: 31 - (Q11 + slow_e) = 20 - slow_e*/ in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, slow_fx, slow_e, fast_fx, fast_e, duck_mult_fac ); /*Q30*/ pIn_duck_gains[i] = in_duck_gain; /*Q30*/ @@ -494,11 +448,11 @@ void ivas_td_decorr_get_ducking_gains_fx( FOR( i = 0; i < frame_len; i++ ) { Word16 fast_e = W_norm( e_fast_fx[i] ); - Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); - fast_e = 31 - ( q_fast + fast_e - 32 ); + Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); /*Q43 + fast_e - 32 = Q11 + fast_e*/ + fast_e = sub( 20, fast_e ); /*exp: 31 - (Q11 + fast_e) = 20 - fast_e*/ Word16 slow_e = W_norm( e_slow_fx[i] ); - Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); - slow_e = 31 - ( q_slow + slow_e - 32 ); + Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); /*Q43 + fast_e - 32 = Q11 + slow_e*/ + slow_e = sub( 20, slow_e ); /*exp: 31 - (Q11 + slow_e) = 20 - slow_e*/ in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, slow_fx, slow_e, fast_fx, fast_e, duck_mult_fac ); /*Q30*/ pIn_duck_gains[i] = in_duck_gain; /*Q30*/ @@ -526,7 +480,7 @@ void ivas_td_decorr_get_ducking_gains_fx( // ==================================================================================================== Word64 test_e_fast_fx[L_FRAME48k]; - Word16 q_fast = Q11 + 32; + Word16 q_fast = Q43; for ( i = 0; i < frame_len; i++ ) { -- GitLab From a3b4967bbf0c8af8e31a1b039c1a6944dec95c46 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 20 Nov 2025 14:19:43 +0000 Subject: [PATCH 10/24] Tidy up code. --- lib_com/ivas_filters_fx.c | 325 ++++++++++++++++++-------------- lib_com/ivas_prot_fx.h | 32 ++-- lib_com/ivas_transient_det_fx.c | 105 ++--------- lib_dec/ivas_lfe_dec_fx.c | 4 + lib_enc/ivas_lfe_enc_fx.c | 4 + 5 files changed, 217 insertions(+), 253 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 93d36fcf5..22a296bdd 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -38,14 +38,6 @@ #include "ivas_rom_com.h" #include "ivas_prot_fx.h" -/*------------------------------------------------------------------------------------------* - * Local functions declaration - *------------------------------------------------------------------------------------------*/ - -static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); -static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); -static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); - /*-----------------------------------------------------------------------------------------* * Function ivas_filters_init() * @@ -204,6 +196,185 @@ void ivas_filters_init_fx( return; } +#ifdef OPT_2239_IVAS_FILTER_PROCESS +static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); +static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); +static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ); + +/*-----------------------------------------------------------------------------------------* + * Function Mpy_64_32() + * + * Performs the the following operation: + * + * z = ((int128_t)x * (int128_t)y) >> 31 + * + * where: + * - x is a 64-bit signed integer + * - y is a 32-bit signed integer + * - z is a 64-bit signed integer + *-----------------------------------------------------------------------------------------*/ + +static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) +{ + Word32 var1_l; + Word64 var_out; + var1_l = W_extract_l( W_var1 ); // 1 + var_out = W_mult0_32_32( L_and( var1_l, 1 ), L_var2 ); // 2 + var_out = W_mac_32_32( var_out, L_lshr( var1_l, 1 ), L_var2 ); // 2 + var_out = W_mac_32_32( W_shr( var_out, 31 ), W_extract_h( W_var1 ), L_var2 ); // 3 + return var_out; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_iir_2_filter_fx32() + * + * Process call for filtering a signal + *-----------------------------------------------------------------------------------------*/ + +static void ivas_iir_2_filter_fx32( + ivas_filters_process_state_t *filter_state, + Word32 *pIn_Out_fx, + const Word16 length, + const Word16 stage, + Word16 q ) +{ + Word64 tmp_prod, tmp; + Word32 in, out; + Word16 i, j, shift; + + FOR( i = 0; i < length; i++ ) + { + in = pIn_Out_fx[i]; + move32(); + + shift = filter_state->num_q[stage][0] + q - filter_state->state64_q[stage]; + tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); + + shift = sub( filter_state->state64_q[stage], q ); + pIn_Out_fx[i] = out = W_extract_l( W_shr( W_add( filter_state->state64_fx[stage][0], tmp_prod ), shift ) ); + move32(); + + FOR( j = 1; j < filter_state->filt_len; j++ ) + { + shift = filter_state->num_q[stage][j] + q - filter_state->state64_q[stage]; + tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); + + tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + + shift = filter_state->den_q[stage][j] + q - filter_state->state64_q[stage]; + tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); + + filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + move32(); + } + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_filter_process_fx32() + * + * Process call for filtering a signal + *-----------------------------------------------------------------------------------------*/ + +void ivas_filter_process_fx32( + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ + const Word16 length, /* i : filter order */ + Word16 q ) +{ + SWITCH( filter_state->order ) + { + case IVAS_FILTER_ORDER_1: + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + BREAK; + case IVAS_FILTER_ORDER_4: + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); + BREAK; + default: + BREAK; + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_iir_2_filter_fx64() + * + * Process call for filtering a signal + *-----------------------------------------------------------------------------------------*/ + +static void ivas_iir_2_filter_fx64( + ivas_filters_process_state_t *filter_state, + Word64 *pIn_Out_fx, + const Word16 length, + const Word16 stage, + Word16 q ) +{ + Word64 tmp_prod, tmp, in, out; + Word16 i, j, shift; + + FOR( i = 0; i < length; i++ ) + { + in = pIn_Out_fx[i]; + move32(); + + shift = ( filter_state->num_q[stage][0] + q - 31 ) - q; + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); + + pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + move32(); + + FOR( j = 1; j < filter_state->filt_len; j++ ) + { + shift = ( filter_state->num_q[stage][j] + q - 31 ) - q; + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); + + tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + + shift = ( filter_state->den_q[stage][j] + q - 31 ) - q; + tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); + + filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + move32(); + } + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_filter_process_fx64() + * + * Process call for filtering a signal + *-----------------------------------------------------------------------------------------*/ + +void ivas_filter_process_fx64( + ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ + Word64 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ + const Word16 length, /* i : filter order */ + Word16 q ) +{ + SWITCH( filter_state->order ) + { + case IVAS_FILTER_ORDER_1: + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + BREAK; + case IVAS_FILTER_ORDER_4: + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); + BREAK; + default: + BREAK; + } + + return; +} + +#else +static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); /*-----------------------------------------------------------------------------------------* * Function ivas_filter_process() @@ -252,7 +423,6 @@ void ivas_filter_process_fx( return; } - void ivas_filter_process_exp_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ @@ -279,7 +449,6 @@ void ivas_filter_process_exp_fx( return; } - /*-----------------------------------------------------------------------------------------* * Function ivas_iir_2_filter() * @@ -341,138 +510,4 @@ static void ivas_iir_2_filter_fx( return; } - -void ivas_filter_process_fx32( - ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ - const Word16 length, /* i : filter order */ - Word16 q ) -{ - SWITCH( filter_state->order ) - { - case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - BREAK; - case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); - BREAK; - default: - BREAK; - } - - return; -} - -void ivas_filter_process_fx64( - ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word64 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ - const Word16 length, /* i : filter order */ - Word16 q ) -{ - SWITCH( filter_state->order ) - { - case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - BREAK; - case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); - BREAK; - default: - BREAK; - } - - return; -} - -static void ivas_iir_2_filter_fx32( - ivas_filters_process_state_t *filter_state, - Word32 *pIn_Out_fx, - const Word16 length, - const Word16 stage, - Word16 q ) -{ - Word64 tmp_prod, tmp; - Word32 in, out; - Word16 i, j, shift; - - FOR( i = 0; i < length; i++ ) - { - in = pIn_Out_fx[i]; - move32(); - - shift = filter_state->num_q[stage][0] + q - filter_state->state64_q[stage]; - tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); - - shift = sub( filter_state->state64_q[stage], q ); - pIn_Out_fx[i] = out = W_extract_l( W_shr( W_add( filter_state->state64_fx[stage][0], tmp_prod ), shift ) ); - move32(); - - FOR( j = 1; j < filter_state->filt_len; j++ ) - { - shift = filter_state->num_q[stage][j] + q - filter_state->state64_q[stage]; - tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); - - tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - - shift = filter_state->den_q[stage][j] + q - filter_state->state64_q[stage]; - tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); - - filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); - move32(); - } - } - - return; -} - -static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) -{ - Word32 var1_l; - Word64 var_out; - var1_l = W_extract_l( W_var1 ); // 1 - var_out = W_mult0_32_32( L_and( var1_l, 1 ), L_var2 ); // 2 - var_out = W_mac_32_32( var_out, L_lshr( var1_l, 1 ), L_var2 ); // 2 - var_out = W_mac_32_32( W_shr( var_out, 31 ), W_extract_h( W_var1 ), L_var2 ); // 3 - return var_out; -} - -static void ivas_iir_2_filter_fx64( - ivas_filters_process_state_t *filter_state, - Word64 *pIn_Out_fx, - const Word16 length, - const Word16 stage, - Word16 q ) -{ - Word64 tmp_prod, tmp, in, out; - Word16 i, j, shift; - - FOR( i = 0; i < length; i++ ) - { - in = pIn_Out_fx[i]; - move32(); - - shift = ( filter_state->num_q[stage][0] + q - 31 ) - q; - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - - pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); - move32(); - - FOR( j = 1; j < filter_state->filt_len; j++ ) - { - shift = ( filter_state->num_q[stage][j] + q - 31 ) - q; - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); - - tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - - shift = ( filter_state->den_q[stage][j] + q - 31 ) - q; - tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); - - filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); - move32(); - } - } - - return; -} +#endif diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index d7d4fbdfc..ce6c223e3 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3803,34 +3803,35 @@ void ivas_lfe_enc_fx( BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ ); -void ivas_filter_process_fx( +#ifdef OPT_2239_IVAS_FILTER_PROCESS +void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ const Word16 length, /* i : filter order */ - Word16 q_factor + Word16 q ); -void ivas_filter_process_exp_fx( +void ivas_filter_process_fx64( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ + Word64 *pIn_Out_fx, /* i : signal subject to filtering */ const Word16 length, /* i : filter order */ - Word16 *pIn_Out_e + Word16 q ); - -void ivas_filter_process_fx32( +#else +void ivas_filter_process_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ const Word16 length, /* i : filter order */ - Word16 q + Word16 q_factor ); -void ivas_filter_process_fx64( +void ivas_filter_process_exp_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word64 *pIn_Out_fx, /* i : signal subject to filtering */ + Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ const Word16 length, /* i : filter order */ - Word16 q + Word16 *pIn_Out_e ); - +#endif ivas_error ivas_osba_enc_open_fx( Encoder_Struct *st_ivas /* i/o: IVAS encoder handle */ ); @@ -6821,13 +6822,6 @@ void ivas_filters_init_fx( const Word16 order ); -void ivas_filter_process_fx( - ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ - const Word16 length, /* i : filter order */ - Word16 q_factor -); - /*----------------------------------------------------------------------------------* * OSBA prototypes *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index 55e301e8b..fca80ce82 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -401,6 +401,8 @@ void ivas_td_decorr_get_ducking_gains_fx( #ifdef OPT_2239_IVAS_FILTER_PROCESS Word64 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; + Word32 fast_fx, slow_fx; + Word16 fast_e, slow_e; FOR( i = 0; i < frame_len; i++ ) { @@ -429,12 +431,12 @@ void ivas_td_decorr_get_ducking_gains_fx( { FOR( i = 0; i < frame_len; i++ ) { - Word16 fast_e = W_norm( e_fast_fx[i] ); - Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); /*Q43 + fast_e - 32 = Q11 + fast_e*/ - fast_e = sub( 20, fast_e ); /*exp: 31 - (Q11 + fast_e) = 20 - fast_e*/ - Word16 slow_e = W_norm( e_slow_fx[i] ); - Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); /*Q43 + fast_e - 32 = Q11 + slow_e*/ - slow_e = sub( 20, slow_e ); /*exp: 31 - (Q11 + slow_e) = 20 - slow_e*/ + fast_e = W_norm( e_fast_fx[i] ); + fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); /*Q43 + fast_e - 32 = Q11 + fast_e*/ + fast_e = sub( 20, fast_e ); /*exp: 31 - (Q11 + fast_e) = 20 - fast_e*/ + slow_e = W_norm( e_slow_fx[i] ); + slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); /*Q43 + fast_e - 32 = Q11 + slow_e*/ + slow_e = sub( 20, slow_e ); /*exp: 31 - (Q11 + slow_e) = 20 - slow_e*/ in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, slow_fx, slow_e, fast_fx, fast_e, duck_mult_fac ); /*Q30*/ pIn_duck_gains[i] = in_duck_gain; /*Q30*/ @@ -447,12 +449,12 @@ void ivas_td_decorr_get_ducking_gains_fx( { FOR( i = 0; i < frame_len; i++ ) { - Word16 fast_e = W_norm( e_fast_fx[i] ); - Word32 fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); /*Q43 + fast_e - 32 = Q11 + fast_e*/ - fast_e = sub( 20, fast_e ); /*exp: 31 - (Q11 + fast_e) = 20 - fast_e*/ - Word16 slow_e = W_norm( e_slow_fx[i] ); - Word32 slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); /*Q43 + fast_e - 32 = Q11 + slow_e*/ - slow_e = sub( 20, slow_e ); /*exp: 31 - (Q11 + slow_e) = 20 - slow_e*/ + fast_e = W_norm( e_fast_fx[i] ); + fast_fx = W_extract_h( W_shl( e_fast_fx[i], fast_e ) ); /*Q43 + fast_e - 32 = Q11 + fast_e*/ + fast_e = sub( 20, fast_e ); /*exp: 31 - (Q11 + fast_e) = 20 - fast_e*/ + slow_e = W_norm( e_slow_fx[i] ); + slow_fx = W_extract_h( W_shl( e_slow_fx[i], slow_e ) ); /*Q43 + fast_e - 32 = Q11 + slow_e*/ + slow_e = sub( 20, slow_e ); /*exp: 31 - (Q11 + slow_e) = 20 - slow_e*/ in_duck_gain = ivas_calc_duck_gain_fx( in_duck_gain, in_duck_coeff, slow_fx, slow_e, fast_fx, fast_e, duck_mult_fac ); /*Q30*/ pIn_duck_gains[i] = in_duck_gain; /*Q30*/ @@ -468,34 +470,16 @@ void ivas_td_decorr_get_ducking_gains_fx( } #else Word32 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; - Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ - Word16 e_fast_e[L_FRAME48k], e_slow_e[L_FRAME48k]; + Copy32( pIn_pcm, e_fast_fx, frame_len ); /*Q11*/ + set16_fx( e_fast_e, 31 - Q11, L_FRAME48k ); /* env hpf */ ivas_filter_process_exp_fx( &hTranDet->env_hpf, e_fast_fx, frame_len, e_fast_e ); - // ==================================================================================================== - Word64 test_e_fast_fx[L_FRAME48k]; - Word16 q_fast = Q43; - - for ( i = 0; i < frame_len; i++ ) - { - test_e_fast_fx[i] = (Word64) pIn_pcm[i] << 32; - } - - ivas_filter_process_fx64( &hTranDet->test_env_hpf, test_e_fast_fx, frame_len, q_fast ); - - for ( i = 0; i < frame_len; i++ ) - { - check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); - } - // ==================================================================================================== - - FOR( i = 0; i < frame_len; i++ ) { // e_fast_fx[i] = L_add( L_abs( e_fast_fx[i] ), L_shr( IVAS_TDET_PARM_ENV_EPS_fx, q_factor_diff ) ); /*Q14*/ @@ -507,68 +491,12 @@ void ivas_td_decorr_get_ducking_gains_fx( move16(); } - // ==================================================================================================== - // Word32 test_e_slow_fx[L_FRAME48k]; - // Word32 env_eps_fx = IVAS_TDET_PARM_ENV_EPS_fx; - // Word16 env_eps_q = Q31; - - // Word16 q_diff = sub( q_fast, env_eps_q ); - // q_fast = s_min( q_fast, env_eps_q ); - - // if ( q_diff >= 0 ) - // { - // for ( i = 0; i < frame_len; i++ ) - // { - // test_e_fast_fx[i] = L_add( L_abs( L_shr( test_e_fast_fx[i], q_diff ) ), env_eps_fx ); - // move32(); - // test_e_slow_fx[i] = test_e_fast_fx[i]; - // move32(); - // } - // } - // else - // { - // env_eps_fx = L_shl( env_eps_fx, q_diff ); - // for ( i = 0; i < frame_len; i++ ) - // { - // test_e_fast_fx[i] = L_add( L_abs( test_e_fast_fx[i] ), env_eps_fx ); - // move32(); - // test_e_slow_fx[i] = test_e_fast_fx[i]; - // move32(); - // } - // } - - // Word16 q_slow = q_fast; - - // for ( i = 0; i < frame_len; i++ ) - // { - // check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); - // } - // ==================================================================================================== - /* env fast*/ ivas_filter_process_exp_fx( &hTranDet->env_fast, e_fast_fx, frame_len, e_fast_e ); - // ==================================================================================================== - // ivas_filter_process_fx32( &hTranDet->test_env_fast, test_e_fast_fx, frame_len, q_fast ); - - // for ( i = 0; i < frame_len; i++ ) - // { - // check( test_e_fast_fx[i], q_fast, e_fast_fx[i], 31 - e_fast_e[i] ); - // } - // ==================================================================================================== - /* env slow */ ivas_filter_process_exp_fx( &hTranDet->env_slow, e_slow_fx, frame_len, e_slow_e ); - // ==================================================================================================== - // ivas_filter_process_fx32( &hTranDet->test_env_slow, test_e_slow_fx, frame_len, q_slow ); - - // for ( i = 0; i < frame_len; i++ ) - // { - // check( test_e_slow_fx[i], q_slow, e_slow_fx[i], 31 - e_slow_e[i] ); - // } - // ==================================================================================================== - IF( tdet_flag ) { FOR( i = 0; i < frame_len; i++ ) @@ -598,6 +526,5 @@ void ivas_td_decorr_get_ducking_gains_fx( } #endif - return; } diff --git a/lib_dec/ivas_lfe_dec_fx.c b/lib_dec/ivas_lfe_dec_fx.c index 74d8de662..3a6fa2c91 100644 --- a/lib_dec/ivas_lfe_dec_fx.c +++ b/lib_dec/ivas_lfe_dec_fx.c @@ -408,7 +408,11 @@ void ivas_lfe_dec_fx( IF( hLFE->filter_state.order > 0 ) { /* Low Pass Filter */ +#ifdef OPT_2239_IVAS_FILTER_PROCESS + ivas_filter_process_fx32( &hLFE->filter_state, output_lfe_ch, output_frame, q_out ); +#else ivas_filter_process_fx( &hLFE->filter_state, output_lfe_ch, output_frame, q_out ); +#endif } /* add delay to make overall max(block_offset, 11.5) */ diff --git a/lib_enc/ivas_lfe_enc_fx.c b/lib_enc/ivas_lfe_enc_fx.c index 96959c9dd..11b02ca14 100644 --- a/lib_enc/ivas_lfe_enc_fx.c +++ b/lib_enc/ivas_lfe_enc_fx.c @@ -684,7 +684,11 @@ void ivas_lfe_lpf_enc_apply_fx( const Word16 input_frame /* i : input frame length per channel */ ) { +#ifdef OPT_2239_IVAS_FILTER_PROCESS + ivas_filter_process_fx32( hLfeLpf, data_lfe_ch, input_frame, (Word16) Q11 ); +#else ivas_filter_process_fx( hLfeLpf, data_lfe_ch, input_frame, (Word16) Q11 ); +#endif return; } -- GitLab From 192c9dc294f90ab38167b260b841a56d876e0941 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 20 Nov 2025 14:54:26 +0000 Subject: [PATCH 11/24] Apply clang format. --- lib_com/ivas_filters_fx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 22a296bdd..b9f7714c9 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -205,9 +205,9 @@ static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ); * Function Mpy_64_32() * * Performs the the following operation: - * + * * z = ((int128_t)x * (int128_t)y) >> 31 - * + * * where: * - x is a 64-bit signed integer * - y is a 32-bit signed integer -- GitLab From c280a982a118f503a81eb829fa05c2f376b1141b Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 20 Nov 2025 15:03:20 +0000 Subject: [PATCH 12/24] Tidy up code. --- lib_com/ivas_filters_fx.c | 109 ++++++++++++++------------------ lib_com/ivas_stat_com.h | 14 ++-- lib_com/ivas_transient_det_fx.c | 3 - 3 files changed, 53 insertions(+), 73 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index b9f7714c9..6804e24b6 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -64,43 +64,42 @@ void ivas_filters_init_fx( FOR( i = 0; i < IVAS_BIQUAD_FILT_LEN; i++ ) { filter_state->num_fx[IVAS_FILTER_STAGE_0][i] = filt_coeff_fx[i]; - filter_state->num_e[IVAS_FILTER_STAGE_0][i] = 1; filter_state->den_fx[IVAS_FILTER_STAGE_0][i] = filt_coeff_fx[i + IVAS_BIQUAD_FILT_LEN]; - filter_state->den_e[IVAS_FILTER_STAGE_0][i] = 1; move32(); move32(); - move16(); - move16(); #ifdef OPT_2239_IVAS_FILTER_PROCESS filter_state->num_q[IVAS_FILTER_STAGE_0][i] = Q30; filter_state->den_q[IVAS_FILTER_STAGE_0][i] = Q30; move16(); move16(); +#else + filter_state->num_e[IVAS_FILTER_STAGE_0][i] = 1; + filter_state->den_e[IVAS_FILTER_STAGE_0][i] = 1; + move16(); + move16(); #endif } +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; + move64(); + move64(); + move64(); +#else filter_state->state_fx[0][0] = 0; - filter_state->state_e[0][0] = 0; filter_state->state_fx[0][1] = 0; - filter_state->state_e[0][1] = 0; filter_state->state_fx[0][2] = 0; - filter_state->state_e[0][2] = 0; move32(); move32(); move32(); + filter_state->state_e[0][0] = 0; + filter_state->state_e[0][1] = 0; + filter_state->state_e[0][2] = 0; move16(); move16(); move16(); - -#ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; - move64(); - move64(); - move64(); - filter_state->state64_q[IVAS_FILTER_STAGE_0] = Q30; - move16(); #endif } ELSE @@ -108,30 +107,16 @@ void ivas_filters_init_fx( filter_state->filt_len = IVAS_BIQUAD_FILT_LEN; move16(); -#ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_q[IVAS_FILTER_STAGE_0] = 63; - filter_state->state64_q[IVAS_FILTER_STAGE_1] = 63; -#endif - FOR( i = 0; i < IVAS_BIQUAD_FILT_LEN; i++ ) { - filter_state->num_fx[IVAS_FILTER_STAGE_0][i] = filt_coeff_fx[i]; - filter_state->num_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i]; filter_state->den_fx[IVAS_FILTER_STAGE_0][i] = filt_coeff_fx[i + IVAS_BIQUAD_FILT_LEN]; - filter_state->den_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN]; filter_state->num_fx[IVAS_FILTER_STAGE_1][i] = filt_coeff_fx[i + IVAS_BIQUAD_FILT_LEN * 2]; - filter_state->num_e[IVAS_FILTER_STAGE_1][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN * 2]; filter_state->den_fx[IVAS_FILTER_STAGE_1][i] = filt_coeff_fx[i + IVAS_BIQUAD_FILT_LEN * 3]; - filter_state->den_e[IVAS_FILTER_STAGE_1][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN * 3]; move32(); move32(); move32(); move32(); - move16(); - move16(); - move16(); - move16(); #ifdef OPT_2239_IVAS_FILTER_PROCESS filter_state->num_q[IVAS_FILTER_STAGE_0][i] = sub( 31, filt_coeff_e[i + 0 * IVAS_BIQUAD_FILT_LEN] ); filter_state->den_q[IVAS_FILTER_STAGE_0][i] = sub( 31, filt_coeff_e[i + 1 * IVAS_BIQUAD_FILT_LEN] ); @@ -141,10 +126,11 @@ void ivas_filters_init_fx( move16(); move16(); move16(); - filter_state->state64_q[IVAS_FILTER_STAGE_0] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_0], filter_state->num_q[IVAS_FILTER_STAGE_0][i] ); - filter_state->state64_q[IVAS_FILTER_STAGE_0] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_0], filter_state->den_q[IVAS_FILTER_STAGE_0][i] ); - filter_state->state64_q[IVAS_FILTER_STAGE_1] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_1], filter_state->num_q[IVAS_FILTER_STAGE_1][i] ); - filter_state->state64_q[IVAS_FILTER_STAGE_1] = s_min( filter_state->state64_q[IVAS_FILTER_STAGE_1], filter_state->den_q[IVAS_FILTER_STAGE_1][i] ); +#else + filter_state->num_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i]; + filter_state->den_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN]; + filter_state->num_e[IVAS_FILTER_STAGE_1][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN * 2]; + filter_state->den_e[IVAS_FILTER_STAGE_1][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN * 3]; move16(); move16(); move16(); @@ -152,44 +138,44 @@ void ivas_filters_init_fx( #endif } +#ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][2] = 0; + move64(); + move64(); + move64(); + move64(); + move64(); + move64(); +#else filter_state->state_fx[0][0] = 0; - filter_state->state_e[0][0] = 0; filter_state->state_fx[0][1] = 0; - filter_state->state_e[0][1] = 0; filter_state->state_fx[0][2] = 0; - filter_state->state_e[0][2] = 0; filter_state->state_fx[1][0] = 0; - filter_state->state_e[1][0] = 0; filter_state->state_fx[1][1] = 0; - filter_state->state_e[1][1] = 0; filter_state->state_fx[1][2] = 0; - filter_state->state_e[1][2] = 0; move32(); move32(); move32(); move32(); move32(); move32(); + filter_state->state_e[0][0] = 0; + filter_state->state_e[0][1] = 0; + filter_state->state_e[0][2] = 0; + filter_state->state_e[1][0] = 0; + filter_state->state_e[1][1] = 0; + filter_state->state_e[1][2] = 0; move16(); move16(); move16(); move16(); move16(); move16(); - -#ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][2] = 0; - move64(); - move64(); - move64(); - move64(); - move64(); - move64(); #endif } @@ -240,28 +226,29 @@ static void ivas_iir_2_filter_fx32( { Word64 tmp_prod, tmp; Word32 in, out; - Word16 i, j, shift; + Word16 i, j, shift, state_q; + + state_q = add( q, 32 ); FOR( i = 0; i < length; i++ ) { in = pIn_Out_fx[i]; move32(); - shift = filter_state->num_q[stage][0] + q - filter_state->state64_q[stage]; + shift = filter_state->num_q[stage][0] + q - state_q; tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); - shift = sub( filter_state->state64_q[stage], q ); - pIn_Out_fx[i] = out = W_extract_l( W_shr( W_add( filter_state->state64_fx[stage][0], tmp_prod ), shift ) ); + pIn_Out_fx[i] = out = W_extract_l( W_add( filter_state->state64_fx[stage][0], tmp_prod ) ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = filter_state->num_q[stage][j] + q - filter_state->state64_q[stage]; + shift = filter_state->num_q[stage][j] + q - state_q; tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - shift = filter_state->den_q[stage][j] + q - filter_state->state64_q[stage]; + shift = filter_state->den_q[stage][j] + q - state_q; tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 97a4f58a8..7ab869605 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -656,16 +656,15 @@ typedef struct ivas_filters_process_state_t Word16 filt_len; Word32 num_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word32 den_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word32 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word16 num_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word16 den_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word16 state_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - #ifdef OPT_2239_IVAS_FILTER_PROCESS Word64 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 den_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word16 state64_q[IVAS_FILTER_MAX_STAGES]; +#else + Word32 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 num_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 den_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 state_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #endif } ivas_filters_process_state_t; @@ -680,9 +679,6 @@ typedef struct ivas_trans_det_state_t ivas_filters_process_state_t env_hpf; ivas_filters_process_state_t env_fast; ivas_filters_process_state_t env_slow; - ivas_filters_process_state_t test_env_hpf; - ivas_filters_process_state_t test_env_fast; - ivas_filters_process_state_t test_env_slow; Word32 in_duck_coeff; Word32 out_duck_coeff; Word32 in_duck_gain; diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index fca80ce82..1c9d58693 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -229,9 +229,6 @@ static void ivas_transient_det_init( ivas_filters_init_fx( &hTranDet->env_hpf, (const Word32 *) filt_coeff_arr_fx[0], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); ivas_filters_init_fx( &hTranDet->env_fast, (const Word32 *) filt_coeff_arr_fx[1], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); ivas_filters_init_fx( &hTranDet->env_slow, (const Word32 *) filt_coeff_arr_fx[2], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); - ivas_filters_init_fx( &hTranDet->test_env_hpf, (const Word32 *) filt_coeff_arr_fx[0], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); - ivas_filters_init_fx( &hTranDet->test_env_fast, (const Word32 *) filt_coeff_arr_fx[1], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); - ivas_filters_init_fx( &hTranDet->test_env_slow, (const Word32 *) filt_coeff_arr_fx[2], filt_coeff_arr_e, IVAS_FILTER_ORDER_1 ); hTranDet->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC; /*Q29*/ move32(); -- GitLab From 2a0924b8257f3eb05f98bf3362c414b7b0fea576 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 20 Nov 2025 15:47:47 +0000 Subject: [PATCH 13/24] Fix ivas_iir_2_filter_fx32. --- lib_com/ivas_filters_fx.c | 39 +++++++++++++++------------------------ lib_com/ivas_stat_com.h | 2 +- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 6804e24b6..29ca10cc4 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -80,17 +80,14 @@ void ivas_filters_init_fx( #endif } + filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; move64(); move64(); move64(); #else - filter_state->state_fx[0][0] = 0; - filter_state->state_fx[0][1] = 0; - filter_state->state_fx[0][2] = 0; move32(); move32(); move32(); @@ -138,13 +135,13 @@ void ivas_filters_init_fx( #endif } + filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][2] = 0; #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][2] = 0; move64(); move64(); move64(); @@ -152,12 +149,6 @@ void ivas_filters_init_fx( move64(); move64(); #else - filter_state->state_fx[0][0] = 0; - filter_state->state_fx[0][1] = 0; - filter_state->state_fx[0][2] = 0; - filter_state->state_fx[1][0] = 0; - filter_state->state_fx[1][1] = 0; - filter_state->state_fx[1][2] = 0; move32(); move32(); move32(); @@ -238,7 +229,7 @@ static void ivas_iir_2_filter_fx32( shift = filter_state->num_q[stage][0] + q - state_q; tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); - pIn_Out_fx[i] = out = W_extract_l( W_add( filter_state->state64_fx[stage][0], tmp_prod ) ); + pIn_Out_fx[i] = out = W_extract_h( W_add( filter_state->state_fx[stage][0], tmp_prod ) ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) @@ -246,12 +237,12 @@ static void ivas_iir_2_filter_fx32( shift = filter_state->num_q[stage][j] + q - state_q; tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); - tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); shift = filter_state->den_q[stage][j] + q - state_q; tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); - filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); } } @@ -311,7 +302,7 @@ static void ivas_iir_2_filter_fx64( shift = ( filter_state->num_q[stage][0] + q - 31 ) - q; tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + pIn_Out_fx[i] = out = W_add( filter_state->state_fx[stage][0], tmp_prod ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) @@ -319,12 +310,12 @@ static void ivas_iir_2_filter_fx64( shift = ( filter_state->num_q[stage][j] + q - 31 ) - q; tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); - tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); shift = ( filter_state->den_q[stage][j] + q - 31 ) - q; tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); - filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); } } diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 7ab869605..b46e5e66b 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -657,7 +657,7 @@ typedef struct ivas_filters_process_state_t Word32 num_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word32 den_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #ifdef OPT_2239_IVAS_FILTER_PROCESS - Word64 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word64 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 den_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #else -- GitLab From 83d041a606b8f2d4a37a57ce092928369326ae74 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 20 Nov 2025 16:41:48 +0000 Subject: [PATCH 14/24] Debug fx32. --- lib_com/ivas_filters_fx.c | 67 +++++++++++++++++++++++---------------- lib_com/ivas_prot_fx.h | 2 +- lib_com/ivas_stat_com.h | 4 +-- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 29ca10cc4..92c773928 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -72,7 +72,7 @@ void ivas_filters_init_fx( filter_state->den_q[IVAS_FILTER_STAGE_0][i] = Q30; move16(); move16(); -#else + // #else FIXME filter_state->num_e[IVAS_FILTER_STAGE_0][i] = 1; filter_state->den_e[IVAS_FILTER_STAGE_0][i] = 1; move16(); @@ -80,14 +80,17 @@ void ivas_filters_init_fx( #endif } - filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; #ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; move64(); move64(); move64(); -#else + // #else FIXME + filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; move32(); move32(); move32(); @@ -123,7 +126,7 @@ void ivas_filters_init_fx( move16(); move16(); move16(); -#else + // #else FIXME filter_state->num_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i]; filter_state->den_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN]; filter_state->num_e[IVAS_FILTER_STAGE_1][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN * 2]; @@ -135,20 +138,26 @@ void ivas_filters_init_fx( #endif } - filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_1][0] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_1][1] = 0; - filter_state->state_fx[IVAS_FILTER_STAGE_1][2] = 0; #ifdef OPT_2239_IVAS_FILTER_PROCESS + filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][0] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][1] = 0; + filter_state->state64_fx[IVAS_FILTER_STAGE_1][2] = 0; move64(); move64(); move64(); move64(); move64(); move64(); -#else + // #else FIXME + filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][2] = 0; move32(); move32(); move32(); @@ -219,30 +228,28 @@ static void ivas_iir_2_filter_fx32( Word32 in, out; Word16 i, j, shift, state_q; - state_q = add( q, 32 ); - FOR( i = 0; i < length; i++ ) { in = pIn_Out_fx[i]; move32(); - shift = filter_state->num_q[stage][0] + q - state_q; + shift = sub( filter_state->num_q[stage][0], 32 ); tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); - pIn_Out_fx[i] = out = W_extract_h( W_add( filter_state->state_fx[stage][0], tmp_prod ) ); + pIn_Out_fx[i] = out = W_extract_h( W_add( filter_state->state64_fx[stage][0], tmp_prod ) ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = filter_state->num_q[stage][j] + q - state_q; + shift = sub( filter_state->num_q[stage][j], 32 ); tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); - tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); + tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - shift = filter_state->den_q[stage][j] + q - state_q; + shift = sub( filter_state->den_q[stage][j], 32 ); tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); - filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); } } @@ -262,6 +269,9 @@ void ivas_filter_process_fx32( const Word16 length, /* i : filter order */ Word16 q ) { +#if 1 + ivas_filter_process_fx( filter_state, pIn_Out_fx, length, q ); +#else SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: @@ -274,6 +284,7 @@ void ivas_filter_process_fx32( default: BREAK; } +#endif return; } @@ -299,23 +310,23 @@ static void ivas_iir_2_filter_fx64( in = pIn_Out_fx[i]; move32(); - shift = ( filter_state->num_q[stage][0] + q - 31 ) - q; + shift = sub( filter_state->num_q[stage][0], 31 ); tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - pIn_Out_fx[i] = out = W_add( filter_state->state_fx[stage][0], tmp_prod ); + pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = ( filter_state->num_q[stage][j] + q - 31 ) - q; + shift = sub( filter_state->num_q[stage][j], 31 ); tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); - tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); + tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - shift = ( filter_state->den_q[stage][j] + q - 31 ) - q; + shift = sub( filter_state->den_q[stage][j], 31 ); tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); - filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); } } @@ -351,7 +362,7 @@ void ivas_filter_process_fx64( return; } -#else +// #else FIXME static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); /*-----------------------------------------------------------------------------------------* diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index ce6c223e3..6a9b5b32a 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3817,7 +3817,7 @@ void ivas_filter_process_fx64( const Word16 length, /* i : filter order */ Word16 q ); -#else +// #else FIXME void ivas_filter_process_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index b46e5e66b..4da7e53aa 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -657,10 +657,10 @@ typedef struct ivas_filters_process_state_t Word32 num_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word32 den_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #ifdef OPT_2239_IVAS_FILTER_PROCESS - Word64 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word64 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 den_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; -#else + // #else FIXME Word32 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 den_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; -- GitLab From 52dee0c437cfb63122791fdd9995bc386a67a411 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 21 Nov 2025 08:13:49 +0000 Subject: [PATCH 15/24] Debug fx32. --- lib_com/ivas_filters_fx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 92c773928..37ba0f20f 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -216,7 +216,7 @@ static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) * * Process call for filtering a signal *-----------------------------------------------------------------------------------------*/ - +#if 0 static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, @@ -226,7 +226,7 @@ static void ivas_iir_2_filter_fx32( { Word64 tmp_prod, tmp; Word32 in, out; - Word16 i, j, shift, state_q; + Word16 i, j, shift; FOR( i = 0; i < length; i++ ) { @@ -256,6 +256,7 @@ static void ivas_iir_2_filter_fx32( return; } +#endif /*-----------------------------------------------------------------------------------------* * Function ivas_filter_process_fx32() -- GitLab From bd1617b756ae69e0a1a19c610954394fd0221247 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 21 Nov 2025 08:45:20 +0000 Subject: [PATCH 16/24] Debug fx32. --- lib_com/ivas_filters_fx.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 37ba0f20f..d93bf720f 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -183,7 +183,6 @@ void ivas_filters_init_fx( } #ifdef OPT_2239_IVAS_FILTER_PROCESS -static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ); @@ -217,6 +216,7 @@ static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) * Process call for filtering a signal *-----------------------------------------------------------------------------------------*/ #if 0 +static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, @@ -233,21 +233,21 @@ static void ivas_iir_2_filter_fx32( in = pIn_Out_fx[i]; move32(); - shift = sub( filter_state->num_q[stage][0], 32 ); - tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][0], in ), shift ); + shift = sub( filter_state->num_q[stage][0], 31 ); // (num_q + q + 1) - (q + 32) + tmp_prod = W_shr( W_mult_32_32( filter_state->num_fx[stage][0], in ), shift ); pIn_Out_fx[i] = out = W_extract_h( W_add( filter_state->state64_fx[stage][0], tmp_prod ) ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = sub( filter_state->num_q[stage][j], 32 ); - tmp_prod = W_shr( W_mult0_32_32( filter_state->num_fx[stage][j], in ), shift ); + shift = sub( filter_state->num_q[stage][j], 31 ); + tmp_prod = W_shr( W_mult_32_32( filter_state->num_fx[stage][j], in ), shift ); tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - shift = sub( filter_state->den_q[stage][j], 32 ); - tmp_prod = W_shr( W_mult0_32_32( filter_state->den_fx[stage][j], out ), shift ); + shift = sub( filter_state->den_q[stage][j], 31 ); + tmp_prod = W_shr( W_mult_32_32( filter_state->den_fx[stage][j], out ), shift ); filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); @@ -311,7 +311,7 @@ static void ivas_iir_2_filter_fx64( in = pIn_Out_fx[i]; move32(); - shift = sub( filter_state->num_q[stage][0], 31 ); + shift = sub( filter_state->num_q[stage][0], 31 ); // (q + numq - 31) - q tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); -- GitLab From 106c565791fa5aedb76ace83bcefa0db5e756a76 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 21 Nov 2025 09:10:49 +0000 Subject: [PATCH 17/24] Debug fx32. --- lib_com/ivas_filters_fx.c | 26 ++++++++++++-------------- lib_com/ivas_prot_fx.h | 3 +-- lib_com/ivas_transient_det_fx.c | 6 +++--- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index d93bf720f..20a1669bd 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -183,7 +183,7 @@ void ivas_filters_init_fx( } #ifdef OPT_2239_IVAS_FILTER_PROCESS -static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); +static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage ); static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ); /*-----------------------------------------------------------------------------------------* @@ -216,13 +216,12 @@ static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) * Process call for filtering a signal *-----------------------------------------------------------------------------------------*/ #if 0 -static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 q ); +static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage ); static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, - const Word16 stage, - Word16 q ) + const Word16 stage ) { Word64 tmp_prod, tmp; Word32 in, out; @@ -276,11 +275,11 @@ void ivas_filter_process_fx32( SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); BREAK; case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); + ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1 ); BREAK; default: BREAK; @@ -300,8 +299,7 @@ static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, - const Word16 stage, - Word16 q ) + const Word16 stage ) { Word64 tmp_prod, tmp, in, out; Word16 i, j, shift; @@ -344,17 +342,17 @@ static void ivas_iir_2_filter_fx64( void ivas_filter_process_fx64( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word64 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ - const Word16 length, /* i : filter order */ - Word16 q ) + const Word16 length ) /* i : filter order */ + { SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); BREAK; case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0, q ); - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1, q ); + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); + ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1 ); BREAK; default: BREAK; diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 6a9b5b32a..4a25844a3 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3814,8 +3814,7 @@ void ivas_filter_process_fx32( void ivas_filter_process_fx64( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word64 *pIn_Out_fx, /* i : signal subject to filtering */ - const Word16 length, /* i : filter order */ - Word16 q + const Word16 length /* i : filter order */ ); // #else FIXME void ivas_filter_process_fx( diff --git a/lib_com/ivas_transient_det_fx.c b/lib_com/ivas_transient_det_fx.c index 1c9d58693..ac285873c 100644 --- a/lib_com/ivas_transient_det_fx.c +++ b/lib_com/ivas_transient_det_fx.c @@ -408,7 +408,7 @@ void ivas_td_decorr_get_ducking_gains_fx( } /* env hpf */ - ivas_filter_process_fx64( &hTranDet->env_hpf, e_fast_fx, frame_len, Q43 ); + ivas_filter_process_fx64( &hTranDet->env_hpf, e_fast_fx, frame_len ); /*Q43*/ FOR( i = 0; i < frame_len; i++ ) { @@ -419,10 +419,10 @@ void ivas_td_decorr_get_ducking_gains_fx( } /* env fast*/ - ivas_filter_process_fx64( &hTranDet->env_fast, e_fast_fx, frame_len, Q43 ); + ivas_filter_process_fx64( &hTranDet->env_fast, e_fast_fx, frame_len ); /*Q43*/ /* env slow */ - ivas_filter_process_fx64( &hTranDet->env_slow, e_slow_fx, frame_len, Q43 ); + ivas_filter_process_fx64( &hTranDet->env_slow, e_slow_fx, frame_len ); /*Q43*/ IF( tdet_flag ) { -- GitLab From 291b49038326b7ad5996359f9aaeb67543b87d9f Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 21 Nov 2025 10:01:36 +0000 Subject: [PATCH 18/24] Add headroom to state. --- lib_com/ivas_filters_fx.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 20a1669bd..f58c35e71 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -309,20 +309,21 @@ static void ivas_iir_2_filter_fx64( in = pIn_Out_fx[i]; move32(); - shift = sub( filter_state->num_q[stage][0], 31 ); // (q + numq - 31) - q + shift = sub( filter_state->num_q[stage][0], 30 ); tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + pIn_Out_fx[i] = W_shl( out, 1 ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = sub( filter_state->num_q[stage][j], 31 ); + shift = sub( filter_state->num_q[stage][j], 30 ); tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - shift = sub( filter_state->den_q[stage][j], 31 ); + shift = sub( filter_state->den_q[stage][j], 30 ); tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); -- GitLab From dedd38232edf865c8e36922fa01f1437841321e6 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 21 Nov 2025 10:24:42 +0000 Subject: [PATCH 19/24] Increase precision in ivas_iir_2_filter_fx32. --- lib_com/ivas_filters_fx.c | 37 +++++++++++++++---------------------- lib_com/ivas_prot_fx.h | 3 +-- lib_dec/ivas_lfe_dec_fx.c | 2 +- lib_enc/ivas_lfe_enc_fx.c | 2 +- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index f58c35e71..d11088adf 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -183,6 +183,7 @@ void ivas_filters_init_fx( } #ifdef OPT_2239_IVAS_FILTER_PROCESS +static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage ); static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage ); static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ); @@ -215,38 +216,37 @@ static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) * * Process call for filtering a signal *-----------------------------------------------------------------------------------------*/ -#if 0 -static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage ); + static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage ) { - Word64 tmp_prod, tmp; - Word32 in, out; + Word64 tmp_prod, tmp, in, out; Word16 i, j, shift; FOR( i = 0; i < length; i++ ) { - in = pIn_Out_fx[i]; + in = W_deposit32_h( pIn_Out_fx[i] ); move32(); - shift = sub( filter_state->num_q[stage][0], 31 ); // (num_q + q + 1) - (q + 32) - tmp_prod = W_shr( W_mult_32_32( filter_state->num_fx[stage][0], in ), shift ); + shift = sub( filter_state->num_q[stage][0], 31 ); + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - pIn_Out_fx[i] = out = W_extract_h( W_add( filter_state->state64_fx[stage][0], tmp_prod ) ); + out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); + pIn_Out_fx[i] = W_extract_h( out ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { shift = sub( filter_state->num_q[stage][j], 31 ); - tmp_prod = W_shr( W_mult_32_32( filter_state->num_fx[stage][j], in ), shift ); + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); shift = sub( filter_state->den_q[stage][j], 31 ); - tmp_prod = W_shr( W_mult_32_32( filter_state->den_fx[stage][j], out ), shift ); + tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); @@ -255,7 +255,6 @@ static void ivas_iir_2_filter_fx32( return; } -#endif /*-----------------------------------------------------------------------------------------* * Function ivas_filter_process_fx32() @@ -266,12 +265,8 @@ static void ivas_iir_2_filter_fx32( void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ - const Word16 length, /* i : filter order */ - Word16 q ) + const Word16 length ) /* i : filter order */ { -#if 1 - ivas_filter_process_fx( filter_state, pIn_Out_fx, length, q ); -#else SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: @@ -284,7 +279,6 @@ void ivas_filter_process_fx32( default: BREAK; } -#endif return; } @@ -309,21 +303,20 @@ static void ivas_iir_2_filter_fx64( in = pIn_Out_fx[i]; move32(); - shift = sub( filter_state->num_q[stage][0], 30 ); + shift = sub( filter_state->num_q[stage][0], 31 ); tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); - pIn_Out_fx[i] = W_shl( out, 1 ); + pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); move32(); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = sub( filter_state->num_q[stage][j], 30 ); + shift = sub( filter_state->num_q[stage][j], 31 ); tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - shift = sub( filter_state->den_q[stage][j], 30 ); + shift = sub( filter_state->den_q[stage][j], 31 ); tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 4a25844a3..3124b7537 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3807,8 +3807,7 @@ void ivas_lfe_enc_fx( void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ - const Word16 length, /* i : filter order */ - Word16 q + const Word16 length /* i : filter order */ ); void ivas_filter_process_fx64( diff --git a/lib_dec/ivas_lfe_dec_fx.c b/lib_dec/ivas_lfe_dec_fx.c index 3a6fa2c91..1078a1a02 100644 --- a/lib_dec/ivas_lfe_dec_fx.c +++ b/lib_dec/ivas_lfe_dec_fx.c @@ -409,7 +409,7 @@ void ivas_lfe_dec_fx( { /* Low Pass Filter */ #ifdef OPT_2239_IVAS_FILTER_PROCESS - ivas_filter_process_fx32( &hLFE->filter_state, output_lfe_ch, output_frame, q_out ); + ivas_filter_process_fx32( &hLFE->filter_state, output_lfe_ch, output_frame ); #else ivas_filter_process_fx( &hLFE->filter_state, output_lfe_ch, output_frame, q_out ); #endif diff --git a/lib_enc/ivas_lfe_enc_fx.c b/lib_enc/ivas_lfe_enc_fx.c index 11b02ca14..96fdc7b5c 100644 --- a/lib_enc/ivas_lfe_enc_fx.c +++ b/lib_enc/ivas_lfe_enc_fx.c @@ -685,7 +685,7 @@ void ivas_lfe_lpf_enc_apply_fx( ) { #ifdef OPT_2239_IVAS_FILTER_PROCESS - ivas_filter_process_fx32( hLfeLpf, data_lfe_ch, input_frame, (Word16) Q11 ); + ivas_filter_process_fx32( hLfeLpf, data_lfe_ch, input_frame ); #else ivas_filter_process_fx( hLfeLpf, data_lfe_ch, input_frame, (Word16) Q11 ); #endif -- GitLab From 32180c9b5507331f59bd1f74aa7aee8c81f7acc4 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Fri, 21 Nov 2025 14:07:25 +0000 Subject: [PATCH 20/24] Implement ivas_iir_2_filter_fx. --- lib_com/ivas_filters_fx.c | 178 ++++++++++++++++++-------------------- lib_com/ivas_prot_fx.h | 2 +- lib_com/ivas_stat_com.h | 4 +- 3 files changed, 86 insertions(+), 98 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index d11088adf..bbde0fff4 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -72,7 +72,7 @@ void ivas_filters_init_fx( filter_state->den_q[IVAS_FILTER_STAGE_0][i] = Q30; move16(); move16(); - // #else FIXME +#else filter_state->num_e[IVAS_FILTER_STAGE_0][i] = 1; filter_state->den_e[IVAS_FILTER_STAGE_0][i] = 1; move16(); @@ -81,13 +81,13 @@ void ivas_filters_init_fx( } #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; move64(); move64(); move64(); - // #else FIXME +#else filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; @@ -126,7 +126,7 @@ void ivas_filters_init_fx( move16(); move16(); move16(); - // #else FIXME +#else filter_state->num_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i]; filter_state->den_e[IVAS_FILTER_STAGE_0][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN]; filter_state->num_e[IVAS_FILTER_STAGE_1][i] = filt_coeff_e[i + IVAS_BIQUAD_FILT_LEN * 2]; @@ -139,19 +139,19 @@ void ivas_filters_init_fx( } #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->state64_fx[IVAS_FILTER_STAGE_0][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_0][2] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][0] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][1] = 0; - filter_state->state64_fx[IVAS_FILTER_STAGE_1][2] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][0] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][1] = 0; + filter_state->state_fx[IVAS_FILTER_STAGE_1][2] = 0; move64(); move64(); move64(); move64(); move64(); move64(); - // #else FIXME +#else filter_state->state_fx[IVAS_FILTER_STAGE_0][0] = 0; filter_state->state_fx[IVAS_FILTER_STAGE_0][1] = 0; filter_state->state_fx[IVAS_FILTER_STAGE_0][2] = 0; @@ -183,8 +183,7 @@ void ivas_filters_init_fx( } #ifdef OPT_2239_IVAS_FILTER_PROCESS -static void ivas_iir_2_filter_fx32( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage ); -static void ivas_iir_2_filter_fx64( ivas_filters_process_state_t *filter_state, Word64 *pIn_Out_fx, const Word16 length, const Word16 stage ); +static Word64 ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, const Word16 stage, const Word64 in ); static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ); /*-----------------------------------------------------------------------------------------* @@ -212,48 +211,39 @@ static Word64 Mpy_64_32( Word64 W_var1, Word32 L_var2 ) } /*-----------------------------------------------------------------------------------------* - * Function ivas_iir_2_filter_fx32() + * Function ivas_iir_2_filter_fx() * - * Process call for filtering a signal + * Process call for filtering a sample *-----------------------------------------------------------------------------------------*/ -static void ivas_iir_2_filter_fx32( +static Word64 ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, - Word32 *pIn_Out_fx, - const Word16 length, - const Word16 stage ) + const Word16 stage, + const Word64 in ) { - Word64 tmp_prod, tmp, in, out; - Word16 i, j, shift; - - FOR( i = 0; i < length; i++ ) - { - in = W_deposit32_h( pIn_Out_fx[i] ); - move32(); + Word64 tmp_prod, tmp, out; + Word16 j, shift; - shift = sub( filter_state->num_q[stage][0], 31 ); - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); + shift = sub( filter_state->num_q[stage][0], 31 ); + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); - pIn_Out_fx[i] = W_extract_h( out ); - move32(); + out = W_add( filter_state->state_fx[stage][0], tmp_prod ); - FOR( j = 1; j < filter_state->filt_len; j++ ) - { - shift = sub( filter_state->num_q[stage][j], 31 ); - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); + FOR( j = 1; j < filter_state->filt_len; j++ ) + { + shift = sub( filter_state->num_q[stage][j], 31 ); + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); - tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); + tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); - shift = sub( filter_state->den_q[stage][j], 31 ); - tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); + shift = sub( filter_state->den_q[stage][j], 31 ); + tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); - filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); - move32(); - } + filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); + move32(); } - return; + return out; } /*-----------------------------------------------------------------------------------------* @@ -267,14 +257,35 @@ void ivas_filter_process_fx32( Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ const Word16 length ) /* i : filter order */ { + Word64 in, out; + Word16 i; + SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); + FOR( i = 0; i < length; i++ ) + { + in = W_deposit32_h( pIn_Out_fx[i] ); + move32(); + + out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_0, in ); + + pIn_Out_fx[i] = W_extract_h( out ); + move32(); + } BREAK; case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); - ivas_iir_2_filter_fx32( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1 ); + FOR( i = 0; i < length; i++ ) + { + in = W_deposit32_h( pIn_Out_fx[i] ); + move32(); + + out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_0, in ); + out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_1, out ); + + pIn_Out_fx[i] = W_extract_h( out ); + move32(); + } BREAK; default: BREAK; @@ -283,50 +294,6 @@ void ivas_filter_process_fx32( return; } -/*-----------------------------------------------------------------------------------------* - * Function ivas_iir_2_filter_fx64() - * - * Process call for filtering a signal - *-----------------------------------------------------------------------------------------*/ - -static void ivas_iir_2_filter_fx64( - ivas_filters_process_state_t *filter_state, - Word64 *pIn_Out_fx, - const Word16 length, - const Word16 stage ) -{ - Word64 tmp_prod, tmp, in, out; - Word16 i, j, shift; - - FOR( i = 0; i < length; i++ ) - { - in = pIn_Out_fx[i]; - move32(); - - shift = sub( filter_state->num_q[stage][0], 31 ); - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); - - pIn_Out_fx[i] = out = W_add( filter_state->state64_fx[stage][0], tmp_prod ); - move32(); - - FOR( j = 1; j < filter_state->filt_len; j++ ) - { - shift = sub( filter_state->num_q[stage][j], 31 ); - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); - - tmp = W_add( filter_state->state64_fx[stage][j], tmp_prod ); - - shift = sub( filter_state->den_q[stage][j], 31 ); - tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); - - filter_state->state64_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); - move32(); - } - } - - return; -} - /*-----------------------------------------------------------------------------------------* * Function ivas_filter_process_fx64() * @@ -339,14 +306,35 @@ void ivas_filter_process_fx64( const Word16 length ) /* i : filter order */ { + Word64 in, out; + Word16 i; + SWITCH( filter_state->order ) { case IVAS_FILTER_ORDER_1: - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); + FOR( i = 0; i < length; i++ ) + { + in = pIn_Out_fx[i]; + move64(); + + out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_0, in ); + + pIn_Out_fx[i] = out; + move64(); + } BREAK; case IVAS_FILTER_ORDER_4: - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_0 ); - ivas_iir_2_filter_fx64( filter_state, pIn_Out_fx, length, IVAS_FILTER_STAGE_1 ); + FOR( i = 0; i < length; i++ ) + { + in = pIn_Out_fx[i]; + move64(); + + out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_0, in ); + out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_1, out ); + + pIn_Out_fx[i] = out; + move64(); + } BREAK; default: BREAK; @@ -355,7 +343,7 @@ void ivas_filter_process_fx64( return; } -// #else FIXME +#else static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Word32 *pIn_Out_fx, const Word16 length, const Word16 stage, Word16 *pIn_Out_e ); /*-----------------------------------------------------------------------------------------* diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 3124b7537..318ad9c2c 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3815,7 +3815,7 @@ void ivas_filter_process_fx64( Word64 *pIn_Out_fx, /* i : signal subject to filtering */ const Word16 length /* i : filter order */ ); -// #else FIXME +#else void ivas_filter_process_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 4da7e53aa..b46e5e66b 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -657,10 +657,10 @@ typedef struct ivas_filters_process_state_t Word32 num_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word32 den_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #ifdef OPT_2239_IVAS_FILTER_PROCESS - Word64 state64_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word64 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 den_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - // #else FIXME +#else Word32 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 den_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; -- GitLab From 18eeb708eb378b3cec2c961ad22d4a0830ebfea0 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Mon, 24 Nov 2025 08:40:51 +0000 Subject: [PATCH 21/24] Finalize optimization. --- lib_com/ivas_filters_fx.c | 27 ++++++++++----------------- lib_com/ivas_stat_com.h | 4 ++-- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index bbde0fff4..becb59c21 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -68,8 +68,8 @@ void ivas_filters_init_fx( move32(); move32(); #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->num_q[IVAS_FILTER_STAGE_0][i] = Q30; - filter_state->den_q[IVAS_FILTER_STAGE_0][i] = Q30; + filter_state->num_shr[IVAS_FILTER_STAGE_0][i] = Q30 - Q31; + filter_state->den_shr[IVAS_FILTER_STAGE_0][i] = Q30 - Q31; move16(); move16(); #else @@ -118,10 +118,10 @@ void ivas_filters_init_fx( move32(); move32(); #ifdef OPT_2239_IVAS_FILTER_PROCESS - filter_state->num_q[IVAS_FILTER_STAGE_0][i] = sub( 31, filt_coeff_e[i + 0 * IVAS_BIQUAD_FILT_LEN] ); - filter_state->den_q[IVAS_FILTER_STAGE_0][i] = sub( 31, filt_coeff_e[i + 1 * IVAS_BIQUAD_FILT_LEN] ); - filter_state->num_q[IVAS_FILTER_STAGE_1][i] = sub( 31, filt_coeff_e[i + 2 * IVAS_BIQUAD_FILT_LEN] ); - filter_state->den_q[IVAS_FILTER_STAGE_1][i] = sub( 31, filt_coeff_e[i + 3 * IVAS_BIQUAD_FILT_LEN] ); + filter_state->num_shr[IVAS_FILTER_STAGE_0][i] = sub( sub( 31, filt_coeff_e[i + 0 * IVAS_BIQUAD_FILT_LEN] ), Q31 ); + filter_state->den_shr[IVAS_FILTER_STAGE_0][i] = sub( sub( 31, filt_coeff_e[i + 1 * IVAS_BIQUAD_FILT_LEN] ), Q31 ); + filter_state->num_shr[IVAS_FILTER_STAGE_1][i] = sub( sub( 31, filt_coeff_e[i + 2 * IVAS_BIQUAD_FILT_LEN] ), Q31 ); + filter_state->den_shr[IVAS_FILTER_STAGE_1][i] = sub( sub( 31, filt_coeff_e[i + 3 * IVAS_BIQUAD_FILT_LEN] ), Q31 ); move16(); move16(); move16(); @@ -222,23 +222,16 @@ static Word64 ivas_iir_2_filter_fx( const Word64 in ) { Word64 tmp_prod, tmp, out; - Word16 j, shift; - - shift = sub( filter_state->num_q[stage][0], 31 ); - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), shift ); + Word16 j; + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][0] ), filter_state->num_shr[stage][0] ); out = W_add( filter_state->state_fx[stage][0], tmp_prod ); FOR( j = 1; j < filter_state->filt_len; j++ ) { - shift = sub( filter_state->num_q[stage][j], 31 ); - tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), shift ); - + tmp_prod = W_shr( Mpy_64_32( in, filter_state->num_fx[stage][j] ), filter_state->num_shr[stage][j] ); tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); - - shift = sub( filter_state->den_q[stage][j], 31 ); - tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), shift ); - + tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), filter_state->den_shr[stage][j] ); filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); move32(); } diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index b46e5e66b..0d4063777 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -658,8 +658,8 @@ typedef struct ivas_filters_process_state_t Word32 den_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #ifdef OPT_2239_IVAS_FILTER_PROCESS Word64 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word16 num_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; - Word16 den_q[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 num_shr[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; + Word16 den_shr[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; #else Word32 state_fx[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; Word16 num_e[IVAS_FILTER_MAX_STAGES][IVAS_BIQUAD_FILT_LEN]; -- GitLab From 95b9d07a4d656ab4d1f1817c693708b3facea7b3 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 27 Nov 2025 11:14:37 +0000 Subject: [PATCH 22/24] Add missing Q values from Q32 to Q63. --- lib_com/cnst.h | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index a6a0258bf..7f5882ca0 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -98,8 +98,38 @@ #define Q29 29 #define Q30 30 #define Q31 31 - +#define Q32 32 +#define Q33 33 +#define Q34 34 +#define Q35 35 +#define Q36 36 +#define Q37 37 +#define Q38 38 +#define Q39 39 +#define Q40 40 +#define Q41 41 +#define Q42 42 #define Q43 43 +#define Q44 44 +#define Q45 45 +#define Q46 46 +#define Q47 47 +#define Q48 48 +#define Q49 49 +#define Q50 50 +#define Q51 51 +#define Q52 52 +#define Q53 53 +#define Q54 54 +#define Q55 55 +#define Q56 56 +#define Q57 57 +#define Q58 58 +#define Q59 59 +#define Q60 60 +#define Q61 61 +#define Q62 62 +#define Q63 63 /*----------------------------------------------------------------------------------* * one in Q -- GitLab From 412658b1b01bfb5e6c1ddf21d4e338833c14e083 Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 27 Nov 2025 12:59:49 +0000 Subject: [PATCH 23/24] Address Tommy's comments. --- lib_com/ivas_filters_fx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index becb59c21..73ab4deb1 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -233,7 +233,7 @@ static Word64 ivas_iir_2_filter_fx( tmp = W_add( filter_state->state_fx[stage][j], tmp_prod ); tmp_prod = W_shr( Mpy_64_32( out, filter_state->den_fx[stage][j] ), filter_state->den_shr[stage][j] ); filter_state->state_fx[stage][j - 1] = W_sub( tmp, tmp_prod ); - move32(); + move64(); } return out; @@ -259,7 +259,6 @@ void ivas_filter_process_fx32( FOR( i = 0; i < length; i++ ) { in = W_deposit32_h( pIn_Out_fx[i] ); - move32(); out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_0, in ); @@ -271,7 +270,6 @@ void ivas_filter_process_fx32( FOR( i = 0; i < length; i++ ) { in = W_deposit32_h( pIn_Out_fx[i] ); - move32(); out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_0, in ); out = ivas_iir_2_filter_fx( filter_state, IVAS_FILTER_STAGE_1, out ); -- GitLab From 9f34f359d173d0b643069b8d120d2c46d0f7edbe Mon Sep 17 00:00:00 2001 From: Nicolas Roussin Date: Thu, 27 Nov 2025 15:10:19 +0000 Subject: [PATCH 24/24] Fixed wrong comments. --- lib_com/ivas_filters_fx.c | 12 ++++++------ lib_com/ivas_prot_fx.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib_com/ivas_filters_fx.c b/lib_com/ivas_filters_fx.c index 73ab4deb1..1e1246fda 100644 --- a/lib_com/ivas_filters_fx.c +++ b/lib_com/ivas_filters_fx.c @@ -247,8 +247,8 @@ static Word64 ivas_iir_2_filter_fx( void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ - const Word16 length ) /* i : filter order */ + Word32 *pIn_Out_fx, /* i/o: signal subject to filtering */ + const Word16 length ) /* i : number of samples to filter */ { Word64 in, out; Word16 i; @@ -293,8 +293,8 @@ void ivas_filter_process_fx32( void ivas_filter_process_fx64( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ - Word64 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q) */ - const Word16 length ) /* i : filter order */ + Word64 *pIn_Out_fx, /* i/o: signal subject to filtering */ + const Word16 length ) /* i : number of samples to filter */ { Word64 in, out; @@ -346,7 +346,7 @@ static void ivas_iir_2_filter_fx( ivas_filters_process_state_t *filter_state, Wo void ivas_filter_process_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering Q(q_factor) */ - const Word16 length, /* i : filter order */ + const Word16 length, /* i : number of samples to filter */ Word16 q_factor ) { Word16 pIn_Out_e[L_FRAME_MAX]; @@ -387,7 +387,7 @@ void ivas_filter_process_fx( void ivas_filter_process_exp_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ - const Word16 length, /* i : filter order */ + const Word16 length, /* i : number of samples to filter */ Word16 *pIn_Out_e ) { SWITCH( filter_state->order ) diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 38a5ca340..fea5d03c1 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3800,26 +3800,26 @@ void ivas_lfe_enc_fx( void ivas_filter_process_fx32( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ - const Word16 length /* i : filter order */ + const Word16 length /* i : number of samples to filter */ ); void ivas_filter_process_fx64( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word64 *pIn_Out_fx, /* i : signal subject to filtering */ - const Word16 length /* i : filter order */ + const Word16 length /* i : number of samples to filter */ ); #else void ivas_filter_process_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i : signal subject to filtering */ - const Word16 length, /* i : filter order */ + const Word16 length, /* i : number of samples to filter */ Word16 q_factor ); void ivas_filter_process_exp_fx( ivas_filters_process_state_t *filter_state, /* i/o: filter state handle */ Word32 *pIn_Out_fx, /* i/o: signal subject to filtering (exp[i] : pIn_out_e[i]) */ - const Word16 length, /* i : filter order */ + const Word16 length, /* i : number of samples to filter */ Word16 *pIn_Out_e ); #endif -- GitLab