diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index b9985a11da6c798343e70f692558d1c15df23598..5595309098a902fbd21c4fccb419d15526eaeaec 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1051,7 +1051,11 @@ enum #define IVAS_APD_16_SECT 16 #define IVAS_DECORR_PARM_LOOKAHEAD_TAU 2e-3f +#ifdef IVAS_FLOAT_FIXED +#define IVAS_DECORR_PARM_APD_TAU 42949673 // Q31 +#else #define IVAS_DECORR_PARM_APD_TAU 20e-3f +#endif /* IVAS SBA PCA */ #define IVAS_PCA_NB_SUBR 20 /* 80 -> 0.25 ms, 40 -> 0.5 ms... */ diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index c36c8207eea6351aee5c7201073eaf8d2e5a6f69..66c4c2178f2d863b62bde4b6988df81329f922e4 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -4621,6 +4621,7 @@ void ivas_transient_det_close( ivas_trans_det_state_t **hTranDet /* i/o: Transient detector handle */ ); +#ifndef IVAS_FLOAT_FIXED void ivas_transient_det_process( ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ float *pIn_pcm, /* i : input audio channels */ @@ -4636,7 +4637,23 @@ void ivas_td_decorr_get_ducking_gains( const int16_t frame_len, const int16_t tdet_flag ); +#else +void ivas_transient_det_process_fx( + ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ + Word32 *pIn_pcm, /* i : input audio channels */ + const Word16 frame_len, /* i : frame length in samples */ + Word16 transient_det[2] /* o : transient det outputs */ +); +void ivas_td_decorr_get_ducking_gains_fx( + ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ + Word32 *pIn_pcm, + Word32 *pIn_duck_gains, + Word32 *pOut_duck_gains, + const Word16 frame_len, + const Word16 tdet_flag +); +#endif #define IVAS_CMULT_FLOAT( in1_re, in1_im, in2_re, in2_im, out1_re, out1_im ) \ out1_re = ( in1_re * in2_re ) - ( in1_im * in2_im ); MAC(1); MULT(1); \ out1_im = ( in1_re * in2_im ) + ( in2_re * in1_im ); MAC(1); MULT(1); diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index ba3417a4651c8769f21a844a235f05403b246711..9f06f25f090b466de7b4940db173d478e26ecaea 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -669,12 +669,19 @@ 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; +#ifdef IVAS_FLOAT_FIXED + Word32 in_duck_coeff; + Word32 out_duck_coeff; + Word32 in_duck_gain; + Word32 out_duck_gain; + Word32 duck_mult_fac; +#else float in_duck_coeff; float out_duck_coeff; float in_duck_gain; float out_duck_gain; float duck_mult_fac; - +#endif } ivas_trans_det_state_t; diff --git a/lib_com/ivas_transient_det.c b/lib_com/ivas_transient_det.c index 7e38f8ce6788a08cb1980984e546c4f32325ce66..2421c7ed9aba974c607ba1f9bda27fe5200c95e2 100644 --- a/lib_com/ivas_transient_det.c +++ b/lib_com/ivas_transient_det.c @@ -44,8 +44,14 @@ *------------------------------------------------------------------------------------------*/ #define IVAS_TDET_PARM_ENV_EPS ( 1e-5f ) +#ifdef IVAS_FLOAT_FIXED +#define IVAS_TDET_DUCK_MULT_FAC ( 590558003 ) // Q29 +#define IVAS_TDET_PARM_TRANS_THR ( 107374182 ) // Q30 +#define IVAS_POINT_ONE_ONE_IN_Q30 ( 118111601 ) // Q30 +#else #define IVAS_TDET_DUCK_MULT_FAC ( 1.1f ) #define IVAS_TDET_PARM_TRANS_THR ( 0.1f ) +#endif #define IVAS_TDET_ONLY ( 1 ) /*env_hpf*/ @@ -63,6 +69,17 @@ #define IVAS_C_SLOW_32k ( 0.999609451284012f ) #define IVAS_C_SLOW_16k ( 0.999219055096324f ) +#ifdef IVAS_FLOAT_FIXED +/*induck*/ +#define IVAS_C_IN_DUCK_48k ( 1073294525 ) // Q30 +#define IVAS_C_IN_DUCK_32k ( 1073070945 ) // Q30 +#define IVAS_C_IN_DUCK_16k ( 1072400485 ) // Q30 + +/*outduck*/ +#define IVAS_C_OUT_DUCK_48k ( 1073294525 ) // Q30 +#define IVAS_C_OUT_DUCK_32k ( 1073070945 ) // Q30 +#define IVAS_C_OUT_DUCK_16k ( 1072400485 ) // Q30 +#else /*induck*/ #define IVAS_C_IN_DUCK_48k ( 0.999583420126834f ) #define IVAS_C_IN_DUCK_32k ( 0.999375195271816f ) @@ -72,7 +89,7 @@ #define IVAS_C_OUT_DUCK_48k ( 0.999583420126834f ) #define IVAS_C_OUT_DUCK_32k ( 0.999375195271816f ) #define IVAS_C_OUT_DUCK_16k ( 0.998750780924581f ) - +#endif /*-----------------------------------------------------------------------------------------* * Function ivas_transient_det_init() @@ -88,9 +105,13 @@ static void ivas_transient_det_init( int16_t i; float filt_coeff_arr[3][IVAS_BIQUAD_FILT_LEN << 1]; +#ifdef IVAS_FLOAT_FIXED + hTranDet->in_duck_gain = 1073741824; // Q30 + hTranDet->out_duck_gain = 1073741824; // Q30 +#else hTranDet->in_duck_gain = 1.0f; hTranDet->out_duck_gain = 1.0f; - +#endif for ( i = 0; i < 3; i++ ) { set_zero( filt_coeff_arr[i], IVAS_BIQUAD_FILT_LEN << 1 ); @@ -169,12 +190,12 @@ static void ivas_transient_det_init( ivas_error ivas_transient_det_open( ivas_trans_det_state_t **hTranDet_in, /* i/o: Transient detector handle */ - const int32_t sampling_rate /* i : sampling rate */ + const Word32 sampling_rate /* i : sampling rate */ ) { ivas_trans_det_state_t *hTranDet; - if ( ( hTranDet = (ivas_trans_det_state_t *) malloc( sizeof( ivas_trans_det_state_t ) ) ) == NULL ) + IF( ( hTranDet = (ivas_trans_det_state_t *) malloc( sizeof( ivas_trans_det_state_t ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR TD\n" ); } @@ -197,7 +218,7 @@ void ivas_transient_det_close( ivas_trans_det_state_t **hTranDet /* i/o: Transient detector handle */ ) { - if ( hTranDet == NULL || *hTranDet == NULL ) + IF( hTranDet == NULL || *hTranDet == NULL ) { return; } @@ -208,7 +229,47 @@ void ivas_transient_det_close( return; } +#ifdef IVAS_FLOAT_FIXED +/*-----------------------------------------------------------------------------------------* + * Function ivas_transient_det_process_fx() + * + * Transient detection process call + *-----------------------------------------------------------------------------------------*/ + +void ivas_transient_det_process_fx( + ivas_trans_det_state_t *hTranDet, /* i/o: SPAR TD handle */ + Word32 *pIn_pcm, /* i : input audio channels */ + const Word16 frame_len, /* i : frame length in samples */ + Word16 transient_det[2] /* o : transient det outputs */ +) +{ + Word32 in_duck_gain[L_FRAME48k]; + Word16 num_sf, sf, sf_samp, idx; + Word32 mem = hTranDet->in_duck_gain; + + ivas_td_decorr_get_ducking_gains_fx( hTranDet, pIn_pcm, in_duck_gain, NULL, frame_len, IVAS_TDET_ONLY ); + transient_det[0] = 0; + transient_det[1] = 0; + IF( GT_32( L_sub( mem, hTranDet->in_duck_gain ), IVAS_TDET_PARM_TRANS_THR ) ) + { + transient_det[0] = 1; + } + num_sf = 16; + sf_samp = frame_len / num_sf; + FOR( sf = 1; sf <= num_sf; sf++ ) + { + idx = ( sf_samp * sf ) - 1; + IF( GT_32( L_sub( mem, in_duck_gain[idx] ), IVAS_POINT_ONE_ONE_IN_Q30 ) ) + { + transient_det[1] = 1; + } + mem = in_duck_gain[idx]; + } + + return; +} +#else /*-----------------------------------------------------------------------------------------* * Function ivas_transient_det_process() * @@ -249,8 +310,8 @@ void ivas_transient_det_process( return; } - - +#endif +#ifndef IVAS_FLOAT_FIXED /*-----------------------------------------------------------------------------------------* * Function ivas_calc_duck_gain() * @@ -275,8 +336,41 @@ static float ivas_calc_duck_gain( return duck_gain_out; } +#else +/*-----------------------------------------------------------------------------------------* + * Function ivas_calc_duck_gain_fx() + * + * Calculate ducking gain utility + *-----------------------------------------------------------------------------------------*/ + +static Word32 ivas_calc_duck_gain_fx( + const Word32 duck_gain, + const Word32 duck_coeff, + const Word32 env_1, + const Word32 env_2, + const Word32 duck_mult_fac ) +{ + Word32 duck_gain_out; + duck_gain_out = L_add( L_shl( Mpy_32_32( L_sub( duck_gain, ONE_IN_Q30 ), duck_coeff ), Q1 ), ONE_IN_Q30 ); + IF ( LT_32( Mpy_32_32( duck_mult_fac, env_1 ), Mpy_32_32( L_shr( duck_gain_out, 1 ), env_2 ) ) ) + { + IF ( EQ_32( env_1, 0 ) || EQ_32( env_2, 0 ) ) + { + duck_gain_out = 0; + } + else + { + duck_gain_out = Mpy_32_32( duck_mult_fac, L_shl( (Word32) ( divide3232( env_1, env_2 ) ), Q16 ) ); + duck_gain_out = L_shl( duck_gain_out, Q1 ); + } + } + + return duck_gain_out; +} +#endif +#ifndef IVAS_FLOAT_FIXED /*-----------------------------------------------------------------------------------------* * Function ivas_td_decorr_get_ducking_gains() * @@ -340,3 +434,80 @@ void ivas_td_decorr_get_ducking_gains( return; } + +#else +/*-----------------------------------------------------------------------------------------* + * Function ivas_td_decorr_get_ducking_gains_fx() + * + * Calculate in/out ducking gains + *-----------------------------------------------------------------------------------------*/ + +void ivas_td_decorr_get_ducking_gains_fx( + ivas_trans_det_state_t *hTranDet, /* i/o: Transient detector handle */ + Word32 *pIn_pcm, + Word32 *pIn_duck_gains, + Word32 *pOut_duck_gains, + const Word16 frame_len, + const Word16 tdet_flag ) +{ + Word16 i, q = Q15; + float e_fast[L_FRAME48k], e_slow[L_FRAME48k]; + Word32 e_fast_fx[L_FRAME48k], e_slow_fx[L_FRAME48k]; + Word32 in_duck_gain = hTranDet->in_duck_gain; + Word32 out_duck_gain = hTranDet->out_duck_gain; + Word32 in_duck_coeff = hTranDet->in_duck_coeff; + Word32 out_duck_coeff = hTranDet->out_duck_coeff; + Word32 duck_mult_fac = hTranDet->duck_mult_fac; + + mvl2l( pIn_pcm, e_fast_fx, frame_len ); + + for ( i = 0; i < frame_len; i++ ) + { + e_fast[i] = ( e_fast_fx[i] / (float) ( 1 << q ) ); + } + + /* env hpf */ + ivas_filter_process( &hTranDet->env_hpf, e_fast, frame_len ); + + for ( i = 0; i < frame_len; i++ ) + { + e_fast[i] = (float) fabs( e_fast[i] ) + IVAS_TDET_PARM_ENV_EPS; + e_slow[i] = e_fast[i]; + } + + /* env fast*/ + ivas_filter_process( &hTranDet->env_fast, e_fast, frame_len ); + + /* env slow */ + ivas_filter_process( &hTranDet->env_slow, e_slow, frame_len ); + + for ( i = 0; i < frame_len; i++ ) + { + e_fast_fx[i] = (Word32) ( e_fast[i] * ( 1 << q ) ); + e_slow_fx[i] = (Word32) ( e_slow[i] * ( 1 << q ) ); + } + 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], e_fast_fx[i], duck_mult_fac ); + pIn_duck_gains[i] = in_duck_gain; + } + hTranDet->in_duck_gain = in_duck_gain; + } + 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], e_fast_fx[i], duck_mult_fac ); + pIn_duck_gains[i] = in_duck_gain; + out_duck_gain = ivas_calc_duck_gain_fx( out_duck_gain, out_duck_coeff, e_fast_fx[i], e_slow_fx[i], duck_mult_fac ); + pOut_duck_gains[i] = out_duck_gain; + } + hTranDet->in_duck_gain = in_duck_gain; + hTranDet->out_duck_gain = out_duck_gain; + } + + return; +} +#endif \ No newline at end of file diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 041bc3068be3d63dc2daf2bbf2323923fc6caaf0..18739ef026a4850cc836ea10f95f5f7138deac46 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -7539,4 +7539,13 @@ ivas_error evs_dec_fx( Word16 output_sp[], /* o : output synthesis signal */ frameMode_fx frameMode /* i : Decoder frame mode */ ); +#endif + +#ifdef IVAS_FLOAT_FIXED +void delay_signal_fx( + Word32 x[], /* i/o: signal to be delayed */ + const Word16 len, /* i : length of the input signal */ + Word32 mem[], /* i/o: synchronization memory */ + const Word16 delay /* i : delay in samples */ +); #endif \ No newline at end of file diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 3464943fa85b1298db1c2eff316a5dfa0748f1d8..cafd3dbf9387394f7619609398e454cfadd05758 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -3036,3 +3036,23 @@ void delay_signal( return; } + +#ifdef IVAS_FLOAT_FIXED +void delay_signal_fx( + Word32 x[], /* i/o: signal to be delayed */ + const Word16 len, /* i : length of the input signal */ + Word32 mem[], /* i/o: synchronization memory */ + const int16_t delay /* i : delay in samples */ +) +{ + + Word32 tmp_buffer[L_FRAME48k]; + + Copy32( mem, tmp_buffer, delay ); + Copy32( x + len - delay, mem, delay ); + Copy32( x, x + delay, len - delay ); + Copy32( tmp_buffer, x, delay ); + + return; +} +#endif \ No newline at end of file diff --git a/lib_dec/ivas_mc_paramupmix_dec.c b/lib_dec/ivas_mc_paramupmix_dec.c index efc15aa597cb1cbe6e99f26f7098ffd7958ab4b4..529bec9c655fdd271c65b78e5997066b78127a71 100644 --- a/lib_dec/ivas_mc_paramupmix_dec.c +++ b/lib_dec/ivas_mc_paramupmix_dec.c @@ -35,6 +35,9 @@ #include #include "cnst.h" #include "prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#endif #include "ivas_prot.h" #include "ivas_prot_rend.h" #include "ivas_cnst.h" @@ -315,7 +318,11 @@ ivas_error ivas_mc_paramupmix_dec_open( for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) { +#ifdef IVAS_FLOAT_FIXED + ivas_td_decorr_dec_open_fx( &( hMCParamUpmix->hTdDecorr[i] ), output_Fs, 2, 1 ); +#else ivas_td_decorr_dec_open( &( hMCParamUpmix->hTdDecorr[i] ), output_Fs, 2, 1 ); +#endif } for ( i = 0; i < MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; i++ ) @@ -427,7 +434,62 @@ void ivas_mc_paramupmix_dec_close( return; } +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------- + * paramupmix_td_decorr_process_jbm_fx() + * + * + *------------------------------------------------------------------------*/ + +static void paramupmix_td_decorr_process_jbm_fx( + ivas_td_decorr_state_t *hTdDecorr[], /* i/o: SPAR Covar. decoder handle */ + Word32 *pcm_in[], /* i : input audio channels */ + Word32 **pp_out_pcm, /* o : output audio channels */ + const Word16 output_frame, /* i : output frame length */ + Word32 *q_format ) +{ + Word16 j, k; + Word16 offset; + Word32 in_duck_gain[L_FRAME48k], out_duck_gain[L_FRAME48k]; + + offset = (Word16) ( output_frame / 10 ); + + /* Look-ahead delay */ + FOR( k = 0; k < MC_PARAMUPMIX_COMBINATIONS; k++ ) + { + mvl2l( pcm_in[k], pp_out_pcm[k], output_frame ); + delay_signal_fx( pp_out_pcm[k], output_frame, hTdDecorr[k]->look_ahead_buf, offset ); + /* In ducking gains */ + IF( hTdDecorr[k]->ducking_flag ) + { + ivas_td_decorr_get_ducking_gains_fx( hTdDecorr[k]->pTrans_det, pcm_in[k], in_duck_gain, out_duck_gain, output_frame, 0 ); + + FOR( j = 0; j < output_frame; j++ ) + { + pp_out_pcm[k][j] = Mpy_32_32( pp_out_pcm[k][j], in_duck_gain[j] ); + } + *q_format -= Q1; + } + + /* All pass delay section */ + ivas_td_decorr_APD_iir_filter_fx( &hTdDecorr[k]->APD_filt_state[0], pp_out_pcm[k], hTdDecorr[k]->num_apd_sections, output_frame ); + + /* Out ducking gains */ + IF( hTdDecorr[k]->ducking_flag ) + { + FOR( j = 0; j < output_frame; j++ ) + { + pp_out_pcm[k][j] = Mpy_32_32( pp_out_pcm[k][j], out_duck_gain[j] ); + } + *q_format -= Q1; + } + } + + return; +} + +#else /*------------------------------------------------------------------------- * paramupmix_td_decorr_process_jbm() * @@ -479,8 +541,7 @@ static void paramupmix_td_decorr_process_jbm( return; } - - +#endif /*------------------------------------------------------------------------- * ivas_param_upmix_dec_decorr_subframes() * @@ -517,8 +578,43 @@ static void ivas_param_upmix_dec_decorr_subframes( { int16_t nSamplesToDecorr = min( nSamplesLeftForTD, default_frame ); +#ifdef IVAS_FLOAT_FIXED + { + Word32 *pPcm_tmp_fx[MC_PARAMUPMIX_COMBINATIONS]; + Word32 *p_tc_fx[MC_PARAMUPMIX_COMBINATIONS]; + Word32 tmp_fx[MC_PARAMUPMIX_COMBINATIONS][L_FRAME48k]; + Word32 tc_fx[MC_PARAMUPMIX_COMBINATIONS][L_FRAME48k]; + Word32 j, q_format = Q15; + + FOR( j = 0; j < MC_PARAMUPMIX_COMBINATIONS; j++ ) + { + pPcm_tmp_fx[j] = tmp_fx[j]; + p_tc_fx[j] = tc_fx[j]; + } + + paramupmix_td_decorr_process_jbm_fx( hMCParamUpmix->hTdDecorr, p_tc_fx, pPcm_tmp_fx, nSamplesToDecorr, &q_format ); + + FOR( j = 0; j < MC_PARAMUPMIX_COMBINATIONS; j++ ) + { + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + pPcm_tmp[j][j] = pPcm_tmp_fx[j][j] / (float) ( 1 << q_format ); + } +#ifdef DUMPS_ENABLED + dbgwrite_txt( pp_out_pcm[k], nSamplesToDecorr, "fixed.txt", NULL ); +#endif + } + } +#else paramupmix_td_decorr_process_jbm( hMCParamUpmix->hTdDecorr, p_tc, pPcm_tmp, nSamplesToDecorr ); +#ifdef DUMPS_ENABLED + for ( j = 0; j < MC_PARAMUPMIX_COMBINATIONS; j++ ) + { + dbgwrite_txt( pp_out_pcm[k], nSamplesToDecorr, "float.txt", NULL ); + } +#endif +#endif for ( ch = 0; ch < nchan_internal; ch++ ) { p_tc[ch] += nSamplesToDecorr; diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 3be1d2ff318f4e19870b922f2e9278bd0a0b204a..1ec9c4579a06d44102991ecde0a544bd76060723 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -697,7 +697,56 @@ void ivas_sba_dec_digest_tc( if ( st_ivas->hDiracDecBin->hTdDecorr ) { +#ifndef IVAS_FLOAT_FIXED ivas_td_decorr_process( st_ivas->hDiracDecBin->hTdDecorr, p_tc, decorr_signal, nSamplesToDecorr ); +#ifdef DUMPS_ENABLED + for ( i = 0; i < st_ivas->hDiracDecBin->hTdDecorr->num_apd_outputs; i++ ) + { +#ifdef DUMPS_ENABLED + dbgwrite_txt( decorr_signal[i], nSamplesToDecorr, "fixed.txt", NULL ); +#endif + } +#endif +#else + { + Word32 *decorr_signal_fx[BINAURAL_CHANNELS]; + Word32 *p_tc_fx[2 * BINAURAL_CHANNELS]; + Word32 arr_decorr_signal_fx[BINAURAL_CHANNELS][L_FRAME48k]; + Word32 arr_tc_fx[2 * BINAURAL_CHANNELS][L_FRAME48k]; + Word32 i, j; + Word16 q_format = Q15; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + decorr_signal_fx[i] = arr_decorr_signal_fx[i]; + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + decorr_signal_fx[0][j] = (Word32) ( decorr_signal[0][j] * ( 1 << q_format ) ); + } + } + FOR( i = 0; i < 2 * BINAURAL_CHANNELS; i++ ) + { + p_tc_fx[i] = arr_tc_fx[i]; + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + p_tc_fx[0][j] = (Word32) ( p_tc[0][j] * ( 1 << q_format ) ); + } + } + + ivas_td_decorr_process_fx( st_ivas->hDiracDecBin->hTdDecorr, p_tc_fx, decorr_signal_fx, nSamplesToDecorr, &q_format ); + + FOR( i = 0; i < st_ivas->hDiracDecBin->hTdDecorr->num_apd_outputs; i++ ) + { + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + decorr_signal[i][j] = ( decorr_signal_fx[i][j] ) / (float) ( 1 << q_format ); + } +#ifdef DUMPS_ENABLED + dbgwrite_txt( decorr_signal[i], nSamplesToDecorr, "fixed.txt", NULL ); +#endif + } + } +#endif } for ( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index b093b3301f78c2dd3984dc6ab913171a6169a129..2ac7bf5c35976b8b487b81e29232da7276b0bb0f 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -105,7 +105,11 @@ ivas_error ivas_spar_dec_open( } else { +#ifdef IVAS_FLOAT_FIXED + if ( ( error = ivas_td_decorr_dec_open_fx( &hSpar->hTdDecorr, output_Fs, num_decor_chs + 1, 1 ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_decorr_dec_open( &hSpar->hTdDecorr, output_Fs, num_decor_chs + 1, 1 ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1312,7 +1316,48 @@ void ivas_spar_dec_digest_tc( if ( hSpar->hTdDecorr ) { +#ifndef IVAS_FLOAT_FIXED ivas_td_decorr_process( hSpar->hTdDecorr, p_tc, pPcm_tmp, nSamplesToDecorr ); +#else + { + Word32 *pPcm_tmp_fx[MAX_SPAR_INTERNAL_CHANNELS]; + Word32 *p_tc_fx[MAX_SPAR_INTERNAL_CHANNELS]; + Word32 pcm_tmp_fx[BINAURAL_CHANNELS][L_FRAME48k]; + Word32 tc_fx[2 * BINAURAL_CHANNELS][L_FRAME48k]; + Word32 i, j; + Word16 q_format = Q15; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + pPcm_tmp_fx[i] = pcm_tmp_fx[i]; + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + pPcm_tmp_fx[0][j] = (Word32) ( pPcm_tmp[0][j] * ( 1 << q_format ) ); + } + } + FOR( i = 0; i < 2 * BINAURAL_CHANNELS; i++ ) + { + p_tc_fx[i] = tc_fx[i]; + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + p_tc_fx[0][j] = (Word32) ( p_tc[0][j] * ( 1 << q_format ) ); + } + } + + ivas_td_decorr_process_fx( st_ivas->hDiracDecBin->hTdDecorr, p_tc_fx, pPcm_tmp_fx, nSamplesToDecorr, &q_format ); + + FOR( i = 0; i < st_ivas->hDiracDecBin->hTdDecorr->num_apd_outputs; i++ ) + { + FOR( j = 0; j < nSamplesToDecorr; j++ ) + { + pPcm_tmp[i][j] = ( pPcm_tmp_fx[i][j] ) / (float) ( 1 << q_format ); + } +#ifdef DUMPS_ENABLED + dbgwrite_txt( decorr_signal[i], nSamplesToDecorr, "fixed.txt", NULL ); +#endif + } + } +#endif if ( hSpar->hTdDecorr->num_apd_outputs >= ( nchan_internal - nchan_transport ) ) { for ( ch = 0; ch < nchan_internal - nchan_transport; ch++ ) @@ -1407,8 +1452,47 @@ void ivas_spar_dec_upmixer( { if ( hSpar->hTdDecorr ) { +#ifndef IVAS_FLOAT_FIXED ivas_td_decorr_process( hSpar->hTdDecorr, output_f_local, pPcm_tmp, output_frame ); +#else + { + Word32 *output_f_local_fx[MAX_OUTPUT_CHANNELS]; + Word32 *pPcm_tmp_fx[MAX_OUTPUT_CHANNELS]; + Word32 arr_output_f_local_fx[BINAURAL_CHANNELS][L_FRAME48k]; + Word32 pcm_tmp_fx[2 * BINAURAL_CHANNELS][L_FRAME48k]; + Word32 j; + Word16 q_format = Q15; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + pPcm_tmp_fx[i] = pcm_tmp_fx[i]; + FOR( j = 0; j < output_frame; j++ ) + { + pPcm_tmp_fx[0][j] = (Word32) ( pPcm_tmp[0][j] * ( 1 << q_format ) ); + } + } + FOR( i = 0; i < 2 * BINAURAL_CHANNELS; i++ ) + { + output_f_local_fx[i] = arr_output_f_local_fx[i]; + FOR( j = 0; j < output_frame; j++ ) + { + output_f_local_fx[0][j] = (Word32) ( output_f_local[0][j] * ( 1 << q_format ) ); + } + } + ivas_td_decorr_process_fx( hSpar->hTdDecorr, output_f_local_fx, pPcm_tmp_fx, output_frame, &q_format ); + FOR( i = 0; i < st_ivas->hDiracDecBin->hTdDecorr->num_apd_outputs; i++ ) + { + FOR( j = 0; j < output_frame; j++ ) + { + pPcm_tmp[i][j] = ( pPcm_tmp_fx[i][j] ) / (float) ( 1 << q_format ); + } +#ifdef DUMPS_ENABLED + dbgwrite_txt( decorr_signal[i], nSamplesToDecorr, "fixed.txt", NULL ); +#endif + } + } +#endif if ( hSpar->hTdDecorr->num_apd_outputs >= ( nchan_internal - nchan_transport ) ) { for ( i = 0; i < nchan_internal - nchan_transport; i++ ) diff --git a/lib_enc/ivas_mc_paramupmix_enc.c b/lib_enc/ivas_mc_paramupmix_enc.c index 54f1eba841626b9877268246947f3acbbff62b1c..b9db9053a45589fb98b60562244aad75b90bc44e 100644 --- a/lib_enc/ivas_mc_paramupmix_enc.c +++ b/lib_enc/ivas_mc_paramupmix_enc.c @@ -697,11 +697,40 @@ static void ivas_mc_paramupmix_param_est_enc( /*-----------------------------------------------------------------------------------------* * Transient detector *-----------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + Word32 *pcm_in_fx[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH]; + Word32 arr_pcm_in[MC_PARAMUPMIX_COMBINATIONS * MC_PARAMUPMIX_NCH][L_FRAME48k]; + Word32 k; + FOR( j = 0; j < MC_PARAMUPMIX_COMBINATIONS; j++ ) + { + pcm_in_fx[j] = arr_pcm_in[j]; + FOR( k = 0; k < input_frame; k++ ) + { + pcm_in_fx[j][k] = (Word32) ( pcm_in[j][k] * ( 1 << Q15 ) ); + } + } +#endif for ( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) { +#ifndef IVAS_FLOAT_FIXED ivas_transient_det_process( hMCParamUpmix->hTranDet[2 * i], pcm_in[2 * i], input_frame, transient_det_l ); ivas_transient_det_process( hMCParamUpmix->hTranDet[2 * i + 1], pcm_in[2 * i + 1], input_frame, transient_det_r ); +#else + ivas_transient_det_process_fx( hMCParamUpmix->hTranDet[2 * i], pcm_in_fx[2 * i], input_frame, transient_det_l ); +#ifdef DUMPS_ENABLED + float a[2]; + a[0] = transient_det_l[0]; + a[1] = transient_det_l[1]; + dbgwrite_txt( a, 2, "fixed.txt", NULL ); +#endif + ivas_transient_det_process_fx( hMCParamUpmix->hTranDet[2 * i + 1], pcm_in_fx[2 * i + 1], input_frame, transient_det_r ); +#ifdef DUMPS_ENABLED + a[0] = transient_det_r[0]; + a[1] = transient_det_r[1]; + dbgwrite_txt( a, 2, "fixed.txt", NULL ); +#endif +#endif transient_det[i][0] = transient_det_l[0] || transient_det_r[0]; transient_det[i][1] = transient_det_l[0] || transient_det_r[0]; /* should probably be transient_det_l[1] || transient_det_r[1] , but choosing 0 reproduces the before merge state */ diff --git a/lib_enc/ivas_spar_encoder.c b/lib_enc/ivas_spar_encoder.c index 3e4dce43c093bd7e0831f8d993c5e49b8e35cd31..56d45720503dc83d323fd8a917a1600af8564f47 100644 --- a/lib_enc/ivas_spar_encoder.c +++ b/lib_enc/ivas_spar_encoder.c @@ -610,9 +610,24 @@ static ivas_error ivas_spar_enc_process( /*-----------------------------------------------------------------------------------------* * Transient detector *-----------------------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + { + Word32 data_fix[L_FRAME48k]; + FOR( i = 0; i < input_frame; i++ ) + { + data_fix[i] = (Word32) ( data_f[0][i] * ( 1 << Q15 ) ); + } + ivas_transient_det_process_fx( hSpar->hTranDet, data_fix, input_frame, transient_det ); + } +#else ivas_transient_det_process( hSpar->hTranDet, data_f[0], input_frame, transient_det ); - +#endif +#ifdef DUMPS_ENABLED + float a[2]; + a[0] = transient_det[0]; + a[1] = transient_det[1]; + dbgwrite_txt( a, 2, "fixed.txt", NULL ); +#endif if ( ivas_total_brate < IVAS_24k4 ) { transient_det[1] = 0; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index ef1e6f7f3cbd8c3f1dc635839ccdb0b38ffdc193..f5b81b11e61f4bf36b5ba959b5fac6d6574e979a 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -112,42 +112,64 @@ void limiter_process( /*----------------------------------------------------------------------------------* * TD decorr. function prototypes *----------------------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_td_decorr_dec_open_fx( + ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t nchan_internal, /* i : number of internal channels */ + const int16_t ducking_flag /* i : ducking flag */ +); +#else ivas_error ivas_td_decorr_dec_open( ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ const int32_t output_Fs, /* i : output sampling rate */ const int16_t nchan_internal, /* i : number of internal channels */ const int16_t ducking_flag /* i : ducking flag */ ); - +#endif void ivas_td_decorr_dec_close( ivas_td_decorr_state_t **hTdDecorr /* i/o: TD decorrelator handle */ ); - +#ifdef IVAS_FLOAT_FIXED +void ivas_td_decorr_process_fx( + ivas_td_decorr_state_t *hTdDecorr, /* i/o: TD decoderrelator handle */ + Word32 *pcm_in[], /* i : input audio channels */ + Word32 **ppOut_pcm, /* o : output audio channels */ + const Word16 output_frame, /* i : output frame length */ +Word16 *q_format +); +#else void ivas_td_decorr_process( ivas_td_decorr_state_t *hTdDecorr, /* i/o: TD decoderrelator handle */ float *pcm_in[], /* i : input audio channels */ float **ppOut_pcm, /* o : output audio channels */ const int16_t output_frame /* i : output frame length */ ); - +#endif ivas_error ivas_td_decorr_reconfig_dec( const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const int32_t ivas_total_brate, /* i : total IVAS bitrate */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int32_t output_Fs, /* i : output sampling rate */ + const Word32 ivas_total_brate, /* i : total IVAS bitrate */ + const Word16 nchan_transport, /* i : number of transport channels */ + const Word32 output_Fs, /* i : output sampling rate */ ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ - uint16_t *useTdDecorr /* i/o: TD decorrelator flag */ + UWord16 *useTdDecorr /* i/o: TD decorrelator flag */ ); +#ifndef IVAS_FLOAT_FIXED void ivas_td_decorr_APD_iir_filter( ivas_td_decorr_APD_filt_state_t *filter_state, /* i/o: TD decorrelator filter handle */ float *pIn_out, /* i/o: audio channels */ const int16_t num_APD_sections, /* i : numbef of APD sections */ const int16_t output_frame /* i : output frame length */ ); - - +#else +void ivas_td_decorr_APD_iir_filter_fx( + ivas_td_decorr_APD_filt_state_t *filter_state, /* i/o: TD decorrelator filter handle */ + Word32 *pIn_out, /* i/o: audio channels */ + const Word16 num_APD_sections, /* i : numbef of APD sections */ + const Word16 output_frame /* i : output frame length */ +); +#endif /*----------------------------------------------------------------------------------* * Amplitude Panning EFAP prototypes *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 12175766d491fb792b6323fe753c07d2a1c68063..6ad74bc45268231bacc9c400fec2c7a5c8601f8d 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -75,15 +75,24 @@ typedef struct ivas_td_decorr_APD_filt_state_t { int16_t order[IVAS_MAX_DECORR_APD_SECTIONS]; int16_t idx[IVAS_MAX_DECORR_APD_SECTIONS]; +#ifdef IVAS_FLOAT_FIXED + Word16 coeffs[IVAS_MAX_DECORR_APD_SECTIONS]; + Word32 *state[IVAS_MAX_DECORR_APD_SECTIONS]; +#else float coeffs[IVAS_MAX_DECORR_APD_SECTIONS]; float *state[IVAS_MAX_DECORR_APD_SECTIONS]; +#endif } ivas_td_decorr_APD_filt_state_t; typedef struct ivas_td_decorr_state_t { ivas_trans_det_state_t *pTrans_det; +#ifdef IVAS_FLOAT_FIXED + Word32 *look_ahead_buf; +#else float *look_ahead_buf; +#endif ivas_td_decorr_APD_filt_state_t APD_filt_state[IVAS_MAX_DECORR_CHS]; int16_t num_apd_outputs; diff --git a/lib_rend/ivas_td_decorr.c b/lib_rend/ivas_td_decorr.c index 8534f8e8a85e68e731168ab3407da37b8ce1b53a..778cb6d002c810931b30667fc01199724654cd2e 100644 --- a/lib_rend/ivas_td_decorr.c +++ b/lib_rend/ivas_td_decorr.c @@ -33,17 +33,23 @@ #include #include "options.h" #include "prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" +#endif #include "ivas_prot.h" #include "ivas_prot_rend.h" #include "math.h" #include #include "wmc_auto.h" - +#ifdef DUMPS_ENABLED +#include +#endif /*------------------------------------------------------------------------------------------* * Local constants *------------------------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static const float ivas_hadamard_decorr_APD_coeff[IVAS_APD_16_SECT][IVAS_APD_16_SECT] = { { 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f }, { 0.4f, -0.4f, 0.4f, -0.4f, 0.4f, -0.4f, 0.4f, -0.4f, 0.4f, -0.4f, 0.4f, -0.4f, 0.4f, -0.4f, 0.4f, -0.4f }, @@ -83,17 +89,51 @@ static const float ivas_three_pow_frac[IVAS_MAX_DECORR_APD_SECTIONS] = { 61.54669053777900f, }; +#else +static const Word16 ivas_hadamard_decorr_APD_coeff[IVAS_APD_16_SECT][IVAS_APD_16_SECT] = { + { 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107 }, + { 13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107 }, + { 13107, 13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, -13107, -13107 }, + { 13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107 }, + { 13107, 13107, 13107, 13107, -13107, -13107, -13107, -13107, 13107, 13107, 13107, 13107, -13107, -13107, -13107, -13107 }, + { 13107, -13107, 13107, -13107, -13107, 13107, -13107, 13107, 13107, -13107, 13107, -13107, -13107, 13107, -13107, 13107 }, + { 13107, 13107, -13107, -13107, -13107, -13107, 13107, 13107, 13107, 13107, -13107, -13107, -13107, -13107, 13107, 13107 }, + { 13107, -13107, -13107, 13107, -13107, 13107, 13107, -13107, 13107, -13107, -13107, 13107, -13107, 13107, 13107, -13107 }, + { 13107, 13107, 13107, 13107, 13107, 13107, 13107, 13107, -13107, -13107, -13107, -13107, -13107, -13107, -13107, -13107 }, + { 13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, 13107 }, + { 13107, 13107, -13107, -13107, 13107, 13107, -13107, -13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107 }, + { 13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, -13107 }, + { 13107, 13107, 13107, 13107, -13107, -13107, -13107, -13107, -13107, -13107, -13107, -13107, 13107, 13107, 13107, 13107 }, + { 13107, -13107, 13107, -13107, -13107, 13107, -13107, 13107, -13107, 13107, -13107, 13107, 13107, -13107, 13107, -13107 }, + { 13107, 13107, -13107, -13107, -13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, 13107, 13107, -13107, -13107 }, + { 13107, -13107, -13107, 13107, -13107, 13107, 13107, -13107, -13107, 13107, 13107, -13107, 13107, -13107, -13107, 13107 } +}; + +/* For R = 3.^([0:obj.parm_APD_nSections-1]/4); Q22 */ +static const Word32 ivas_three_pow_frac[IVAS_MAX_DECORR_APD_SECTIONS] = { + 4194304, 5520015, 7264748, 9560946, 12582912, 16560043, 21794242, + 28682836, 37748736, 49680132, 65382728, 86048512, 113246208, + 149040384, 196148192, 258145536 +}; +#endif + +#ifndef IVAS_FLOAT_FIXED #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN ( 2.0f ) #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f ) - +#else +#define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN ( 1073741824 ) // Q29 +#define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 1610612736 ) // Q29 +#endif /*------------------------------------------------------------------------------------------* * Local functions declaration *------------------------------------------------------------------------------------------*/ -static int16_t ivas_get_APD_filt_orders( const int16_t num_out_chans, const int32_t output_Fs, int16_t *APD_filt_orders ); - -static void ivas_td_decorr_init( ivas_td_decorr_state_t *hTdDecorr, const int16_t num_out_chans, const int16_t ducking_flag ); - +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_get_APD_filt_orders_fx( const Word16 num_out_chans, const Word32 output_Fs, Word16 *APD_filt_orders ); +#else +static Word16 ivas_get_APD_filt_orders( const Word16 num_out_chans, const Word32 output_Fs, Word16 *APD_filt_orders ); +#endif +static void ivas_td_decorr_init( ivas_td_decorr_state_t *hTdDecorr, const Word16 num_out_chans, const Word16 ducking_flag ); /*------------------------------------------------------------------------- * ivas_td_decorr_reconfig_dec() @@ -103,80 +143,88 @@ static void ivas_td_decorr_init( ivas_td_decorr_state_t *hTdDecorr, const int16_ ivas_error ivas_td_decorr_reconfig_dec( const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const int32_t ivas_total_brate, /* i : total IVAS bitrate */ - const int16_t nchan_transport, /* i : number of transport channels */ - const int32_t output_Fs, /* i : output sampling rate */ + const Word32 ivas_total_brate, /* i : total IVAS bitrate */ + const Word16 nchan_transport, /* i : number of transport channels */ + const Word32 output_Fs, /* i : output sampling rate */ ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ - uint16_t *useTdDecorr /* i/o: TD decorrelator flag */ + UWord16 *useTdDecorr /* i/o: TD decorrelator flag */ ) { - uint16_t useTdDecorr_new; + UWord16 useTdDecorr_new; ivas_error error; useTdDecorr_new = 0; - if ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) + IF( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) { - if ( nchan_transport == 1 ) + IF( nchan_transport == 1 ) { useTdDecorr_new = 1; } } - else if ( ivas_format == MASA_FORMAT ) + ELSE IF( ivas_format == MASA_FORMAT ) { - if ( ( ivas_total_brate < IVAS_48k && nchan_transport == 1 ) || ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + IF( ( LT_32( ivas_total_brate, IVAS_48k ) && nchan_transport == 1 ) || LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) { useTdDecorr_new = 1; } } - else if ( ivas_format == MC_FORMAT ) + ELSE IF( ivas_format == MC_FORMAT ) { - if ( ivas_total_brate < IVAS_48k && nchan_transport == 1 ) + IF( LT_32( ivas_total_brate, IVAS_48k ) && EQ_16( nchan_transport, 1 ) ) { useTdDecorr_new = 1; } } - if ( *useTdDecorr != useTdDecorr_new ) + IF( *useTdDecorr != useTdDecorr_new ) { *useTdDecorr = useTdDecorr_new; - if ( *useTdDecorr ) + IF( *useTdDecorr ) { - if ( ivas_total_brate >= IVAS_13k2 && ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) ) + IF( GE_32( ivas_total_brate, IVAS_13k2 ) && ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) ) { - if ( *hTdDecorr == NULL ) + IF( *hTdDecorr == NULL ) { - if ( ( error = ivas_td_decorr_dec_open( hTdDecorr, output_Fs, 3, 1 ) ) != IVAS_ERR_OK ) +#ifdef IVAS_FLOAT_FIXED + IF( ( error = ivas_td_decorr_dec_open_fx( hTdDecorr, output_Fs, 3, 1 ) ) != IVAS_ERR_OK ) +#else + IF( ( error = ivas_td_decorr_dec_open( hTdDecorr, output_Fs, 3, 1 ) ) != IVAS_ERR_OK ) +#endif { return error; } } - if ( ivas_total_brate < IVAS_24k4 ) + IF( LT_32( ivas_total_brate, IVAS_24k4 ) ) { ( *hTdDecorr )->pTrans_det->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR; } - else + ELSE { ( *hTdDecorr )->pTrans_det->duck_mult_fac = IVAS_TDET_DUCK_MULT_FAC_PARA_BIN; } } - else + ELSE { - if ( *hTdDecorr == NULL ) + IF( *hTdDecorr == NULL ) { - if ( ( error = ivas_td_decorr_dec_open( hTdDecorr, output_Fs, 3, 0 ) ) != IVAS_ERR_OK ) +#ifdef IVAS_FLOAT_FIXED + IF( ( error = ivas_td_decorr_dec_open_fx( hTdDecorr, output_Fs, 3, 0 ) ) != IVAS_ERR_OK ) +#else + IF( ( error = ivas_td_decorr_dec_open( hTdDecorr, output_Fs, 3, 0 ) ) != IVAS_ERR_OK ) +#endif { return error; } } - else + ELSE { ivas_td_decorr_init( *hTdDecorr, 3, 0 ); } } } - else + ELSE { ivas_td_decorr_dec_close( hTdDecorr ); } @@ -185,7 +233,76 @@ ivas_error ivas_td_decorr_reconfig_dec( return IVAS_ERR_OK; } +#ifdef IVAS_FLOAT_FIXED +/*------------------------------------------------------------------------- + * ivas_td_decorr_dec_open_fx() + * + * Allocate and initialize time domain decorrelator handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_td_decorr_dec_open_fx( + ivas_td_decorr_state_t **hTdDecorr, /* i/o: TD decorrelator handle */ + const Word32 output_Fs, /* i : output sampling rate */ + const Word16 nchan_internal, /* i : number of internal channels */ + const Word16 ducking_flag /* i : ducking flag */ +) +{ + Word16 i, j, len; + Word16 num_out_chans; + ivas_td_decorr_state_t *hTdDecorr_loc; + ivas_error error; + num_out_chans = nchan_internal - 1; + + error = IVAS_ERR_OK; + + IF( ( hTdDecorr_loc = (ivas_td_decorr_state_t *) malloc( sizeof( ivas_td_decorr_state_t ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory FOR SPAR COV decoder" ); + } + + IF( ( hTdDecorr_loc->look_ahead_buf = (Word32 *) malloc( sizeof( Word32 ) * (Word16) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory FOR SPAR COV decoder" ); + } + set32_fx( hTdDecorr_loc->look_ahead_buf, 0, (Word16) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ) ); + hTdDecorr_loc->offset = (Word16) ( output_Fs * IVAS_DECORR_PARM_LOOKAHEAD_TAU ); + hTdDecorr_loc->num_apd_sections = ivas_get_APD_filt_orders_fx( num_out_chans, output_Fs, hTdDecorr_loc->APD_filt_state[0].order ); + + FOR( j = 0; j < num_out_chans; j++ ) + { + FOR( i = 0; i < hTdDecorr_loc->num_apd_sections; i++ ) + { + len = hTdDecorr_loc->APD_filt_state[0].order[i]; + + IF( ( hTdDecorr_loc->APD_filt_state[j].state[i] = (Word32 *) malloc( sizeof( Word32 ) * len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory FOR SPAR COV decoder" ); + } + + set32_fx( hTdDecorr_loc->APD_filt_state[j].state[i], 0, len ); + } + } + + ivas_td_decorr_init( hTdDecorr_loc, num_out_chans, ducking_flag ); + + IF( ducking_flag ) + { + IF( ( error = ivas_transient_det_open( &hTdDecorr_loc->pTrans_det, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + hTdDecorr_loc->pTrans_det = NULL; + } + + *hTdDecorr = hTdDecorr_loc; + + return error; +} +#else /*------------------------------------------------------------------------- * ivas_td_decorr_dec_open() * @@ -254,7 +371,7 @@ ivas_error ivas_td_decorr_dec_open( return error; } - +#endif /*------------------------------------------------------------------------- * ivas_td_decorr_dec_close() @@ -266,9 +383,9 @@ void ivas_td_decorr_dec_close( ivas_td_decorr_state_t **hTdDecorr /* i/o: TD decorrelator handle */ ) { - int16_t i, j; + Word16 i, j; - if ( hTdDecorr == NULL || *hTdDecorr == NULL ) + IF( hTdDecorr == NULL || *hTdDecorr == NULL ) { return; } @@ -276,16 +393,16 @@ void ivas_td_decorr_dec_close( free( ( *hTdDecorr )->look_ahead_buf ); ( *hTdDecorr )->look_ahead_buf = NULL; - for ( j = 0; j < ( *hTdDecorr )->num_apd_outputs; j++ ) + FOR( j = 0; j < ( *hTdDecorr )->num_apd_outputs; j++ ) { - for ( i = 0; i < ( *hTdDecorr )->num_apd_sections; i++ ) + FOR( i = 0; i < ( *hTdDecorr )->num_apd_sections; i++ ) { free( ( *hTdDecorr )->APD_filt_state[j].state[i] ); ( *hTdDecorr )->APD_filt_state[j].state[i] = NULL; } } - if ( ( *hTdDecorr )->pTrans_det != NULL ) + IF( ( *hTdDecorr )->pTrans_det != NULL ) { ivas_transient_det_close( &( *hTdDecorr )->pTrans_det ); } @@ -296,6 +413,58 @@ void ivas_td_decorr_dec_close( return; } +#ifdef IVAS_FLOAT_FIXED +/*-----------------------------------------------------------------------------------------* + * Function ivas_get_APD_filt_orders_fx() + * + * Calculate the orders of the APD IIR filters and return num APD sections + *-----------------------------------------------------------------------------------------*/ + +static Word16 ivas_get_APD_filt_orders_fx( + const Word16 num_out_chans, + const Word32 output_Fs, + Word16 *APD_filt_orders ) +{ + Word16 i; + Word16 num_apd_sections = 0; + Word32 sum_R, R[IVAS_MAX_DECORR_APD_SECTIONS]; + + SWITCH( num_out_chans ) + { + case IVAS_TD_DECORR_OUT_1CH: + case IVAS_TD_DECORR_OUT_2CH: + num_apd_sections = IVAS_APD_2_SECT; + BREAK; + case IVAS_TD_DECORR_OUT_3CH: + case IVAS_TD_DECORR_OUT_4CH: + num_apd_sections = IVAS_APD_4_SECT; + BREAK; + case IVAS_TD_DECORR_OUT_5CH: + case IVAS_TD_DECORR_OUT_6CH: + case IVAS_TD_DECORR_OUT_7CH: + case IVAS_TD_DECORR_OUT_8CH: + num_apd_sections = IVAS_APD_8_SECT; + BREAK; + default: + assert( !"Invalid num out chans" ); + BREAK; + } + + sum_R = 0; + FOR( i = 0; i < num_apd_sections; i++ ) + { + R[i] = ivas_three_pow_frac[i]*2; + sum_R = L_add( sum_R, R[i] ); + } + + FOR( i = 0; i < num_apd_sections; i++ ) + { + APD_filt_orders[i] = (Word16) L_shr( Mpy_32_32( L_shl( output_Fs, Q15 ), Mpy_32_32( IVAS_DECORR_PARM_APD_TAU, L_shl( (Word32) divide3232( R[i], sum_R ), Q15 ) ) ), Q14 ) + 1; + } + + return num_apd_sections; +} +#else /*-----------------------------------------------------------------------------------------* * Function ivas_get_APD_filt_orders() @@ -347,8 +516,7 @@ static int16_t ivas_get_APD_filt_orders( return num_apd_sections; } - - +#endif /*-----------------------------------------------------------------------------------------* * Function ivas_td_decorr_init() * @@ -357,18 +525,18 @@ static int16_t ivas_get_APD_filt_orders( static void ivas_td_decorr_init( ivas_td_decorr_state_t *hTdDecorr, /* i/o: TD decorrelator handle */ - const int16_t num_out_chans, /* i : number of channels */ - const int16_t ducking_flag /* i : TD ducking flag */ + const Word16 num_out_chans, /* i : number of channels */ + const Word16 ducking_flag /* i : TD ducking flag */ ) { - int16_t i, j; + Word16 i, j; hTdDecorr->ducking_flag = ducking_flag; hTdDecorr->num_apd_outputs = num_out_chans; - for ( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) + FOR( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) { - for ( j = 0; j < hTdDecorr->num_apd_sections; j++ ) + FOR( j = 0; j < hTdDecorr->num_apd_sections; j++ ) { hTdDecorr->APD_filt_state[i].order[j] = hTdDecorr->APD_filt_state[0].order[j]; hTdDecorr->APD_filt_state[i].coeffs[j] = ivas_hadamard_decorr_APD_coeff[i][j]; @@ -379,7 +547,7 @@ static void ivas_td_decorr_init( return; } - +#ifndef IVAS_FLOAT_FIXED /*-----------------------------------------------------------------------------------------* * Function ivas_td_decorr_APD_iir_filter() * @@ -389,25 +557,25 @@ static void ivas_td_decorr_init( void ivas_td_decorr_APD_iir_filter( ivas_td_decorr_APD_filt_state_t *filter_state, /* i/o: TD decorrelator filter handle */ float *pIn_out, /* i/o: audio channels */ - const int16_t num_APD_sections, /* i : numbef of APD sections */ - const int16_t length /* i : output frame length */ + const Word16 num_APD_sections, /* i : numbef of APD sections */ + const Word16 length /* i : output frame length */ ) { - int16_t i, k; - int16_t idx; + Word16 i, k; + Word16 idx; float *pIn = pIn_out; float *pOut = pIn_out; float tmp_pIn_buf_i; - for ( k = 0; k < num_APD_sections; k++ ) + FOR( k = 0; k < num_APD_sections; k++ ) { float *pFilt_state = filter_state->state[k]; float filt_coeff = filter_state->coeffs[k]; - int16_t order = filter_state->order[k]; + Word16 order = filter_state->order[k]; idx = filter_state->idx[k]; - for ( i = 0; i < length; i++ ) + FOR( i = 0; i < length; i++ ) { tmp_pIn_buf_i = pIn[i]; @@ -415,7 +583,7 @@ void ivas_td_decorr_APD_iir_filter( pFilt_state[idx++] = tmp_pIn_buf_i - filt_coeff * pOut[i]; - if ( order == idx ) + IF( order == idx ) { idx = 0; } @@ -436,12 +604,12 @@ void ivas_td_decorr_APD_iir_filter( static void ivas_td_decorr_APD_sections( ivas_td_decorr_state_t *hTdDecorr, /* i/o: TD decorrelator handle */ float **ppOut_pcm, /* i/o: audio channels */ - const int16_t output_frame /* i : output frame length */ + const Word16 output_frame /* i : output frame length */ ) { - int16_t i; + Word16 i; - for ( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) + FOR( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) { ivas_td_decorr_APD_iir_filter( &hTdDecorr->APD_filt_state[i], ppOut_pcm[i], hTdDecorr->num_apd_sections, output_frame ); } @@ -460,10 +628,10 @@ void ivas_td_decorr_process( ivas_td_decorr_state_t *hTdDecorr, /* i/o: TD decorrelator handle */ float *pcm_in[], /* i : input audio channels */ float **ppOut_pcm, /* o : output audio channels */ - const int16_t output_frame /* i : output frame length */ + const Word16 output_frame /* i : output frame length */ ) { - int16_t i, j; + Word16 i, j; float in_duck_gain[L_FRAME48k], out_duck_gain[L_FRAME48k]; /* Look-ahead delay */ @@ -471,17 +639,17 @@ void ivas_td_decorr_process( delay_signal_float( ppOut_pcm[0], output_frame, hTdDecorr->look_ahead_buf, hTdDecorr->offset ); /* In ducking gains */ - if ( hTdDecorr->ducking_flag ) + IF( hTdDecorr->ducking_flag ) { ivas_td_decorr_get_ducking_gains( hTdDecorr->pTrans_det, pcm_in[0], in_duck_gain, out_duck_gain, output_frame, 0 ); - for ( j = 0; j < output_frame; j++ ) + FOR( j = 0; j < output_frame; j++ ) { ppOut_pcm[0][j] = ppOut_pcm[0][j] * in_duck_gain[j]; } } - for ( i = 1; i < hTdDecorr->num_apd_outputs; i++ ) + FOR( i = 1; i < hTdDecorr->num_apd_outputs; i++ ) { mvr2r( ppOut_pcm[0], ppOut_pcm[i], output_frame ); } @@ -490,11 +658,11 @@ void ivas_td_decorr_process( ivas_td_decorr_APD_sections( hTdDecorr, ppOut_pcm, output_frame ); /* Out ducking gains */ - if ( hTdDecorr->ducking_flag ) + IF( hTdDecorr->ducking_flag ) { - for ( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) + FOR( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) { - for ( j = 0; j < output_frame; j++ ) + FOR( j = 0; j < output_frame; j++ ) { ppOut_pcm[i][j] = ppOut_pcm[i][j] * out_duck_gain[j]; } @@ -503,3 +671,126 @@ void ivas_td_decorr_process( return; } + +#else +/*-----------------------------------------------------------------------------------------* + * Function ivas_td_decorr_APD_iir_filter_fx() + * + * APD IIR filter + *-----------------------------------------------------------------------------------------*/ + +void ivas_td_decorr_APD_iir_filter_fx( + ivas_td_decorr_APD_filt_state_t *filter_state, + Word32 *pIn_out, + const Word16 num_APD_sections, + const Word16 length ) +{ + Word16 i, k; + Word16 idx; + Word32 *pIn = pIn_out; + Word32 *pOut = pIn_out; + Word32 tmp_pIn_buf_i; + + FOR( k = 0; k < num_APD_sections; k++ ) + { + Word32 *pFilt_state = filter_state->state[k]; + Word16 filt_coeff = filter_state->coeffs[k]; + Word16 order = filter_state->order[k]; + + idx = filter_state->idx[k]; + + FOR( i = 0; i < length; i++ ) + { + tmp_pIn_buf_i = pIn[i]; + + pOut[i] = Madd_32_16( pFilt_state[idx], pIn[i], filt_coeff ); + + pFilt_state[idx++] = Msub_32_16( tmp_pIn_buf_i, pOut[i], filt_coeff ); + + IF( order == idx ) + { + idx = 0; + } + } + filter_state->idx[k] = idx; + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_td_decorr_APD_sections() + * + * TD decorr all pass delay sections + *-----------------------------------------------------------------------------------------*/ + +static void ivas_td_decorr_APD_sections_fx( + ivas_td_decorr_state_t *hTdDecorr, + Word32 **ppOut_pcm, + const Word16 output_frame ) +{ + Word16 i; + FOR( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) + { + ivas_td_decorr_APD_iir_filter_fx( &hTdDecorr->APD_filt_state[i], ppOut_pcm[i], hTdDecorr->num_apd_sections, output_frame ); + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_td_decorr_process_fx() + * + * TD decorr process call + *-----------------------------------------------------------------------------------------*/ + +void ivas_td_decorr_process_fx( + ivas_td_decorr_state_t *hTdDecorr, /* i/o: SPAR Covar. decoder handle */ + Word32 *pcm_in[], /* i : input audio channels */ + Word32 **ppOut_pcm, /* o : output audio channels */ + const Word16 output_frame, /* i : output frame length */ + Word16 *q_format ) +{ + Word16 i, j; + Word32 in_duck_gain[L_FRAME48k], out_duck_gain[L_FRAME48k]; + + /* Look-ahead delay */ + mvl2l( pcm_in[0], ppOut_pcm[0], output_frame ); + delay_signal_fx( ppOut_pcm[0], output_frame, hTdDecorr->look_ahead_buf, hTdDecorr->offset ); + + /* In ducking gains */ + IF( hTdDecorr->ducking_flag ) + { + ivas_td_decorr_get_ducking_gains_fx( hTdDecorr->pTrans_det, pcm_in[0], in_duck_gain, out_duck_gain, output_frame, 0 ); + + FOR( j = 0; j < output_frame; j++ ) + { + ppOut_pcm[0][j] = Mpy_32_32( ppOut_pcm[0][j], in_duck_gain[j] ); + } + *q_format -= Q1; + } + + FOR( i = 1; i < hTdDecorr->num_apd_outputs; i++ ) + { + mvl2l( ppOut_pcm[0], ppOut_pcm[i], output_frame ); + } + + /* All pass delay section */ + ivas_td_decorr_APD_sections_fx( hTdDecorr, ppOut_pcm, output_frame ); + + /* Out ducking gains */ + IF( hTdDecorr->ducking_flag ) + { + FOR( i = 0; i < hTdDecorr->num_apd_outputs; i++ ) + { + FOR( j = 0; j < output_frame; j++ ) + { + ppOut_pcm[i][j] = Mpy_32_32( ppOut_pcm[i][j], out_duck_gain[j] ); + } + } + *q_format -= Q1; + } + + return; +} +#endif