From 18d64dd6cc02b3c83d723065197552a30be578d1 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Thu, 9 May 2024 22:00:57 +0530 Subject: [PATCH] Renderer functions conversion, cleanup and few MSAN error fixes [x] Conversions related to ivas_mcmasa_ana.c added [x] ivas dirac dec binaural functions converted, integrated and cleaned up. [x] ivas_param_mc_dec_render clean up [x] ivas_reflections.c file clean up [x] Few MSAN issue fixes. --- lib_com/ivas_dirac_com.c | 57 + lib_com/ivas_prot.h | 21 + lib_com/ivas_prot_fx.h | 6 + lib_com/ivas_qmetadata_com.c | 2 +- lib_com/ivas_spar_com.c | 11 + lib_com/ivas_tools.c | 16 + lib_com/options.h | 3 + lib_com/tools_fx.c | 2 + lib_dec/ivas_dirac_dec.c | 29 + lib_dec/ivas_init_dec.c | 38 +- lib_dec/ivas_ism_dec.c | 12 - lib_dec/ivas_jbm_dec.c | 169 + lib_dec/ivas_mc_param_dec.c | 1131 ++--- lib_dec/ivas_mdct_core_dec.c | 10 + lib_rend/ivas_dirac_dec_binaural_functions.c | 4503 +++++++++++------- lib_rend/ivas_mcmasa_ana.c | 1476 +++++- lib_rend/ivas_objectRenderer_mix.c | 3 +- lib_rend/ivas_objectRenderer_sources.c | 6 +- lib_rend/ivas_prot_rend.h | 10 + lib_rend/ivas_reflections.c | 373 +- lib_rend/ivas_rom_binauralRenderer.c | 2 +- lib_rend/ivas_rom_rend.c | 21 + lib_rend/ivas_rom_rend.h | 4 + lib_rend/ivas_stat_rend.h | 68 +- lib_rend/lib_rend.c | 82 + 25 files changed, 5562 insertions(+), 2493 deletions(-) diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 180e27ddb..d3057e3e8 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -898,6 +898,63 @@ ivas_error ivas_dirac_sba_config( #ifdef IVAS_FLOAT_FIXED +void computeDirectionVectors_fixed( + Word32 *intensity_real_x, + Word32 *intensity_real_y, + Word32 *intensity_real_z, + const Word16 enc_param_start_band, + const Word16 num_frequency_bands, + Word32 *direction_vector_x,/*Q30*/ + Word32 *direction_vector_y,/*Q30*/ + Word32 *direction_vector_z,/*Q30*/ + Word16 i_e /*Exponent of all the intensity buffers*/) +{ + Word16 i; + Word32 intensityNorm; + Word16 intensityNorm_e; + Word32 temp1; + Word16 exp1; + Word16 norm_x, norm_y, norm_z; + Word32 scaled_x, scaled_y, scaled_z; + Word16 e_x, e_y, e_z; + for ( i = enc_param_start_band; i < enc_param_start_band + num_frequency_bands; ++i ) + { + norm_x = norm_l( *intensity_real_x ); + norm_y = norm_l( *intensity_real_y); + norm_z = norm_l( *intensity_real_z ); + scaled_x = L_shl( *intensity_real_x, norm_x ); + scaled_y = L_shl( *intensity_real_y, norm_y); + scaled_z = L_shl( *intensity_real_z, norm_z); + e_x = i_e - norm_x; + e_y = i_e - norm_y; + e_z = i_e - norm_z; + temp1 = BASOP_Util_Add_Mant32Exp( Mult_32_32( scaled_x, scaled_x ), 2*e_x, Mult_32_32( scaled_y, scaled_y ), 2*e_y, &exp1 ); + intensityNorm = BASOP_Util_Add_Mant32Exp( temp1, exp1, Mult_32_32( scaled_z, scaled_z ), 2 * e_z, &intensityNorm_e); + + IF ( LE_32(intensityNorm , EPSILON_FX) ) + { + intensityNorm = L_shl(1, intensityNorm_e); + *( direction_vector_x++ ) = ONE_IN_Q30; + *( direction_vector_y++ ) = 0; + *( direction_vector_z++ ) = 0; + intensity_real_x++; + intensity_real_y++; + intensity_real_z++; + } + ELSE + { + intensityNorm = ISqrt32( intensityNorm, &intensityNorm_e ); /*Q31-intensityNorm_e*/ + *( direction_vector_x++ ) = L_shl(Mult_32_32(scaled_x , intensityNorm),e_x+ intensityNorm_e-1);/*Q30*/ + intensity_real_x++; + *( direction_vector_y++ ) = L_shl(Mult_32_32( scaled_y, intensityNorm ), e_y+ intensityNorm_e-1);/*Q30*/ + intensity_real_y++; + *( direction_vector_z++ ) = L_shl(Mult_32_32(scaled_z, intensityNorm), e_z + intensityNorm_e-1);/*Q30*/ + intensity_real_z++; + } + } + + return; +} /*------------------------------------------------------------------------- * computeDirectionVectors() * diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 0444bac65..b1a94cf24 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -4421,6 +4421,16 @@ void computeDiffuseness_mdft( float *diffuseness ); #ifdef IVAS_FLOAT_FIXED +void computeDirectionVectors_fixed( + Word32 *intensity_real_x, + Word32 *intensity_real_y, + Word32 *intensity_real_z, + const Word16 enc_param_start_band, + const Word16 num_frequency_bands, + Word32 *direction_vector_x,/*Q30*/ + Word32 *direction_vector_y,/*Q30*/ + Word32 *direction_vector_z,/*Q30*/ + Word16 i_e /*Exponent of all the intensity buffers*/); void computeDirectionVectors_fx( Word32 *intensity_real_x, Word32 *intensity_real_y, @@ -4677,6 +4687,17 @@ void ivas_param_mc_dec_digest_tc_fx( Word32 *transport_channels_f_fx[], Word16 transport_f_e ); +#ifdef IVAS_FLOAT_FIXED +void ivas_param_mc_dec_render_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const UWord16 nSamplesAsked, /* i : number of CLDFB slots requested */ + UWord16 *nSamplesRendered, /* o : number of CLDFB slots rendered */ + UWord16 *nSamplesAvailable, /* o : number of CLDFB slots still to render */ + Word32 *output_f_fx[], /* o : rendered time signal */ + Word16 channel_active_fx[MAX_OUTPUT_CHANNELS] +); +#endif + void ivas_param_mc_dec_render( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index cdd3f2c3f..c32713fb4 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -1054,6 +1054,12 @@ void v_multc_acc_32_16( Word32 y[], /* o : Output vector that contains y + c*x */ const Word16 N /* i : Vector length */ ); +void v_multc_acc_32_32( + const Word32 x[], /* i : Input vector */ + const Word32 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains y + c*x */ + const Word16 N /* i : Vector length */ +); void ivas_mono_stereo_downmix_mcmasa_fx( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ diff --git a/lib_com/ivas_qmetadata_com.c b/lib_com/ivas_qmetadata_com.c index 538d74c71..12bc2f9e9 100644 --- a/lib_com/ivas_qmetadata_com.c +++ b/lib_com/ivas_qmetadata_com.c @@ -1219,7 +1219,7 @@ void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( Word32 L_tmp; Word16 e_tmp; L_tmp = L_add( Mpy_32_32( dv[0], dv[0] ), Mpy_32_32( dv[1], dv[1] ) ); /* 2 * dv_q - 31 */ - e_tmp = shl( sub( 31, dv_q ), 2 ); + e_tmp = shl( sub( 31, dv_q ), 1 ); L_tmp = Sqrt32( L_tmp, &e_tmp ); *el = L_mult0( BASOP_util_atan2( dv[2], L_tmp, 31 - dv_q - e_tmp ), 29335 ); /* Q22 */ *az = L_mult0( BASOP_util_atan2( dv[1], dv[0], 0 ), 29335 ); /* Q22 */ diff --git a/lib_com/ivas_spar_com.c b/lib_com/ivas_spar_com.c index d7ccff598..d9994bc39 100644 --- a/lib_com/ivas_spar_com.c +++ b/lib_com/ivas_spar_com.c @@ -3002,6 +3002,16 @@ void ivas_compute_spar_params_fx( Word16 q_tmp = hSparMd->band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].q_C_re_fx; IF( NE_16(ndm, 1 )) { +#ifdef MSAN_FIX + FOR( i = 0; i < num_ch - ndm; i++ ) + { + FOR( int j = 0; j < ndm - 1; j++ ) + { + hSparMd->band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re_fx[i][j] = L_shr( hSparMd->band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re_fx[i][j], sub( q_tmp, 22 ) ); + move32(); + } + } +#else for (i = 0; i < IVAS_SPAR_MAX_CH - IVAS_SPAR_MAX_DMX_CHS; i++) { for (int j = 0; j < IVAS_SPAR_MAX_DMX_CHS - 1; j++) @@ -3009,6 +3019,7 @@ void ivas_compute_spar_params_fx( hSparMd->band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re_fx[i][j] = L_shr(hSparMd->band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].C_re_fx[i][j], sub(q_tmp, 22)); } } +#endif hSparMd->band_coeffs[b + i_ts * IVAS_MAX_NUM_BANDS].q_C_re_fx = Q22; } diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index ac837f747..9d5dd4419 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -2082,6 +2082,22 @@ void v_multc_acc_32_16( return; } +void v_multc_acc_32_32( + const Word32 x[], /* i : Input vector */ + const Word32 c, /* i : Constant */ + Word32 y[], /* o : Output vector that contains y + c*x */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = L_add( y[i], Mpy_32_32( x[i], c ) ); + } + + return; +} #endif /*---------------------------------------------------------------------* diff --git a/lib_com/options.h b/lib_com/options.h index 8b1da2222..677bbe613 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -102,6 +102,9 @@ #define NONBE_FIX_849_OMASA_BFI_CRASH /* VA: issue 849: fix OMASA 2TC and FEC crashes */ #define NONBE_FIX_738_QUATERNION_SLERP_PRECISION /* Quaternion slerp changes*/ #define IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED +#define MSAN_FIX +#endif #define ISM_DISABLE #define FIX_TMP_714 #define BASOP_NOGLOB_TMP_715 diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 3e2376151..955338c2b 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -64,6 +64,8 @@ Word32 float_to_fix( float number, Word32 Q ) assert( Q >= 0 ); if (number == 1.0f && Q == Q31) return ONE_IN_Q31; + if(isnan(number)) + number = 0; assert( fabs( number ) < pow( 2, 31 - Q ) ); Word32 ret = (Word32) ( number * ( (UWord32) 1 << Q ) ); return ret; diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 1d6922e89..cfe4ce0cc 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -5411,6 +5411,17 @@ void ivas_dirac_dec_render_sf_fx( } ELSE { +#ifdef MSAN_FIX + FOR( ch = 0; ch < nchan_transport; ch++ ) + { + floatToFixed_arrL( Cldfb_RealBuffer[ch][0], Cldfb_RealBuffer_fx[ch][0], + Q6, + hSpatParamRendCom->num_freq_bands ); + floatToFixed_arrL( Cldfb_ImagBuffer[ch][0], Cldfb_ImagBuffer_fx[ch][0], + Q6, + hSpatParamRendCom->num_freq_bands ); + } +#else FOR( ch = 0; ch < hDirACRend->num_outputs_dir; ch++ ) { FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) @@ -5423,6 +5434,7 @@ void ivas_dirac_dec_render_sf_fx( hSpatParamRendCom->num_freq_bands ); } } +#endif } hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth = Q26; @@ -5767,6 +5779,20 @@ void ivas_dirac_dec_render_sf_fx( #ifdef IVAS_FLOAT_FIXED //////////////////////////////////////////////// FLOAT TO FIXED ///////////////////////////////////////////// +#ifdef MSAN_FIX + Word16 idx1, idx2, idx3; + for ( idx1 = 0; idx1 < hDirACRend->hOutSetup.nchan_out_woLFE; idx1++ ) + { + for ( idx2 = 0; idx2 < hSpatParamRendCom->subframe_nbslots[subframe_idx]; idx2++ ) + { + for ( idx3 = 0; idx3 < hSpatParamRendCom->num_freq_bands; idx3++ ) + { + Cldfb_RealBuffer_fx[idx1][idx2][idx3] = floatToFixed( Cldfb_RealBuffer[idx1][idx2][idx3], Q6 ); + Cldfb_ImagBuffer_fx[idx1][idx2][idx3] = floatToFixed( Cldfb_ImagBuffer[idx1][idx2][idx3], Q6 ); + } + } + } +#else for (int idx1 = 0; idx1 < MAX_OUTPUT_CHANNELS; idx1++) { for (int idx2 = 0; idx2 < MAX_PARAM_SPATIAL_SUBFRAMES; idx2++) @@ -5779,15 +5805,18 @@ void ivas_dirac_dec_render_sf_fx( } } } +#endif Word32 output_buf_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) { // Float to fixed +#ifndef MSAN_FIX for (i = 0; i < st_ivas->hDecoderConfig->nchan_out; i++) { floatToFixed_arrL(output_f[i], output_buf_fx[i], Q11, L_FRAME48k); } +#endif } else if (st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT) { diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 9e5afa24b..5f244108e 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -399,7 +399,6 @@ ivas_error ivas_dec_setup( // Cleanup changes for ivas_td_binaural_open: fixed to float IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) { - st_ivas->hBinRendererTd->Gain = 1.0f; /*1.0f Q15*/ fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Pos_fx, st_ivas->hBinRendererTd->Listener_p->Pos, st_ivas->hBinRendererTd->Listener_p->Pos_q, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Vel_fx, st_ivas->hBinRendererTd->Listener_p->Vel, Q30, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Front_fx, st_ivas->hBinRendererTd->Listener_p->Front, Q30, 3 ); @@ -433,17 +432,6 @@ ivas_error ivas_dec_setup( Src_p->SrcRend_p->SrcGainMin_p[nC] = 0.0f; Src_p->SrcRend_p->SrcGainMax_p[nC] = 1.0f; } - set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN ); - set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - Src_p->hrf_left_prev[0] = 1; - Src_p->hrf_right_prev[0] = 1; - Src_p->azim_prev = 0.0f; - Src_p->elev_prev = 0.0f; - Src_p->Gain = 1.0f; - Src_p->prevGain = 1.0f; TDREND_SRC_SPATIAL_t *SrcSpatial_p = st_ivas->hBinRendererTd->Sources[nS]->SrcSpatial_p; fixedToFloat_arrL( SrcSpatial_p->Pos_p_fx, SrcSpatial_p->Pos_p, Q31, 3 ); fixedToFloat_arrL( SrcSpatial_p->Front_p_fx, SrcSpatial_p->Front_p, Q30, 3 ); @@ -537,7 +525,6 @@ ivas_error ivas_dec_setup( // Cleanup changes for ivas_td_binaural_open: fixed to float IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) { - st_ivas->hBinRendererTd->Gain = 1.0f; /*1.0f Q15*/ fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Pos_fx, st_ivas->hBinRendererTd->Listener_p->Pos, st_ivas->hBinRendererTd->Listener_p->Pos_q, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Vel_fx, st_ivas->hBinRendererTd->Listener_p->Vel, Q30, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Front_fx, st_ivas->hBinRendererTd->Listener_p->Front, Q30, 3 ); @@ -571,17 +558,6 @@ ivas_error ivas_dec_setup( Src_p->SrcRend_p->SrcGainMin_p[nC] = 0.0f; Src_p->SrcRend_p->SrcGainMax_p[nC] = 1.0f; } - set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN ); - set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - Src_p->hrf_left_prev[0] = 1; - Src_p->hrf_right_prev[0] = 1; - Src_p->azim_prev = 0.0f; - Src_p->elev_prev = 0.0f; - Src_p->Gain = 1.0f; - Src_p->prevGain = 1.0f; TDREND_SRC_SPATIAL_t *SrcSpatial_p = st_ivas->hBinRendererTd->Sources[nS]->SrcSpatial_p; fixedToFloat_arrL( SrcSpatial_p->Pos_p_fx, SrcSpatial_p->Pos_p, Q31, 3 ); fixedToFloat_arrL( SrcSpatial_p->Front_p_fx, SrcSpatial_p->Front_p, Q30, 3 ); @@ -2256,7 +2232,6 @@ ivas_error ivas_init_decoder_fx( return error; } #if 1 // Cleanup changes for ivas_td_binaural_open: fixed to float - st_ivas->hBinRendererTd->Gain = 1.0f; /*1.0f Q15*/ fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Pos_fx, st_ivas->hBinRendererTd->Listener_p->Pos, st_ivas->hBinRendererTd->Listener_p->Pos_q, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Vel_fx, st_ivas->hBinRendererTd->Listener_p->Vel, Q30, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Front_fx, st_ivas->hBinRendererTd->Listener_p->Front, Q30, 3 ); @@ -2290,17 +2265,6 @@ ivas_error ivas_init_decoder_fx( Src_p->SrcRend_p->SrcGainMin_p[nC] = 0.0f; Src_p->SrcRend_p->SrcGainMax_p[nC] = 1.0f; } - set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN ); - set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - Src_p->hrf_left_prev[0] = 1; - Src_p->hrf_right_prev[0] = 1; - Src_p->azim_prev = 0.0f; - Src_p->elev_prev = 0.0f; - Src_p->Gain = 1.0f; - Src_p->prevGain = 1.0f; TDREND_SRC_SPATIAL_t *SrcSpatial_p = st_ivas->hBinRendererTd->Sources[nS]->SrcSpatial_p; fixedToFloat_arrL( SrcSpatial_p->Pos_p_fx, SrcSpatial_p->Pos_p, Q31, 3 ); fixedToFloat_arrL( SrcSpatial_p->Front_p_fx, SrcSpatial_p->Front_p, Q30, 3 ); @@ -2522,11 +2486,13 @@ ivas_error ivas_init_decoder_fx( IF( st_ivas->cldfbAnaDec[i] ) floatToFixed_arrL( st_ivas->cldfbAnaDec[i]->cldfb_state, st_ivas->cldfbAnaDec[i]->cldfb_state_fx, 11, sub( st_ivas->cldfbAnaDec[i]->p_filter_length, st_ivas->cldfbAnaDec[i]->no_channels ) ); } +#ifndef MSAN_FIX IF( st_ivas->hSpar ) { st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q = Q_factor_arr( st_ivas->hSpar->hFbMixer->cldfb_cross_fade, 16 ); floatToFixed_arr( st_ivas->hSpar->hFbMixer->cldfb_cross_fade, st_ivas->hSpar->hFbMixer->cldfb_cross_fade_fx, st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q, 16 ); } +#endif IF( st_ivas->cldfbSynDec[0] ) { floatToFixed_arrL( st_ivas->cldfbSynDec[0]->cldfb_state, st_ivas->cldfbSynDec[0]->cldfb_state_fx, Q_cldfbSynDec, sub( st_ivas->cldfbSynDec[0]->p_filter_length, st_ivas->cldfbSynDec[0]->no_channels ) ); diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index d162c9366..22d7484c4 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -634,7 +634,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( return error; } #if 1 // Cleanup changes for ivas_td_binaural_open: fixed to float - st_ivas->hBinRendererTd->Gain = 1.0f; /*1.0f Q15*/ fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Pos_fx, st_ivas->hBinRendererTd->Listener_p->Pos, st_ivas->hBinRendererTd->Listener_p->Pos_q, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Vel_fx, st_ivas->hBinRendererTd->Listener_p->Vel, Q30, 3 ); fixedToFloat_arrL( st_ivas->hBinRendererTd->Listener_p->Front_fx, st_ivas->hBinRendererTd->Listener_p->Front, Q30, 3 ); @@ -668,17 +667,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( Src_p->SrcRend_p->SrcGainMin_p[nC] = 0.0f; Src_p->SrcRend_p->SrcGainMax_p[nC] = 1.0f; } - set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN ); - set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); - set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); - Src_p->hrf_left_prev[0] = 1; - Src_p->hrf_right_prev[0] = 1; - Src_p->azim_prev = 0.0f; - Src_p->elev_prev = 0.0f; - Src_p->Gain = 1.0f; - Src_p->prevGain = 1.0f; TDREND_SRC_SPATIAL_t *SrcSpatial_p = st_ivas->hBinRendererTd->Sources[nS]->SrcSpatial_p; fixedToFloat_arrL( SrcSpatial_p->Pos_p_fx, SrcSpatial_p->Pos_p, Q31, 3 ); fixedToFloat_arrL( SrcSpatial_p->Front_p_fx, SrcSpatial_p->Front_p, Q30, 3 ); diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 08bcdc2fe..7aa01f581 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -4615,7 +4615,11 @@ ivas_error ivas_jbm_dec_render( hDecoderConfig = st_ivas->hDecoderConfig; Word16 numch_out_dirac = hDecoderConfig->nchan_out; +#ifdef MSAN_FIX + for ( i = 0; i < st_ivas->hTcBuffer->nchan_transport_internal; i++ ) +#else for ( i = 0; i < s_max( st_ivas->nchan_ism, 0 ) + nchan_internal; i++ ) +#endif { floatToFixed_arr32( st_ivas->hTcBuffer->tc[i], st_ivas->hTcBuffer->tc_fx[i], Q11, st_ivas->hTcBuffer->n_samples_available ); } @@ -5464,7 +5468,172 @@ ivas_error ivas_jbm_dec_render( } else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) { +#ifdef IVAS_FLOAT_FIXED +#if 1//ftf changes + int16_t channel_active_fx[MAX_OUTPUT_CHANNELS]; + uint16_t nchan_out_init; + Word16 nchan_out_cov; + Word16 nchan_out_cldfb = 0; + + set_s(channel_active_fx, 0, MAX_CICP_CHANNELS ); + Word16 nchan_transport_tmp = st_ivas->nchan_transport; + output_Fs = st_ivas->hDecoderConfig->output_Fs; + Word16 nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + nchan_out_init = nchan_out_transport; + + if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) + { + nchan_out_cldfb = BINAURAL_CHANNELS; + set_s(channel_active_fx, 1, BINAURAL_CHANNELS); + nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + } + else if (st_ivas->hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB) + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + } + else if (st_ivas->hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || st_ivas->hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO) + { + nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + nchan_out_cldfb = nchan_out_cov; + set_s(channel_active_fx, 1, nchan_out_cov); + } + else + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = nchan_out_transport; + set_s(channel_active_fx, 1, nchan_out_cov); + } + + FOR( i = 0; i < nchan_out_cldfb; ++i ) + { + floatToFixed_arrL( p_output[i], p_output_fx[i], Q11, L_FRAME48k ); + } + + //ftf for ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot_fx + FOR( i = 0; i < 16 * nchan_transport_tmp * st_ivas->hParamMC->num_freq_bands; i++) + { + st_ivas->hParamMC->Cldfb_RealBuffer_tc_fx[i] = floatToFixed(st_ivas->hParamMC->Cldfb_RealBuffer_tc[i], Q6); + st_ivas->hParamMC->Cldfb_ImagBuffer_tc_fx[i] = floatToFixed(st_ivas->hParamMC->Cldfb_ImagBuffer_tc[i], Q6); + } + //ftf changes + if (st_ivas->hParamMC->max_band_decorr > 0) + { + //ftf for param_mc_protoSignalComputation_fx + FOR(Word16 x = 0; x < st_ivas->hParamMC->diff_proto_info->num_protos_diff; x++) + { + Word16 num_source_ch = st_ivas->hParamMC->diff_proto_info->num_source_chan_diff[x]; + move16(); + + floatToFixed_arrL(st_ivas->hParamMC->diff_proto_info->proto_fac[x], st_ivas->hParamMC->diff_proto_info->proto_fac_fx[x], Q30, num_source_ch); + } + + //ftf for ivas_dirac_dec_decorr_process_fx + Word16 tmp_e; + f2me_buf(st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer, st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_fx, &tmp_e, st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_len); + st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer = 31 - tmp_e; + } + + FOR(Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->num_param_bands_synth; param_band_idx++) { + + + f2me_buf(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], &st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx], nchan_transport * nchan_out_cov); + + IF(st_ivas->hParamMC->band_grouping[param_band_idx] < st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr) { + f2me_buf(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], &st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx], nchan_out_cov * nchan_out_cov); + f2me_buf(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_fx[param_band_idx], &st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_exp[param_band_idx], nchan_out_cov * nchan_out_cov); + } + } + + floatToFixed_arr16(st_ivas->hParamMC->h_output_synthesis_params.interpolator, st_ivas->hParamMC->h_output_synthesis_params.interpolator_fx, 15, DEFAULT_JBM_CLDFB_TIMESLOTS); + if ((st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM)) + { + if (st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV) + { + Word16 Q_hoa_encoder = 31; + floatToFixed_arrL(st_ivas->hParamMC->hoa_encoder, st_ivas->hParamMC->hoa_encoder_fx, Q_hoa_encoder, st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS); + } + } + //ftf for ivas_binRenderer_fx + if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) + { + if (st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] && st_ivas->hBinRenderer->rotInCldfb) + { + if (st_ivas->hBinRenderer->hInputSetup->is_loudspeaker_setup == 0) + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + st_ivas->hCombinedOrientationData->Rmat_fx[st_ivas->hCombinedOrientationData->subframe_idx][i][j] = (Word32)floatToFixed(st_ivas->hCombinedOrientationData->Rmat[st_ivas->hCombinedOrientationData->subframe_idx][i][j], 30); + } + } + } + } + } + /* CLDFB synthesis */ + for (int ch = 0; ch < nchan_out_cldfb; ch++) + { + if (channel_active_fx[ch]) + { + for (i = 0; i < st_ivas->cldfbSynDec[ch]->p_filter_length; i++) + { + st_ivas->cldfbSynDec[ch]->cldfb_state_fx[i] = (Word32)(st_ivas->cldfbSynDec[ch]->cldfb_state[i] * (1LL << (5))); + } + } + } + + if (st_ivas->hParamMC->slots_rendered == st_ivas->hParamMC->num_slots) + { + FOR(Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->hMetadataPMC->nbands_coded; param_band_idx++) { + f2me_buf(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], &st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx], nchan_transport_tmp * nchan_out_cov); + IF(st_ivas->hParamMC->band_grouping[param_band_idx] < st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr) { + f2me_buf(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], &st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx], nchan_transport_tmp * nchan_out_cov); + } + } + } +#endif + ivas_param_mc_dec_render_fx(st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx, channel_active_fx); +#if 1//ftf changes + if (st_ivas->hParamMC->max_band_decorr > 0) + { + // ftf for param_mc_protoSignalComputation_fx + fixedToFloat_arrL(st_ivas->hParamMC->proto_frame_f_fx, st_ivas->hParamMC->proto_frame_f, Q11, 2 * st_ivas->hParamMC->diff_proto_info->num_protos_diff * st_ivas->hParamMC->num_freq_bands); + + // ftf for ivas_dirac_dec_decorr_process_fx + fixedToFloat_arrL32(st_ivas->hParamMC->proto_frame_dec_f_fx, st_ivas->hParamMC->proto_frame_dec_f, Q11, nchan_out_cov * 2 * st_ivas->hParamMC->num_freq_bands); + } + for (int ch = 0; ch < nchan_out_cldfb; ch++) + { + if (channel_active_fx[ch]) { + for (i = 0; i < st_ivas->cldfbSynDec[ch]->p_filter_length; i++) + { + st_ivas->cldfbSynDec[ch]->cldfb_state[i] = ((float)st_ivas->cldfbSynDec[ch]->cldfb_state_fx[i] / (1LL << (5))); + } + } + fixedToFloat_arrL(p_output_fx[ch], p_output[ch], Q11, *nSamplesRendered); + } + if (st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC) + { + FOR(i = 0; i < MAX_OUTPUT_CHANNELS; i++) + { + fixedToFloat_arrL(p_output_fx[i], p_output[i], Q11, *nSamplesRendered); + } + } + if (st_ivas->hParamMC->slots_rendered == st_ivas->hParamMC->num_slots) + { + FOR(Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->hMetadataPMC->nbands_coded; param_band_idx++) { + IF(st_ivas->hParamMC->band_grouping[param_band_idx] < st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr) { + mvr2r(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], nchan_transport_tmp * nchan_out_cov); + } + mvr2r(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[param_band_idx], nchan_transport_tmp * nchan_out_cov); + } + } +#endif + +#else ivas_param_mc_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); +#endif } else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 313c478d5..f38bbff23 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -3361,6 +3361,359 @@ void ivas_param_mc_dec_digest_tc( * Parametric MC decoding process *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED +void ivas_param_mc_dec_render_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const UWord16 nSamplesAsked, /* i : number of CLDFB slots requested */ + UWord16 *nSamplesRendered, /* o : number of CLDFB slots rendered */ + UWord16 *nSamplesAvailableNext, /* o : number of CLDFB slots still to render */ + Word32 *output_f_fx[], /* o : rendered time signal */ + Word16 channel_active_fx[MAX_OUTPUT_CHANNELS] +) +{ + PARAM_MC_DEC_HANDLE hParamMC; + Word16 i, ch; + Word16 subframe_idx; + Word16 slot_idx, slot_idx_start, slot_idx_start_cldfb_synth, first_sf, last_sf, slots_to_render; + Word16 nchan_transport, nchan_out_transport, nchan_out_cldfb; + Word16 nchan_out_cov; + + /*CLDFB*/ + Word32 Cldfb_RealBuffer_fx[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_fx[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 *p_output_f_fx[MAX_OUTPUT_CHANNELS]; + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_output_f_fx[i] = output_f_fx[i]; + } + /*Decorrelator*/ + Word32 onset_filter_fx[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; + + Word16 tmp_q = Q6; + /* format converter */ + Word16 channel_active[MAX_OUTPUT_CHANNELS]; + UWord16 nband_synth, nbands_to_zero; + UWord16 nchan_out_init; + UWord32 output_Fs; + + hParamMC = st_ivas->hParamMC; + assert( hParamMC ); + + push_wmops( "param_mc_dec_render" ); + + set_s( channel_active, 0, MAX_CICP_CHANNELS ); + nchan_transport = st_ivas->nchan_transport; + nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + nchan_out_init = nchan_out_transport; + output_Fs = st_ivas->hDecoderConfig->output_Fs; + IF ( EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV )|| EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV_ROOM) ) + { + nchan_out_cldfb = BINAURAL_CHANNELS; + set_s( channel_active, 1, nchan_out_cldfb ); + IF ( st_ivas->hCombinedOrientationData ) + { + nchan_out_init = MAX_INTERN_CHANNELS; + } + nchan_out_cov = add(st_ivas->hTransSetup.nchan_out_woLFE , st_ivas->hTransSetup.num_lfe); + } + ELSE IF ( EQ_16(hParamMC->synthesis_conf , PARAM_MC_SYNTH_LS_CONV_CLDFB )) + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = add(st_ivas->hOutSetup.nchan_out_woLFE , st_ivas->hOutSetup.num_lfe); + } + ELSE IF ( EQ_16(hParamMC->synthesis_conf , PARAM_MC_SYNTH_LS_CONV_COV )|| EQ_16(hParamMC->synthesis_conf , PARAM_MC_SYNTH_MONO_STEREO) ) + { + nchan_out_cov = add(st_ivas->hOutSetup.nchan_out_woLFE , st_ivas->hOutSetup.num_lfe); + nchan_out_cldfb = nchan_out_cov; + set_s( channel_active, 1, nchan_out_cov ); + } + ELSE + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = nchan_out_transport; + set_s( channel_active, 1, nchan_out_cov ); + } + + /* set everything to zero that will not be decoded */ + nband_synth = hParamMC->band_grouping[hParamMC->num_param_bands_synth]; + nbands_to_zero = sub(hParamMC->num_freq_bands , nband_synth); + FOR ( ch = 0; ch < nchan_out_init; ch++ ) + { + FOR ( slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++ ) + { + set32_fx( &( Cldfb_RealBuffer_fx[ch][slot_idx][nband_synth] ), 0, nbands_to_zero ); + set32_fx( &( Cldfb_ImagBuffer_fx[ch][slot_idx][nband_synth] ), 0, nbands_to_zero ); + } + } + + /* loop FOR synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( sub(hParamMC->num_slots , hParamMC->slots_rendered), nSamplesAsked / NS2SA( output_Fs, CLDFB_SLOT_NS ) ); + *nSamplesRendered = slots_to_render * NS2SA( output_Fs, CLDFB_SLOT_NS ); + Word16 j, k; + first_sf = hParamMC->subframes_rendered; + last_sf = first_sf; + WHILE ( GT_16(slots_to_render , 0 )) + { + slots_to_render = sub(slots_to_render, hParamMC->subframe_nbslots[last_sf]); + last_sf = add(last_sf, 1); + } + IF ( EQ_16(st_ivas->renderer_type , RENDERER_SBA_LINEAR_ENC )) + { + FOR ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + slots_to_render = add(slots_to_render, hParamMC->subframe_nbslots[subframe_idx]); + } + } + slot_idx_start = hParamMC->slots_rendered; + slot_idx_start_cldfb_synth = 0; + + FOR ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++ ) + { + IF ( GT_16(hParamMC->max_band_decorr , 0 )) + { + /*-----------------------------------------------------------------* + * protoype signal computation + *-----------------------------------------------------------------*/ + param_mc_protoSignalComputation_fx( &hParamMC->Cldfb_RealBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + hParamMC->proto_frame_f_fx, hParamMC->diff_proto_info, + hParamMC->num_freq_bands ); + Scale_sig32(hParamMC->proto_frame_f_fx, 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands, Q11 - Q5); + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ + /* decorrelate prototype frame */ + + ivas_dirac_dec_decorr_process_fx( hParamMC->num_freq_bands, + hParamMC->num_outputs_diff, + hParamMC->diff_proto_info->num_protos_diff, + DIRAC_SYNTHESIS_COV_MC_LS, + nchan_transport, + hParamMC->proto_frame_f_fx, + 11, + hParamMC->diff_proto_info->num_protos_diff, + hParamMC->diff_proto_info->proto_index_diff, + hParamMC->proto_frame_dec_f_fx, // output + &hParamMC->exp_proto_frame_dec_f, + onset_filter_fx, + hParamMC->h_freq_domain_decorr_ap_params, + hParamMC->h_freq_domain_decorr_ap_state ); + + /* copy decorrelated frame directly to output CLDFB buffer, acts also as intermediate */ + /* memory FOR the decorrelated signal */ + ivas_param_mc_dec_copy_diffuse_proto( hParamMC, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, nchan_out_cov, slot_idx ); + + FOR( k = 0; k < nchan_out_cov; k++ ) + { + FOR( int l = 0; l < hParamMC->h_output_synthesis_params.max_band_decorr; l++ ) + { + Cldfb_RealBuffer_fx[k][slot_idx][l] = L_shl( Cldfb_RealBuffer_fx[k][slot_idx][l], 6 - ( 31 - hParamMC->exp_proto_frame_dec_f ) ); + Cldfb_ImagBuffer_fx[k][slot_idx][l] = L_shl( Cldfb_ImagBuffer_fx[k][slot_idx][l], 6 - ( 31 - hParamMC->exp_proto_frame_dec_f ) ); + } + } + } + + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot_fx( + &hParamMC->Cldfb_RealBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp, slot_idx, slot_idx + slot_idx_start, + nchan_transport, nchan_out_cov, hParamMC ); + + IF ( ( EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV ) || EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV_ROOM) ) ) + { + IF ( st_ivas->hCombinedOrientationData && EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV) ) + { + Word16 Q_Cldfb_ImagBuffer, Q_Cldfb_RealBuffer; + Q_Cldfb_ImagBuffer = sub(Q6 , 5); /*max value =MAX_INTERN_CHANNELS(=16)*Cldfb_ImagBuffer_fx*/ + Q_Cldfb_RealBuffer = sub(Q6 , 5); + FOR ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + FOR ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + Scale_sig32( Cldfb_RealBuffer_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub(Q_Cldfb_ImagBuffer , Q6 )); + Scale_sig32( Cldfb_ImagBuffer_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub(Q_Cldfb_RealBuffer , Q6 )); + } + } + ivas_param_mc_mc2sba_cldfb_fx( st_ivas->hTransSetup, hParamMC->hoa_encoder_fx, slot_idx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, nband_synth, GAIN_LFE_FX ); + FOR ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + FOR ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + Scale_sig32( Cldfb_RealBuffer_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub(Q6 , Q_Cldfb_ImagBuffer) ); + Scale_sig32( Cldfb_ImagBuffer_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub(Q6 , Q_Cldfb_RealBuffer) ); + } + } + } + ELSE + { + /* remove LFE */ + UWord16 idx_out; + UWord16 idx_lfe; + IVAS_OUTPUT_SETUP hLsSetup; + + hLsSetup = st_ivas->hTransSetup; + /* If LFE should be rendered, add it to other channels before removing */ + IF ( st_ivas->hBinRenderer->render_lfe ) + { + Word16 tmp_exp = 0; + Word16 tmp = BASOP_Util_Divide1616_Scale( GAIN_LFE_FX, hLsSetup.nchan_out_woLFE, &tmp_exp ); + tmp_exp = tmp_exp + ( 1 - 15 ); + FOR ( idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++ ) + { + /* Copy just the first band of LFE*/ + v_multc_fixed_16( Cldfb_RealBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], tmp, Cldfb_RealBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); + v_multc_fixed_16( Cldfb_ImagBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], tmp, Cldfb_ImagBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); + + Scale_sig32( Cldfb_RealBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1, tmp_exp ); + Scale_sig32( Cldfb_ImagBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1, tmp_exp ); + FOR ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + { + IF ( hLsSetup.index_lfe[idx_lfe] != ch ) + { + v_add_fixed( Cldfb_RealBuffer_fx[ch][slot_idx], Cldfb_RealBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer_fx[ch][slot_idx], 1, 0 ); + v_add_fixed( Cldfb_ImagBuffer_fx[ch][slot_idx], Cldfb_ImagBuffer_fx[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer_fx[ch][slot_idx], 1, 0 ); + } + } + } + } + + idx_out = 0; + idx_lfe = 0; + + FOR ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + { + IF ( (GT_16( hLsSetup.num_lfe , 0 )) && ( EQ_16(hLsSetup.index_lfe[idx_lfe] , ch )) ) + { + IF ( LT_16(idx_lfe , ( sub(hLsSetup.num_lfe , 1) )) ) + { + idx_lfe = add(idx_lfe, 1); + } + } + ELSE IF ( NE_16(ch , idx_out) ) + { + Copy32( Cldfb_RealBuffer_fx[ch][slot_idx], Cldfb_RealBuffer_fx[idx_out][slot_idx], nband_synth ); + Copy32( Cldfb_ImagBuffer_fx[ch][slot_idx], Cldfb_ImagBuffer_fx[idx_out][slot_idx], nband_synth ); + idx_out = add(idx_out, 1); + } + ELSE + { + idx_out = add(idx_out, 1); + } + } + } + } + } + + IF ( EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV ) || EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV_ROOM) ) + { + Word16 input_q = 6; + /* Implement binaural rendering */ + ivas_binRenderer_fx( st_ivas->hBinRenderer, + st_ivas->hCombinedOrientationData, + hParamMC->subframe_nbslots[subframe_idx], + Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, + Cldfb_RealBuffer_fx, + Cldfb_ImagBuffer_fx, &input_q ); + + FOR ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + FOR ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + FOR ( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + { + Cldfb_RealBuffer_fx[i][j][k] = L_shl( Cldfb_RealBuffer_fx[i][j][k], sub(Q6 , input_q) ); + Cldfb_ImagBuffer_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_fx[i][j][k], sub(Q6 , input_q) ); + } + } + } + + FOR ( int idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) + { + FOR ( int idx2 = 0; idx2 < hParamMC->subframe_nbslots[subframe_idx]; idx2++ ) + { + Scale_sig32( Cldfb_RealBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub(Q6 , input_q )); + Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub(Q6 , input_q )); + } + } + /* update combined orientation access index */ + ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + } + ELSE IF ( EQ_16(hParamMC->synthesis_conf , PARAM_MC_SYNTH_LS_CONV_CLDFB )) + { + /* format conversion*/ + ivas_lssetupconversion_process_param_mc_fx( st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, channel_active ); + } + + + /* CLDFB synthesis */ + FOR ( ch = 0; ch < nchan_out_cldfb; ch++ ) + { + Word32 *RealBuffer_fx[16]; + Word32 *ImagBuffer_fx[16]; + + IF ( channel_active[ch] ) + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands FOR 48kHz */ + FOR ( i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++ ) + { + IF ( EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV )|| EQ_16(st_ivas->renderer_type , RENDERER_BINAURAL_FASTCONV_ROOM) ) + { + RealBuffer_fx[i] = Cldfb_RealBuffer_Binaural_fx[ch][i]; + ImagBuffer_fx[i] = Cldfb_ImagBuffer_Binaural_fx[ch][i]; + } + ELSE + { + RealBuffer_fx[i] = Cldfb_RealBuffer_fx[ch][i]; + ImagBuffer_fx[i] = Cldfb_ImagBuffer_fx[ch][i]; + } + } + + Word16 len = slot_idx_start_cldfb_synth * hParamMC->num_freq_bands + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]; + scale_sig32( output_f_fx[ch], len, 5 - 11 ); + cldfbSynthesis_ivas_fx( RealBuffer_fx, ImagBuffer_fx, &( output_f_fx[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + + scale_sig32( output_f_fx[ch], len, 11 - 5 ); + } + ELSE + { + set32_fx( &( output_f_fx[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), 0, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + } + } + slot_idx_start = add(slot_idx_start, hParamMC->subframe_nbslots[subframe_idx]); + slot_idx_start_cldfb_synth = add(slot_idx_start_cldfb_synth, hParamMC->subframe_nbslots[subframe_idx]); + } + IF ( EQ_16(st_ivas->renderer_type , RENDERER_SBA_LINEAR_ENC )) + { + ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_f_fx, p_output_f_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); + } + + /* update */ + + IF ( EQ_16(hParamMC->slots_rendered , hParamMC->num_slots) ) + { + hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; + param_mc_update_mixing_matrices_fx( hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp, nchan_transport, nchan_out_cov ); + } + + + hParamMC->subframes_rendered = last_sf; + *nSamplesAvailableNext = ( hParamMC->num_slots - hParamMC->slots_rendered ) * NS2SA( output_Fs, CLDFB_SLOT_NS ); + + for (int i = 0; i < MAX_OUTPUT_CHANNELS; i++) { + channel_active_fx[i] = channel_active[i]; + } + pop_wmops(); + + return; +} +#endif + void ivas_param_mc_dec_render( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ @@ -3376,8 +3729,7 @@ void ivas_param_mc_dec_render( int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; int16_t nchan_out_cov; /*CLDFB*/ - float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + #ifdef IVAS_FLOAT_FIXED Word32 Cldfb_RealBuffer_fx[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_fx[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; @@ -3385,19 +3737,25 @@ void ivas_param_mc_dec_render( Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 output_f_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; Word32 *p_output_f_fx[MAX_OUTPUT_CHANNELS]; - for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++) { + for (i = 0; i < MAX_OUTPUT_CHANNELS; i++) { p_output_f_fx[i] = output_f_fx[i]; } - #endif + float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + for ( i = 0; i < MAX_INTERN_CHANNELS; i++) { + for (int j = 0; j < PARAM_MC_MAX_NSLOTS_IN_SUBFRAME; j++) { + for (int k = 0; k < CLDFB_NO_CHANNELS_MAX; k++) { + Cldfb_RealBuffer[i][j][k] = 0; + Cldfb_ImagBuffer[i][j][k] = 0; + + } + } + } /*Decorrelator*/ float onset_filter[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; - -#ifdef IVAS_FLOAT_FIXED - Word32 onset_filter_fx[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; -#endif /* format converter */ int16_t channel_active[MAX_OUTPUT_CHANNELS]; uint16_t nband_synth, nbands_to_zero; @@ -3405,91 +3763,93 @@ void ivas_param_mc_dec_render( uint32_t output_Fs; hParamMC = st_ivas->hParamMC; - assert( hParamMC ); + assert(hParamMC); - push_wmops( "param_mc_dec_render" ); + push_wmops("param_mc_dec_render"); - set_s( channel_active, 0, MAX_CICP_CHANNELS ); + set_s(channel_active, 0, MAX_CICP_CHANNELS); nchan_transport = st_ivas->nchan_transport; nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; nchan_out_init = nchan_out_transport; output_Fs = st_ivas->hDecoderConfig->output_Fs; - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) { nchan_out_cldfb = BINAURAL_CHANNELS; - set_s( channel_active, 1, nchan_out_cldfb ); - if ( st_ivas->hCombinedOrientationData ) + set_s(channel_active, 1, nchan_out_cldfb); + if (st_ivas->hCombinedOrientationData) { nchan_out_init = MAX_INTERN_CHANNELS; } nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + else if (hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB) { nchan_out_cov = nchan_out_transport; nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + else if (hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO) { nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; nchan_out_cldfb = nchan_out_cov; - set_s( channel_active, 1, nchan_out_cov ); + set_s(channel_active, 1, nchan_out_cov); } else { nchan_out_cov = nchan_out_transport; nchan_out_cldfb = nchan_out_transport; - set_s( channel_active, 1, nchan_out_cov ); + set_s(channel_active, 1, nchan_out_cov); } /* set everything to zero that will not be decoded */ nband_synth = hParamMC->band_grouping[hParamMC->num_param_bands_synth]; nbands_to_zero = hParamMC->num_freq_bands - nband_synth; - for ( ch = 0; ch < nchan_out_init; ch++ ) + for (ch = 0; ch < nchan_out_init; ch++) { - for ( slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++ ) + for (slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++) { - set_zero( &( Cldfb_RealBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); - set_zero( &( Cldfb_ImagBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); + set_zero(&(Cldfb_RealBuffer[ch][slot_idx][nband_synth]), nbands_to_zero); + set_zero(&(Cldfb_ImagBuffer[ch][slot_idx][nband_synth]), nbands_to_zero); #ifdef IVAS_FLOAT_FIXED - set32_fx(&(Cldfb_RealBuffer_fx[ch][slot_idx][nband_synth]), 0,nbands_to_zero); - set32_fx(&(Cldfb_ImagBuffer_fx[ch][slot_idx][nband_synth]), 0,nbands_to_zero); + set32_fx(&(Cldfb_RealBuffer_fx[ch][slot_idx][nband_synth]), 0, nbands_to_zero); + set32_fx(&(Cldfb_ImagBuffer_fx[ch][slot_idx][nband_synth]), 0, nbands_to_zero); #endif } } /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min( hParamMC->num_slots - hParamMC->slots_rendered, nSamplesAsked / NS2SA( output_Fs, CLDFB_SLOT_NS ) ); - *nSamplesRendered = slots_to_render * NS2SA( output_Fs, CLDFB_SLOT_NS ); + slots_to_render = min(hParamMC->num_slots - hParamMC->slots_rendered, nSamplesAsked / NS2SA(output_Fs, CLDFB_SLOT_NS)); + *nSamplesRendered = slots_to_render * NS2SA(output_Fs, CLDFB_SLOT_NS); first_sf = hParamMC->subframes_rendered; last_sf = first_sf; - while ( slots_to_render > 0 ) + while (slots_to_render > 0) { slots_to_render -= hParamMC->subframe_nbslots[last_sf]; last_sf++; } - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + if (st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC) { - for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + for (subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++) { slots_to_render += hParamMC->subframe_nbslots[subframe_idx]; } } slot_idx_start = hParamMC->slots_rendered; slot_idx_start_cldfb_synth = 0; - for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + for (subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++) { Word16 len = slot_idx_start_cldfb_synth * hParamMC->num_freq_bands + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]; - for ( i = 0; i < nchan_out_cldfb; i++) +#ifdef IVAS_FLOAT_FIXED + for (i = 0; i < nchan_out_cldfb; i++) { floatToFixed_arrL(output_f[i], output_f_fx[i], Q11, len); } +#endif - for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++ ) + for (slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++) { - if ( hParamMC->max_band_decorr > 0 ) + if (hParamMC->max_band_decorr > 0) { /*-----------------------------------------------------------------* * protoype signal computation @@ -3497,76 +3857,54 @@ void ivas_param_mc_dec_render( #ifdef IVAS_FLOAT_FIXED - floatToFixed_arrL(hParamMC->Cldfb_RealBuffer_tc, hParamMC->Cldfb_RealBuffer_tc_fx, Q12, hParamMC->sz); + floatToFixed_arrL(hParamMC->Cldfb_RealBuffer_tc, hParamMC->Cldfb_RealBuffer_tc_fx, Q12, hParamMC->sz); - floatToFixed_arrL(hParamMC->Cldfb_ImagBuffer_tc, hParamMC->Cldfb_ImagBuffer_tc_fx, Q12, hParamMC->sz); + floatToFixed_arrL(hParamMC->Cldfb_ImagBuffer_tc, hParamMC->Cldfb_ImagBuffer_tc_fx, Q12, hParamMC->sz); - FOR(Word16 x = 0; x < hParamMC->diff_proto_info->num_protos_diff; x++) - { - Word16 num_source_ch = hParamMC->diff_proto_info->num_source_chan_diff[x]; - move16(); + FOR(Word16 x = 0; x < hParamMC->diff_proto_info->num_protos_diff; x++) + { + Word16 num_source_ch = hParamMC->diff_proto_info->num_source_chan_diff[x]; + move16(); - floatToFixed_arrL(hParamMC->diff_proto_info->proto_fac[x], hParamMC->diff_proto_info->proto_fac_fx[x], Q30, num_source_ch); - } + floatToFixed_arrL(hParamMC->diff_proto_info->proto_fac[x], hParamMC->diff_proto_info->proto_fac_fx[x], Q30, num_source_ch); + } - param_mc_protoSignalComputation_fx(&hParamMC->Cldfb_RealBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - hParamMC->proto_frame_f_fx, hParamMC->diff_proto_info, - hParamMC->num_freq_bands); + param_mc_protoSignalComputation_fx(&hParamMC->Cldfb_RealBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + hParamMC->proto_frame_f_fx, hParamMC->diff_proto_info, + hParamMC->num_freq_bands); - fixedToFloat_arrL(hParamMC->proto_frame_f_fx, hParamMC->proto_frame_f, Q11, 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands); + fixedToFloat_arrL(hParamMC->proto_frame_f_fx, hParamMC->proto_frame_f, Q11, 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands); #else - param_mc_protoSignalComputation( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - hParamMC->proto_frame_f, hParamMC->diff_proto_info, - hParamMC->num_freq_bands ); + param_mc_protoSignalComputation(&hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + hParamMC->proto_frame_f, hParamMC->diff_proto_info, + hParamMC->num_freq_bands); #endif /*-----------------------------------------------------------------* * frequency domain decorrelation *-----------------------------------------------------------------*/ - /* decorrelate prototype frame */ -#ifdef IVAS_FLOAT_FIXED - Word16 tmp_e; - f2me_buf(hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer, hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_fx, &tmp_e, hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_len ); - hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer = 31 - tmp_e; - ivas_dirac_dec_decorr_process_fx( hParamMC->num_freq_bands, - hParamMC->num_outputs_diff, - hParamMC->diff_proto_info->num_protos_diff, - DIRAC_SYNTHESIS_COV_MC_LS, - nchan_transport, - hParamMC->proto_frame_f_fx, - 11, - hParamMC->diff_proto_info->num_protos_diff, - hParamMC->diff_proto_info->proto_index_diff, - hParamMC->proto_frame_dec_f_fx,//output - &hParamMC->exp_proto_frame_dec_f, - onset_filter_fx, - hParamMC->h_freq_domain_decorr_ap_params, - hParamMC->h_freq_domain_decorr_ap_state ); - fixedToFloat_arrL32(onset_filter_fx, onset_filter, 31, MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX); - fixedToFloat_arrL32(hParamMC->proto_frame_dec_f_fx, hParamMC->proto_frame_dec_f, 11, nchan_out_cov * 2 * hParamMC->num_freq_bands); -#else - ivas_dirac_dec_decorr_process( hParamMC->num_freq_bands, - hParamMC->num_outputs_diff, - hParamMC->diff_proto_info->num_protos_diff, - DIRAC_SYNTHESIS_COV_MC_LS, - nchan_transport, - hParamMC->proto_frame_f, - hParamMC->diff_proto_info->num_protos_diff, - hParamMC->diff_proto_info->proto_index_diff, - hParamMC->proto_frame_dec_f,//output - onset_filter, - hParamMC->h_freq_domain_decorr_ap_params, - hParamMC->h_freq_domain_decorr_ap_state ); -#endif + /* decorrelate prototype frame */ + ivas_dirac_dec_decorr_process(hParamMC->num_freq_bands, + hParamMC->num_outputs_diff, + hParamMC->diff_proto_info->num_protos_diff, + DIRAC_SYNTHESIS_COV_MC_LS, + nchan_transport, + hParamMC->proto_frame_f, + hParamMC->diff_proto_info->num_protos_diff, + hParamMC->diff_proto_info->proto_index_diff, + hParamMC->proto_frame_dec_f,//output + onset_filter, + hParamMC->h_freq_domain_decorr_ap_params, + hParamMC->h_freq_domain_decorr_ap_state); /* copy decorrelated frame directly to output CLDFB buffer, acts also as intermediate */ /* memory for the decorrelated signal */ #ifdef IVAS_FLOAT_FIXED - //f2me_buf(hParamMC->proto_frame_dec_f, hParamMC->proto_frame_dec_f_fx, &hParamMC->exp_proto_frame_dec_f, nchan_out_cov * 2 * hParamMC->num_freq_bands); + f2me_buf(hParamMC->proto_frame_dec_f, hParamMC->proto_frame_dec_f_fx, &hParamMC->exp_proto_frame_dec_f, nchan_out_cov * 2 * hParamMC->num_freq_bands); ivas_param_mc_dec_copy_diffuse_proto(hParamMC, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, nchan_out_cov, slot_idx); FOR(int k = 0; k < nchan_out_cov; k++) { @@ -3575,9 +3913,9 @@ void ivas_param_mc_dec_render( Cldfb_RealBuffer[k][slot_idx][l] = me2f(Cldfb_RealBuffer_fx[k][slot_idx][l], hParamMC->exp_proto_frame_dec_f); Cldfb_ImagBuffer[k][slot_idx][l] = me2f(Cldfb_ImagBuffer_fx[k][slot_idx][l], hParamMC->exp_proto_frame_dec_f); } - } + } #else - ivas_param_mc_dec_copy_diffuse_proto( hParamMC, Cldfb_RealBuffer, Cldfb_ImagBuffer, nchan_out_cov, slot_idx ); + ivas_param_mc_dec_copy_diffuse_proto(hParamMC, Cldfb_RealBuffer, Cldfb_ImagBuffer, nchan_out_cov, slot_idx); #endif } @@ -3585,94 +3923,36 @@ void ivas_param_mc_dec_render( * output synthesis *-----------------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED - Word16 j, k; + ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot(&hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + Cldfb_RealBuffer, Cldfb_ImagBuffer, + hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, slot_idx, slot_idx + slot_idx_start, + nchan_transport, nchan_out_cov, hParamMC); - FOR ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) - { - FOR ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) - { - FOR ( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) - { - Cldfb_RealBuffer_fx[i][j][k] = (Word32) (floatToFixed( Cldfb_RealBuffer[i][j][k], 6 ) ); - Cldfb_ImagBuffer_fx[i][j][k] = (Word32) (floatToFixed(Cldfb_ImagBuffer[i][j][k], 6 ) ); - } - } - } - - FOR ( i = 0; i < 16 * nchan_transport * hParamMC->num_freq_bands; i++) - { - st_ivas->hParamMC->Cldfb_RealBuffer_tc_fx[i] = - floatToFixed(st_ivas->hParamMC->Cldfb_RealBuffer_tc[i], 6); - st_ivas->hParamMC->Cldfb_ImagBuffer_tc_fx[i] = - floatToFixed(st_ivas->hParamMC->Cldfb_ImagBuffer_tc[i], 6); - } - - FOR(Word16 param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx++) { - - - f2me_buf(hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], &hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx], nchan_transport * nchan_out_cov); - - IF(hParamMC->band_grouping[param_band_idx] < hParamMC->h_output_synthesis_params.max_band_decorr) { - f2me_buf(hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], &hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx], nchan_out_cov * nchan_out_cov); - - f2me_buf(hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_fx[param_band_idx], &hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_exp[param_band_idx], nchan_out_cov * nchan_out_cov); - } - } - - floatToFixed_arr16(hParamMC->h_output_synthesis_params.interpolator, hParamMC->h_output_synthesis_params.interpolator_fx, 15, DEFAULT_JBM_CLDFB_TIMESLOTS); - - - ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot_fx( - &hParamMC->Cldfb_RealBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc_fx[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp, slot_idx, slot_idx + slot_idx_start, - nchan_transport, nchan_out_cov, hParamMC ); - - - FOR (i = 0; i < MAX_OUTPUT_CHANNELS; i++) - { - FOR (j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++) - { - FOR (k = 0; k < CLDFB_NO_CHANNELS_MAX; k++) - { - Cldfb_RealBuffer[i][j][k] = ((float)Cldfb_RealBuffer_fx[i][j][k] / ( 1 << 6)); - Cldfb_ImagBuffer[i][j][k] = ((float)Cldfb_ImagBuffer_fx[i][j][k] / ( 1 << 6)); - } - } - } - -#else - ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - Cldfb_RealBuffer, Cldfb_ImagBuffer, - hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, slot_idx, slot_idx + slot_idx_start, - nchan_transport, nchan_out_cov, hParamMC ); -#endif - - if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) + if ((st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM)) { if ( - st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV) { #ifdef IVAS_FLOAT_FIXED #if 1 Word16 Q_hoa_encoder = 31; - floatToFixed_arrL(hParamMC->hoa_encoder, hParamMC->hoa_encoder_fx, Q_hoa_encoder, st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS ); + floatToFixed_arrL(hParamMC->hoa_encoder, hParamMC->hoa_encoder_fx, Q_hoa_encoder, st_ivas->hTransSetup.nchan_out_woLFE * MAX_INTERN_CHANNELS); Word16 Q_Cldfb_ImagBuffer, Q_Cldfb_RealBuffer; - Q_Cldfb_ImagBuffer = Q_factor_arrL( &Cldfb_ImagBuffer[0][0][0], 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ) - 5;/*max value =MAX_INTERN_CHANNELS(=16)*Cldfb_ImagBuffer_fx*/ - Q_Cldfb_RealBuffer = Q_factor_arrL( &Cldfb_RealBuffer[0][0][0], 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ) - 5; - floatToFixed_arrL( &Cldfb_ImagBuffer[0][0][0], &Cldfb_ImagBuffer_fx[0][0][0], Q_Cldfb_ImagBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); - floatToFixed_arrL( &Cldfb_RealBuffer[0][0][0], &Cldfb_RealBuffer_fx[0][0][0], Q_Cldfb_RealBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + Q_Cldfb_ImagBuffer = Q_factor_arrL(&Cldfb_ImagBuffer[0][0][0], 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX) - 5;/*max value =MAX_INTERN_CHANNELS(=16)*Cldfb_ImagBuffer_fx*/ + Q_Cldfb_RealBuffer = Q_factor_arrL(&Cldfb_RealBuffer[0][0][0], 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX) - 5; + floatToFixed_arrL(&Cldfb_ImagBuffer[0][0][0], &Cldfb_ImagBuffer_fx[0][0][0], Q_Cldfb_ImagBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX); + floatToFixed_arrL(&Cldfb_RealBuffer[0][0][0], &Cldfb_RealBuffer_fx[0][0][0], Q_Cldfb_RealBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX); #endif - ivas_param_mc_mc2sba_cldfb_fx( st_ivas->hTransSetup, hParamMC->hoa_encoder_fx, slot_idx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, nband_synth, GAIN_LFE_FX ); + ivas_param_mc_mc2sba_cldfb_fx(st_ivas->hTransSetup, hParamMC->hoa_encoder_fx, slot_idx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, nband_synth, GAIN_LFE_FX); #if 1 - fixedToFloat_arrL( &Cldfb_ImagBuffer_fx[0][0][0], &Cldfb_ImagBuffer[0][0][0], Q_Cldfb_ImagBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); - fixedToFloat_arrL( &Cldfb_RealBuffer_fx[0][0][0], &Cldfb_RealBuffer[0][0][0], Q_Cldfb_RealBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + fixedToFloat_arrL(&Cldfb_ImagBuffer_fx[0][0][0], &Cldfb_ImagBuffer[0][0][0], Q_Cldfb_ImagBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX); + fixedToFloat_arrL(&Cldfb_RealBuffer_fx[0][0][0], &Cldfb_RealBuffer[0][0][0], Q_Cldfb_RealBuffer, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX); #endif // IVAS_FLOAT_FIXED #else - ivas_param_mc_mc2sba_cldfb( st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE ); + ivas_param_mc_mc2sba_cldfb(st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE); #endif // IVAS_FLOAT_FIXED } @@ -3684,43 +3964,41 @@ void ivas_param_mc_dec_render( IVAS_OUTPUT_SETUP hLsSetup; hLsSetup = st_ivas->hTransSetup; - /* If LFE should be rendered, add it to other channels before removing */ - if ( st_ivas->hBinRenderer->render_lfe ) + if (st_ivas->hBinRenderer->render_lfe) { - for ( idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++ ) + for (idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++) { /* Copy just the first band of LFE*/ - v_multc( Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); - v_multc( Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); + v_multc(Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], (GAIN_LFE / hLsSetup.nchan_out_woLFE), Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1); + v_multc(Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], (GAIN_LFE / hLsSetup.nchan_out_woLFE), Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1); - for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + for (ch = 0; ch < (hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe); ch++) { - if ( hLsSetup.index_lfe[idx_lfe] != ch ) + if (hLsSetup.index_lfe[idx_lfe] != ch) { - v_add( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer[ch][slot_idx], 1 ); - v_add( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], 1 ); + v_add(Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer[ch][slot_idx], 1); + v_add(Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], 1); } } } } - idx_out = 0; idx_lfe = 0; - for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + for (ch = 0; ch < (hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe); ch++) { - if ( ( hLsSetup.num_lfe > 0 ) && ( hLsSetup.index_lfe[idx_lfe] == ch ) ) + if ((hLsSetup.num_lfe > 0) && (hLsSetup.index_lfe[idx_lfe] == ch)) { - if ( idx_lfe < ( hLsSetup.num_lfe - 1 ) ) + if (idx_lfe < (hLsSetup.num_lfe - 1)) { idx_lfe++; } } - else if ( ch != idx_out ) + else if (ch != idx_out) { - mvr2r( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[idx_out][slot_idx], nband_synth ); - mvr2r( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[idx_out][slot_idx], nband_synth ); + mvr2r(Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[idx_out][slot_idx], nband_synth); + mvr2r(Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[idx_out][slot_idx], nband_synth); idx_out++; } else @@ -3732,31 +4010,31 @@ void ivas_param_mc_dec_render( } } - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) { #ifdef IVAS_FLOAT_FIXED Word16 j, k; - for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + for (i = 0; i < MAX_OUTPUT_CHANNELS; i++) { - for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + for (j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++) { - for ( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + for (k = 0; k < CLDFB_NO_CHANNELS_MAX; k++) { - Cldfb_RealBuffer_fx[i][j][k] = (Word32) floatToFixed( Cldfb_RealBuffer[i][j][k], Q6 ); - Cldfb_ImagBuffer_fx[i][j][k] = (Word32) floatToFixed( Cldfb_ImagBuffer[i][j][k], Q6 ); + Cldfb_RealBuffer_fx[i][j][k] = (Word32)floatToFixed(Cldfb_RealBuffer[i][j][k], Q6); + Cldfb_ImagBuffer_fx[i][j][k] = (Word32)floatToFixed(Cldfb_ImagBuffer[i][j][k], Q6); } } } - if ( st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] && st_ivas->hBinRenderer->rotInCldfb ) + if (st_ivas->hCombinedOrientationData != NULL && st_ivas->hCombinedOrientationData->enableCombinedOrientation[st_ivas->hCombinedOrientationData->subframe_idx] && st_ivas->hBinRenderer->rotInCldfb) { - if ( st_ivas->hBinRenderer->hInputSetup->is_loudspeaker_setup == 0 ) + if (st_ivas->hBinRenderer->hInputSetup->is_loudspeaker_setup == 0) { - for ( i = 0; i < 3; i++ ) + for (i = 0; i < 3; i++) { - for ( j = 0; j < 3; j++ ) + for (j = 0; j < 3; j++) { - st_ivas->hCombinedOrientationData->Rmat_fx[st_ivas->hCombinedOrientationData->subframe_idx][i][j] = (Word32) floatToFixed( st_ivas->hCombinedOrientationData->Rmat[st_ivas->hCombinedOrientationData->subframe_idx][i][j], 30 ); + st_ivas->hCombinedOrientationData->Rmat_fx[st_ivas->hCombinedOrientationData->subframe_idx][i][j] = (Word32)floatToFixed(st_ivas->hCombinedOrientationData->Rmat[st_ivas->hCombinedOrientationData->subframe_idx][i][j], 30); } } } @@ -3764,103 +4042,103 @@ void ivas_param_mc_dec_render( Word16 input_q = 6; /* Implement binaural rendering */ - ivas_binRenderer_fx( st_ivas->hBinRenderer, - st_ivas->hCombinedOrientationData, - hParamMC->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, - Cldfb_RealBuffer_fx, - Cldfb_ImagBuffer_fx, &input_q ); + ivas_binRenderer_fx(st_ivas->hBinRenderer, + st_ivas->hCombinedOrientationData, + hParamMC->subframe_nbslots[subframe_idx], + Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, + Cldfb_RealBuffer_fx, + Cldfb_ImagBuffer_fx, &input_q); /* fixed to float */ - for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + for (i = 0; i < MAX_OUTPUT_CHANNELS; i++) { - for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + for (j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++) { - for ( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + for (k = 0; k < CLDFB_NO_CHANNELS_MAX; k++) { - Cldfb_RealBuffer[i][j][k] = fixedToFloat( Cldfb_RealBuffer_fx[i][j][k], input_q ); - Cldfb_ImagBuffer[i][j][k] = fixedToFloat( Cldfb_ImagBuffer_fx[i][j][k], input_q ); + Cldfb_RealBuffer[i][j][k] = fixedToFloat(Cldfb_RealBuffer_fx[i][j][k], input_q); + Cldfb_ImagBuffer[i][j][k] = fixedToFloat(Cldfb_ImagBuffer_fx[i][j][k], input_q); } } } - for ( int idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) + for (int idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++) { - for ( int idx2 = 0; idx2 < hParamMC->subframe_nbslots[subframe_idx]; idx2++ ) + for (int idx2 = 0; idx2 < hParamMC->subframe_nbslots[subframe_idx]; idx2++) { - Scale_sig32( Cldfb_RealBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, 6 - input_q ); - Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, 6 - input_q ); + Scale_sig32(Cldfb_RealBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, 6 - input_q); + Scale_sig32(Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, 6 - input_q); } } - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + for (i = 0; i < BINAURAL_CHANNELS; i++) { - for ( j = 0; j < hParamMC->subframe_nbslots[subframe_idx]; j++ ) + for (j = 0; j < hParamMC->subframe_nbslots[subframe_idx]; j++) { - for ( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + for (k = 0; k < CLDFB_NO_CHANNELS_MAX; k++) { - Cldfb_RealBuffer_Binaural[i][j][k] = fix_to_float( Cldfb_RealBuffer_Binaural_fx[i][j][k], Q6 ); - Cldfb_ImagBuffer_Binaural[i][j][k] = fix_to_float( Cldfb_ImagBuffer_Binaural_fx[i][j][k], Q6 ); + Cldfb_RealBuffer_Binaural[i][j][k] = fix_to_float(Cldfb_RealBuffer_Binaural_fx[i][j][k], Q6); + Cldfb_ImagBuffer_Binaural[i][j][k] = fix_to_float(Cldfb_ImagBuffer_Binaural_fx[i][j][k], Q6); } } } #else - ivas_binRenderer( st_ivas->hBinRenderer, - st_ivas->hCombinedOrientationData, - hParamMC->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); + ivas_binRenderer(st_ivas->hBinRenderer, + st_ivas->hCombinedOrientationData, + hParamMC->subframe_nbslots[subframe_idx], + Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer); #endif /* update combined orientation access index */ - ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + ivas_combined_orientation_update_index(st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]); } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + else if (hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB) { /* format conversion*/ #ifdef IVAS_FLOAT_FIXED Word16 inChannels = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; Word16 num_timeslots = hParamMC->subframe_nbslots[subframe_idx]; Word16 j; - FOR( i = 0; i < inChannels; ++i ) + FOR(i = 0; i < inChannels; ++i) { - FOR( j = 0; j < num_timeslots; ++j ) + FOR(j = 0; j < num_timeslots; ++j) { - floatToFixed_arrL( Cldfb_RealBuffer[i][j], Cldfb_RealBuffer_fx[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt ); - floatToFixed_arrL( Cldfb_ImagBuffer[i][j], Cldfb_ImagBuffer_fx[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt ); + floatToFixed_arrL(Cldfb_RealBuffer[i][j], Cldfb_RealBuffer_fx[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt); + floatToFixed_arrL(Cldfb_ImagBuffer[i][j], Cldfb_ImagBuffer_fx[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt); } } - ivas_lssetupconversion_process_param_mc_fx( st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, channel_active ); - FOR( i = 0; i < inChannels; ++i ) + ivas_lssetupconversion_process_param_mc_fx(st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, channel_active); + FOR(i = 0; i < inChannels; ++i) { - FOR( j = 0; j < num_timeslots; ++j ) + FOR(j = 0; j < num_timeslots; ++j) { - fixedToFloat_arrL( Cldfb_RealBuffer_fx[i][j], Cldfb_RealBuffer[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt ); - fixedToFloat_arrL( Cldfb_ImagBuffer_fx[i][j], Cldfb_ImagBuffer[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt ); + fixedToFloat_arrL(Cldfb_RealBuffer_fx[i][j], Cldfb_RealBuffer[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt); + fixedToFloat_arrL(Cldfb_ImagBuffer_fx[i][j], Cldfb_ImagBuffer[i][j], Q9, st_ivas->hLsSetUpConversion->sfbCnt); } } #else - ivas_lssetupconversion_process_param_mc( st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer, Cldfb_ImagBuffer, channel_active ); + ivas_lssetupconversion_process_param_mc(st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer, Cldfb_ImagBuffer, channel_active); #endif } /* CLDFB synthesis */ #ifdef IVAS_FLOAT_FIXED - - floatToFixed_arrL( &Cldfb_ImagBuffer[0][0][0], &Cldfb_ImagBuffer_fx[0][0][0], Q6, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); - floatToFixed_arrL( &Cldfb_RealBuffer[0][0][0], &Cldfb_RealBuffer_fx[0][0][0], Q6, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + + floatToFixed_arrL(&Cldfb_ImagBuffer[0][0][0], &Cldfb_ImagBuffer_fx[0][0][0], Q6, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX); + floatToFixed_arrL(&Cldfb_RealBuffer[0][0][0], &Cldfb_RealBuffer_fx[0][0][0], Q6, 16 * MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX); /* CLDFB synthesis */ - for ( ch = 0; ch < nchan_out_cldfb; ch++ ) + for (ch = 0; ch < nchan_out_cldfb; ch++) { Word32 *RealBuffer_fx[16]; Word32 *ImagBuffer_fx[16]; - if ( channel_active[ch] ) + if (channel_active[ch]) { /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++ ) + for (i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++) { - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) { RealBuffer_fx[i] = Cldfb_RealBuffer_Binaural_fx[ch][i]; ImagBuffer_fx[i] = Cldfb_ImagBuffer_Binaural_fx[ch][i]; @@ -3872,43 +4150,43 @@ void ivas_param_mc_dec_render( } } - for ( i = 0; i < st_ivas->cldfbSynDec[ch]->p_filter_length; i++ ) + for (i = 0; i < st_ivas->cldfbSynDec[ch]->p_filter_length; i++) { - st_ivas->cldfbSynDec[ch]->cldfb_state_fx[i] = (Word32) ( st_ivas->cldfbSynDec[ch]->cldfb_state[i] * ( 1LL << ( 5 ) ) ); + st_ivas->cldfbSynDec[ch]->cldfb_state_fx[i] = (Word32)(st_ivas->cldfbSynDec[ch]->cldfb_state[i] * (1LL << (5))); } - scale_sig32( output_f_fx[ch], len, 5 - 11 ); + scale_sig32(output_f_fx[ch], len, 5 - 11); - cldfbSynthesis_ivas_fx( RealBuffer_fx, ImagBuffer_fx, &( output_f_fx[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), - hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + cldfbSynthesis_ivas_fx(RealBuffer_fx, ImagBuffer_fx, &(output_f_fx[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands]), + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch]); - scale_sig32( output_f_fx[ch], len, 11 - 5 ); - for ( i = 0; i < st_ivas->cldfbSynDec[ch]->p_filter_length; i++ ) + scale_sig32(output_f_fx[ch], len, 11 - 5); + for (i = 0; i < st_ivas->cldfbSynDec[ch]->p_filter_length; i++) { - st_ivas->cldfbSynDec[ch]->cldfb_state[i] = ( (float) st_ivas->cldfbSynDec[ch]->cldfb_state_fx[i] / ( 1LL << ( 5 ) ) ); + st_ivas->cldfbSynDec[ch]->cldfb_state[i] = ((float)st_ivas->cldfbSynDec[ch]->cldfb_state_fx[i] / (1LL << (5))); } - fixedToFloat_arrL( output_f_fx[ch], output_f[ch], Q11, len ); + fixedToFloat_arrL(output_f_fx[ch], output_f[ch], Q11, len); } else { - set32_fx( &( output_f_fx[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), 0, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); - fixedToFloat_arrL( output_f_fx[ch], output_f[ch], Q11, len ); + set32_fx(&(output_f_fx[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands]), 0, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]); + fixedToFloat_arrL(output_f_fx[ch], output_f[ch], Q11, len); } } slot_idx_start += hParamMC->subframe_nbslots[subframe_idx]; slot_idx_start_cldfb_synth += hParamMC->subframe_nbslots[subframe_idx]; } #else - for ( ch = 0; ch < nchan_out_cldfb; ch++ ) + for (ch = 0; ch < nchan_out_cldfb; ch++) { float *RealBuffer[16]; float *ImagBuffer[16]; - if ( channel_active[ch] ) + if (channel_active[ch]) { /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++ ) + for (i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++) { - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) { RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; @@ -3920,351 +4198,77 @@ void ivas_param_mc_dec_render( } } - cldfbSynthesis_ivas( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), - hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + cldfbSynthesis_ivas(RealBuffer, ImagBuffer, &(output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands]), + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch]); } else { - set_f( &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), 0.0f, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + set_f(&(output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands]), 0.0f, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]); } } slot_idx_start += hParamMC->subframe_nbslots[subframe_idx]; slot_idx_start_cldfb_synth += hParamMC->subframe_nbslots[subframe_idx]; - } -#endif - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { -#ifdef IVAS_FLOAT_FIXED - ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_f_fx, p_output_f_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); -#if 1 - FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) - { - fixedToFloat_arrL(output_f_fx[i], output_f[i], Q11 , *nSamplesRendered ); - } +} #endif -#else - ivas_mc2sba( st_ivas->hIntSetup, output_f, output_f, hParamMC->num_freq_bands * slots_to_render, st_ivas->hOutSetup.ambisonics_order, 0.f ); -#endif // IVAS_FLOAT_FIXED - } - /* update */ - if ( hParamMC->slots_rendered == hParamMC->num_slots ) - { - hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; #ifdef IVAS_FLOAT_FIXED + if (hParamMC->slots_rendered == hParamMC->num_slots) + { FOR(Word16 param_band_idx = 0; param_band_idx < hParamMC->hMetadataPMC->nbands_coded; param_band_idx++) { f2me_buf(hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], &hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx], nchan_transport * nchan_out_cov); IF(hParamMC->band_grouping[param_band_idx] < hParamMC->h_output_synthesis_params.max_band_decorr) { f2me_buf(hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], &hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx], nchan_transport * nchan_out_cov); } } - - param_mc_update_mixing_matrices_fx(hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp, nchan_transport, nchan_out_cov); - - FOR(Word16 param_band_idx = 0; param_band_idx < hParamMC->hMetadataPMC->nbands_coded; param_band_idx++) { - IF( hParamMC->band_grouping[param_band_idx] < hParamMC->h_output_synthesis_params.max_band_decorr) { - mvr2r(hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], nchan_transport * nchan_out_cov ); - } - mvr2r(hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[param_band_idx], nchan_transport * nchan_out_cov); - } - -#else - param_mc_update_mixing_matrices( hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_transport, nchan_out_cov ); -#endif } - hParamMC->subframes_rendered = last_sf; - *nSamplesAvailableNext = ( hParamMC->num_slots - hParamMC->slots_rendered ) * NS2SA( output_Fs, CLDFB_SLOT_NS ); - //fclose(fp1); - //fclose(fp); - pop_wmops(); - - return; -} - +#endif -#else -void ivas_param_mc_dec_render( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ - uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ - uint16_t *nSamplesAvailableNext, /* o : number of CLDFB slots still to render */ - float *output_f[] /* o : rendered time signal */ -) -{ - PARAM_MC_DEC_HANDLE hParamMC; - int16_t i, ch; - int16_t subframe_idx; - int16_t slot_idx, slot_idx_start, slot_idx_start_cldfb_synth, first_sf, last_sf, slots_to_render; - int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; - int16_t nchan_out_cov; - /*CLDFB*/ - float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - /*Decorrelator*/ - float onset_filter[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; - /* format converter */ - int16_t channel_active[MAX_OUTPUT_CHANNELS]; - uint16_t nband_synth, nbands_to_zero; - uint16_t nchan_out_init; - uint32_t output_Fs; - - hParamMC = st_ivas->hParamMC; - assert(hParamMC); - - push_wmops("param_mc_dec_render"); - - set_s(channel_active, 0, MAX_CICP_CHANNELS); - nchan_transport = st_ivas->nchan_transport; - nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; - nchan_out_init = nchan_out_transport; - output_Fs = st_ivas->hDecoderConfig->output_Fs; - - if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) - { - nchan_out_cldfb = BINAURAL_CHANNELS; - set_s(channel_active, 1, nchan_out_cldfb); - if (st_ivas->hCombinedOrientationData) + if (st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC) { - nchan_out_init = MAX_INTERN_CHANNELS; +#ifdef IVAS_FLOAT_FIXED + ivas_mc2sba_fx(st_ivas->hIntSetup, p_output_f_fx, p_output_f_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0); +#else + ivas_mc2sba(st_ivas->hIntSetup, output_f, output_f, hParamMC->num_freq_bands * slots_to_render, st_ivas->hOutSetup.ambisonics_order, 0.f); +#endif // IVAS_FLOAT_FIXED } - nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; - } - else if (hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB) - { - nchan_out_cov = nchan_out_transport; - nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - } - else if (hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO) - { - nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - nchan_out_cldfb = nchan_out_cov; - set_s(channel_active, 1, nchan_out_cov); - } - else - { - nchan_out_cov = nchan_out_transport; - nchan_out_cldfb = nchan_out_transport; - set_s(channel_active, 1, nchan_out_cov); - } - /* set everything to zero that will not be decoded */ - nband_synth = hParamMC->band_grouping[hParamMC->num_param_bands_synth]; - nbands_to_zero = hParamMC->num_freq_bands - nband_synth; - for (ch = 0; ch < nchan_out_init; ch++) - { - for (slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++) - { - set_zero(&(Cldfb_RealBuffer[ch][slot_idx][nband_synth]), nbands_to_zero); - set_zero(&(Cldfb_ImagBuffer[ch][slot_idx][nband_synth]), nbands_to_zero); - } - } + /* update */ - /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min(hParamMC->num_slots - hParamMC->slots_rendered, nSamplesAsked / NS2SA(output_Fs, CLDFB_SLOT_NS)); - *nSamplesRendered = slots_to_render * NS2SA(output_Fs, CLDFB_SLOT_NS); - first_sf = hParamMC->subframes_rendered; - last_sf = first_sf; - while (slots_to_render > 0) - { - slots_to_render -= hParamMC->subframe_nbslots[last_sf]; - last_sf++; - } - if (st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC) - { - for (subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++) + if (hParamMC->slots_rendered == hParamMC->num_slots) { - slots_to_render += hParamMC->subframe_nbslots[subframe_idx]; - } - } - slot_idx_start = hParamMC->slots_rendered; - slot_idx_start_cldfb_synth = 0; - for (subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++) - { - for (slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++) - { - - if (hParamMC->max_band_decorr > 0) - { - /*-----------------------------------------------------------------* - * protoype signal computation - *-----------------------------------------------------------------*/ - - param_mc_protoSignalComputation(&hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - hParamMC->proto_frame_f, hParamMC->diff_proto_info, - hParamMC->num_freq_bands); - - /*-----------------------------------------------------------------* - * frequency domain decorrelation - *-----------------------------------------------------------------*/ - - /* decorrelate prototype frame */ - ivas_dirac_dec_decorr_process(hParamMC->num_freq_bands, - hParamMC->num_outputs_diff, - hParamMC->diff_proto_info->num_protos_diff, - DIRAC_SYNTHESIS_COV_MC_LS, - nchan_transport, - hParamMC->proto_frame_f, - hParamMC->diff_proto_info->num_protos_diff, - hParamMC->diff_proto_info->proto_index_diff, - hParamMC->proto_frame_dec_f, - onset_filter, - hParamMC->h_freq_domain_decorr_ap_params, - hParamMC->h_freq_domain_decorr_ap_state); - - /* copy decorrelated frame directly to output CLDFB buffer, acts also as intermediate */ - /* memory for the decorrelated signal */ - ivas_param_mc_dec_copy_diffuse_proto(hParamMC, Cldfb_RealBuffer, Cldfb_ImagBuffer, nchan_out_cov, slot_idx); - } - - /*-----------------------------------------------------------------* - * output synthesis - *-----------------------------------------------------------------*/ - - ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot(&hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - Cldfb_RealBuffer, Cldfb_ImagBuffer, - hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, slot_idx, slot_idx + slot_idx_start, - nchan_transport, nchan_out_cov, hParamMC); - - if ((st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM)) - { - if ( - st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV) - { - ivas_param_mc_mc2sba_cldfb(st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE); - } - else - { - /* remove LFE */ - uint16_t idx_out; - uint16_t idx_lfe; - IVAS_OUTPUT_SETUP hLsSetup; - - hLsSetup = st_ivas->hTransSetup; - - /* If LFE should be rendered, add it to other channels before removing */ - if (st_ivas->hBinRenderer->render_lfe) - { - for (idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++) - { - /* Copy just the first band of LFE*/ - v_multc(Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], (GAIN_LFE / hLsSetup.nchan_out_woLFE), Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1); - v_multc(Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], (GAIN_LFE / hLsSetup.nchan_out_woLFE), Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1); - - for (ch = 0; ch < (hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe); ch++) - { - if (hLsSetup.index_lfe[idx_lfe] != ch) - { - v_add(Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer[ch][slot_idx], 1); - v_add(Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], 1); - } - } - } - } - - idx_out = 0; - idx_lfe = 0; - - for (ch = 0; ch < (hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe); ch++) - { - if ((hLsSetup.num_lfe > 0) && (hLsSetup.index_lfe[idx_lfe] == ch)) - { - if (idx_lfe < (hLsSetup.num_lfe - 1)) - { - idx_lfe++; - } - } - else if (ch != idx_out) - { - mvr2r(Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[idx_out][slot_idx], nband_synth); - mvr2r(Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[idx_out][slot_idx], nband_synth); - idx_out++; - } - else - { - idx_out++; - } - } - } - } +#ifdef IVAS_FLOAT_FIXED + hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; + param_mc_update_mixing_matrices_fx(hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp, nchan_transport, nchan_out_cov); +#else + param_mc_update_mixing_matrices(hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_transport, nchan_out_cov); +#endif } - if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) - { - - ivas_binRenderer(st_ivas->hBinRenderer, - st_ivas->hCombinedOrientationData, - hParamMC->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer); - - - /* update combined orientation access index */ - ivas_combined_orientation_update_index(st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]); - } - else if (hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB) +#ifdef IVAS_FLOAT_FIXED +if (st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC) +{ + FOR(i = 0; i < MAX_OUTPUT_CHANNELS; i++) { - /* format conversion*/ - ivas_lssetupconversion_process_param_mc(st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer, Cldfb_ImagBuffer, channel_active); + fixedToFloat_arrL(output_f_fx[i], output_f[i], Q11, *nSamplesRendered); } - - /* CLDFB synthesis */ - for (ch = 0; ch < nchan_out_cldfb; ch++) - { - float *RealBuffer[16]; - float *ImagBuffer[16]; - - if (channel_active[ch]) - { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for (i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++) - { - if (st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM) - { - RealBuffer[i] = Cldfb_RealBuffer_Binaural[ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[ch][i]; - } - else - { - RealBuffer[i] = Cldfb_RealBuffer[ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[ch][i]; - } - } - - cldfbSynthesis_ivas(RealBuffer, ImagBuffer, &(output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands]), - hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch]); - } - else - { - set_f(&(output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands]), 0.0f, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx]); - } +} +if (hParamMC->slots_rendered == hParamMC->num_slots) +{ + FOR(Word16 param_band_idx = 0; param_band_idx < hParamMC->hMetadataPMC->nbands_coded; param_band_idx++) { + IF(hParamMC->band_grouping[param_band_idx] < hParamMC->h_output_synthesis_params.max_band_decorr) { + mvr2r(hParamMC->h_output_synthesis_cov_state.mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], nchan_transport * nchan_out_cov); + } + mvr2r(hParamMC->h_output_synthesis_cov_state.mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[param_band_idx], nchan_transport * nchan_out_cov); } - slot_idx_start += hParamMC->subframe_nbslots[subframe_idx]; - slot_idx_start_cldfb_synth += hParamMC->subframe_nbslots[subframe_idx]; - } - - if (st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC) - { - ivas_mc2sba(st_ivas->hIntSetup, output_f, output_f, hParamMC->num_freq_bands * slots_to_render, st_ivas->hOutSetup.ambisonics_order, 0.f); - } - - /* update */ - if (hParamMC->slots_rendered == hParamMC->num_slots) - { - hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; - param_mc_update_mixing_matrices(hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_transport, nchan_out_cov); - } - hParamMC->subframes_rendered = last_sf; - *nSamplesAvailableNext = (hParamMC->num_slots - hParamMC->slots_rendered) * NS2SA(output_Fs, CLDFB_SLOT_NS); - pop_wmops(); - - return; } +#endif +hParamMC->subframes_rendered = last_sf; +*nSamplesAvailableNext = (hParamMC->num_slots - hParamMC->slots_rendered) * NS2SA(output_Fs, CLDFB_SLOT_NS); +pop_wmops(); +return; +} -#endif /*------------------------------------------------------------------------- * ivas_param_mc_dec() * @@ -4510,17 +4514,16 @@ static void param_mc_protoSignalComputation_fx( p_real_buffer_fx = &RealBuffer_fx[source_ch_idx * num_freq_bands]; p_imag_buffer_fx = &ImagBuffer_fx[source_ch_idx * num_freq_bands]; - FOR (band = 0; band < num_freq_bands; band++) { - Word32 tmp_x = Mpy_32_32(fac_fx, (*(p_real_buffer_fx++))); // Q(30 + 12 - 31) :: Q11 + Word32 tmp_x = Mpy_32_32(fac_fx, (*(p_real_buffer_fx++))); // Q(30 + 6 - 31) :: Q5 *(p_proto_frame_fx) = L_add(*(p_proto_frame_fx), tmp_x); move32(); p_proto_frame_fx++; - tmp_x = Mpy_32_32(fac_fx, (*(p_imag_buffer_fx++))); // Q(30 + 12 - 31) :: Q11 + tmp_x = Mpy_32_32(fac_fx, (*(p_imag_buffer_fx++))); // Q(30 + 6 - 31) :: Q5 *(p_proto_frame_fx) = L_add(*(p_proto_frame_fx), tmp_x); move32(); diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c index 9cc2cd5b0..7aa9de8ce 100644 --- a/lib_dec/ivas_mdct_core_dec.c +++ b/lib_dec/ivas_mdct_core_dec.c @@ -1862,8 +1862,13 @@ void ivas_mdct_core_reconstruct_fx( Scale_sig(st->hTcxDec->syn_OverlFB, L_FRAME_MAX / 2, sub(q_win, st->Q_syn)); Scale_sig(st->hHQ_core->old_out_LB_fx, L_FRAME32k, sub(q_win, st->Q_syn)); Scale_sig(st->hHQ_core->old_out_fx, L_FRAME48k, sub(q_win, st->Q_syn)); +#ifdef MSAN_FIX + Scale_sig( synth_buf_fx, add( add( st->hTcxDec->old_synth_len, L_FRAME_PLUS ), M ), sub( q_win, q_syn ) ); + Scale_sig( synth_bufFB_fx, add( add( st->hTcxDec->old_synth_lenFB, L_FRAME_PLUS ), M ), sub( q_win, q_syn ) ); +#else Scale_sig(synth_buf_fx, 3136, sub(q_win, q_syn)); Scale_sig(synth_bufFB_fx, 3136, sub(q_win, q_syn)); +#endif Scale_sig(st->syn, M + 1, q_win - st->Q_syn); FOR( k = 0; k < nSubframes[ch]; k++ ) { @@ -1899,8 +1904,13 @@ void ivas_mdct_core_reconstruct_fx( Scale_sig(st->hTcxDec->syn_Overl_TDACFB, shr(L_FRAME_MAX, 1), sub(-1 - st->Q_syn, q_win)); Scale_sig(st->hTcxDec->syn_Overl_TDAC, shr(L_FRAME32k, 1), sub(-1 - st->Q_syn, q_win)); Scale_sig(st->hTcxDec->old_syn_Overl, shr(L_FRAME32k, 1), sub(-1 - st->Q_syn, q_win)); +#ifdef MSAN_FIX + Scale_sig( synth_buf_fx, add( add( st->hTcxDec->old_synth_len, L_FRAME_PLUS ), M ), sub(q_syn, q_win) ); + Scale_sig( synth_bufFB_fx, add( add( st->hTcxDec->old_synth_lenFB, L_FRAME_PLUS ), M ), sub(q_syn, q_win) ); +#else Scale_sig(synth_buf_fx, 3136, sub(q_syn, q_win)); Scale_sig(synth_bufFB_fx, 3136, sub(q_syn, q_win)); +#endif Scale_sig(st->syn, M + 1, st->Q_syn + 2); Scale_sig(st->hTcxDec->syn_OverlFB, shr(L_FRAME_MAX, 1), sub(st->Q_syn, q_win)); Scale_sig(st->hTcxDec->syn_Overl, shr(L_FRAME32k, 1), sub(st->Q_syn, q_win)); diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index a7870d075..d3ce9ff94 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -1,32 +1,32 @@ /****************************************************************************************************** - (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository. All Rights Reserved. - - This software is protected by copyright law and by international treaties. - The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, - Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., - Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, - Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other - contributors to this repository retain full ownership rights in their respective contributions in - the software. This notice grants no license of any kind, including but not limited to patent - license, nor is any license granted by implication, estoppel or otherwise. - - Contributors are required to enter into the IVAS codec Public Collaboration agreement before making - contributions. - - This software is provided "AS IS", without any express or implied warranties. The software is in the - development stage. It is intended exclusively for experts who have experience with such software and - solely for the purpose of inspection. All implied warranties of non-infringement, merchantability - and fitness for a particular purpose are hereby disclaimed and excluded. - - Any dispute, controversy or claim arising under or in relation to providing this software shall be - submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in - accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and - the United Nations Convention on Contracts on the International Sales of Goods. + (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. *******************************************************************************************************/ @@ -40,6 +40,7 @@ #include "ivas_prot_rend.h" #include "ivas_cnst.h" #include "ivas_rom_binauralRenderer.h" +#include "ivas_rom_binaural_crend_head.h" #include "ivas_rom_rend.h" #include "ivas_rom_com.h" #ifdef IVAS_FLOAT_FIXED @@ -49,7 +50,7 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED -Word16 slot_fx[4] = {32767, 16384, 10922 ,8192}; +Word16 slot_fx[4] = { 32767, 16384, 10922, 8192 }; #endif #define IVAS_FLOAT_FIXED_TO_BE_REMOVED @@ -64,7 +65,7 @@ Word16 slot_fx[4] = {32767, 16384, 10922 ,8192}; #define STEREO_PREPROCESS_IIR_FACTOR ( 0.9f ) #ifdef IVAS_FLOAT_FIXED -#define STEREO_PREPROCESS_IIR_FACTOR_Q15 (29491 ) +#define STEREO_PREPROCESS_IIR_FACTOR_Q15 ( 29491 ) #endif /* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */ #define ADAPT_HTPROTO_IIR_FAC 0.81450625f @@ -77,10 +78,10 @@ Word16 slot_fx[4] = {32767, 16384, 10922 ,8192}; #define TWO_POINT_FIVE_IN_Q13 20480 // Q13 #define ADAPT_HTPROTO_IIR_FAC_FX 26689 // Q15 #define LOG_10_BASE_2_Q29 1783446528 // Q29 -#define TAN_30_FX 17157 //Q15 -#define INV_TAN30_FX 28377 //Q14 +#define TAN_30_FX 17157 // Q15 +#define INV_TAN30_FX 28377 // Q14 #endif -#define ADAPT_HTPROTO_ROT_LIM_1 0.8f +#define ADAPT_HTPROTO_ROT_LIM_1 0.8f #define MAX_GAIN_CACHE_SIZE ( ( MASA_MAXIMUM_DIRECTIONS * 3 ) + MAX_NUM_OBJECTS ) /* == different calls to get gains */ @@ -90,6 +91,10 @@ typedef struct hrtfGainCache int16_t ele; float shVec[HRTF_SH_CHANNELS]; +#ifdef IVAS_FLOAT_FIXED + Word32 shVec_fx[HRTF_SH_CHANNELS]; +#endif + } PARAMBIN_HRTF_GAIN_CACHE; typedef struct parambin_rend_config_data @@ -100,6 +105,9 @@ typedef struct parambin_rend_config_data int32_t ivas_total_brate; int16_t nchan_transport; float qualityBasedSmFactor; +#ifdef IVAS_FLOAT_FIXED + Word32 qualityBasedSmFactor_fx; +#endif int16_t processReverb; ISM_MODE ism_mode; } PARAMBIN_REND_CONFIG, *PARAMBIN_REND_CONFIG_HANDLE; @@ -114,19 +122,23 @@ static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, COMBINED_ static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const int16_t num_freq_bands, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] ); #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_decorrelate_slot_fx(DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX], Word32 decIm[][CLDFB_NO_CHANNELS_MAX]); +static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX], Word32 decIm[][CLDFB_NO_CHANNELS_MAX] ); #endif +#ifdef IVAS_FLOAT_FIXED +static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 Rmat_fx[3][3], const Word16 subframe, const Word16 isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData, Word16 q ); +#else static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData ); +#endif static void ivas_dirac_dec_binaural_determine_processing_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const int16_t nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData ); #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_binaural_process_output_fx(DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[], Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat); +static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[], Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat ); -static void adaptTransportSignalsHeadtracked_fx(COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3]); +static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] ); -static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx(COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3]); +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] ); #endif static void ivas_dirac_dec_binaural_process_output( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t processReverb, const int16_t subframe ); @@ -137,8 +149,16 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( COM static void formulate2x2MixingMatrix( float Ein1, float Ein2, float CinRe, float CinIm, float Eout1, float Eout2, float CoutRe, float CoutIm, float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const float regularizationFactor ); +#ifdef IVAS_FLOAT_FIXED +static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 useCachedValue ); +#endif + static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, const int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t useCachedValue ); +#ifdef IVAS_FLOAT_FIXED +static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked ); +#endif + static void getDirectPartGains( const int16_t bin, int16_t aziDeg, int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, const uint8_t stereoMode, float Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t isHeadtracked ); static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] ); @@ -168,136 +188,136 @@ ivas_error ivas_dirac_dec_init_binaural_data( float frequency_axis[CLDFB_NO_CHANNELS_MAX]; hDiracDecBin = st_ivas->hDiracDecBin; - if ( hDiracDecBin == NULL ) + if ( hDiracDecBin == NULL ) + { + if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) { - if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); - } - - hDiracDecBin->hTdDecorr = NULL; - hDiracDecBin->hReverb = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); } - output_Fs = st_ivas->hDecoderConfig->output_Fs; - nBins = st_ivas->hSpatParamRendCom->num_freq_bands; - renderer_type = st_ivas->renderer_type; - - for ( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) - { - set_zero( hDiracDecBin->processMtxRe[j][k], nBins ); - set_zero( hDiracDecBin->processMtxIm[j][k], nBins ); - } - - for ( k = 0; k < BINAURAL_CHANNELS; k++ ) - { - set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins ); - set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins ); - } - set_zero( hDiracDecBin->ChEnePrev[j], nBins ); - set_zero( hDiracDecBin->ChEneOutPrev[j], nBins ); - } - set_zero( hDiracDecBin->ChCrossRePrev, nBins ); - set_zero( hDiracDecBin->ChCrossImPrev, nBins ); - set_zero( hDiracDecBin->ChCrossReOutPrev, nBins ); - set_zero( hDiracDecBin->ChCrossImOutPrev, nBins ); - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; + hDiracDecBin->hTdDecorr = NULL; + hDiracDecBin->hReverb = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; + } + output_Fs = st_ivas->hDecoderConfig->output_Fs; + nBins = st_ivas->hSpatParamRendCom->num_freq_bands; + renderer_type = st_ivas->renderer_type; - for ( bin = 0; bin < nBins; bin++ ) + for ( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) { - binCenterFreq = ( (float) bin + CLDFB_HALF_BIN_FREQUENCY_OFFSET ) / (float) nBins * ( (float) output_Fs / 2.0f ); - /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ - tmpFloat = max( 0.0f, 1.0f - binCenterFreq / 2700.0f ); - hDiracDecBin->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f ); + set_zero( hDiracDecBin->processMtxRe[j][k], nBins ); + set_zero( hDiracDecBin->processMtxIm[j][k], nBins ); } - for ( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ ) + for ( k = 0; k < BINAURAL_CHANNELS; k++ ) { - hDiracDecBin->diffuseFieldCoherenceX[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin]; - hDiracDecBin->diffuseFieldCoherenceY[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin]; - hDiracDecBin->diffuseFieldCoherenceZ[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin]; + set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins ); + set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins ); } + set_zero( hDiracDecBin->ChEnePrev[j], nBins ); + set_zero( hDiracDecBin->ChEneOutPrev[j], nBins ); + } + set_zero( hDiracDecBin->ChCrossRePrev, nBins ); + set_zero( hDiracDecBin->ChCrossImPrev, nBins ); + set_zero( hDiracDecBin->ChCrossReOutPrev, nBins ); + set_zero( hDiracDecBin->ChCrossImOutPrev, nBins ); + hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; - if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC ) /* Indication of binaural rendering without room effect */ - { - set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->hReverb = NULL; - } - else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */ - { - mvr2r( hHrtfParambin->parametricEarlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection, nBins ); - /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ - if ( hDiracDecBin->hReverb != NULL && ( ( hDiracDecBin->hReverb->numBins != nBins ) || - ( hDiracDecBin->hReverb->blockSize != CLDFB_SLOTS_PER_SUBFRAME ) ) ) - { + for ( bin = 0; bin < nBins; bin++ ) + { + binCenterFreq = ( (float) bin + CLDFB_HALF_BIN_FREQUENCY_OFFSET ) / (float) nBins * ( (float) output_Fs / 2.0f ); + /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ + tmpFloat = max( 0.0f, 1.0f - binCenterFreq / 2700.0f ); + hDiracDecBin->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f ); + } + + for ( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ ) + { + hDiracDecBin->diffuseFieldCoherenceX[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin]; + hDiracDecBin->diffuseFieldCoherenceY[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin]; + hDiracDecBin->diffuseFieldCoherenceZ[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin]; + } + + if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC ) /* Indication of binaural rendering without room effect */ + { + set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->hReverb = NULL; + } + else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */ + { + mvr2r( hHrtfParambin->parametricEarlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection, nBins ); + + /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ + if ( hDiracDecBin->hReverb != NULL && ( ( hDiracDecBin->hReverb->numBins != nBins ) || + ( hDiracDecBin->hReverb->blockSize != CLDFB_SLOTS_PER_SUBFRAME ) ) ) + { #ifdef IVAS_FLOAT_FIXED - ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) ); + ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) ); #else - ivas_binaural_reverb_close( &( hDiracDecBin->hReverb ) ); + ivas_binaural_reverb_close( &( hDiracDecBin->hReverb ) ); #endif - } + } if ( hDiracDecBin->hReverb == NULL ) + { + /* Todo Philips: Room acoustics should be passed here once the underlying part works. Probably enough to pick it from st_ivas but you know best. */ + if ( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) { - /* Todo Philips: Room acoustics should be passed here once the underlying part works. Probably enough to pick it from st_ivas but you know best. */ - if ( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) - { - return error; - } + return error; } } - else if ( renderer_type == RENDERER_STEREO_PARAMETRIC ) - { - set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->hReverb = NULL; - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; - } - else /* Not valid renderer type for this renderer */ - { - assert( false ); - } + } + else if ( renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->hReverb = NULL; + hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; + } + else /* Not valid renderer type for this renderer */ + { + assert( false ); + } - hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */ + hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */ - if ( hDiracDecBin->hTdDecorr == NULL ) - { - hDiracDecBin->useTdDecorr = 0; - } + if ( hDiracDecBin->hTdDecorr == NULL ) + { + hDiracDecBin->useTdDecorr = 0; + } - if ( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL ) - { - ivas_dirac_dec_decorr_close( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state ); - } + if ( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL ) + { + ivas_dirac_dec_decorr_close( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state ); + } - if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) - { - return error; - } + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + { + return error; + } - if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) ) - { - ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, nBins ); - if ( ( error = ivas_dirac_dec_decorr_open( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), - &( hDiracDecBin->h_freq_domain_decorr_ap_state ), - nBins, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - frequency_axis, - BINAURAL_CHANNELS, - output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } + if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) ) + { + ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, nBins ); + if ( ( error = ivas_dirac_dec_decorr_open( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), + &( hDiracDecBin->h_freq_domain_decorr_ap_state ), + nBins, + BINAURAL_CHANNELS, + BINAURAL_CHANNELS, + DIRAC_SYNTHESIS_PSD_LS, + frequency_axis, + BINAURAL_CHANNELS, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } - hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); st_ivas->hDiracDecBin = hDiracDecBin; @@ -341,9 +361,9 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( ivas_error error; hDiracDecBin = st_ivas->hDiracDecBin; - IF ( hDiracDecBin == NULL ) + IF( hDiracDecBin == NULL ) { - IF ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); } @@ -360,25 +380,25 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( move16(); renderer_type = st_ivas->renderer_type; - FOR ( j = 0; j < BINAURAL_CHANNELS; j++ ) + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) { - FOR ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) + FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) { -#if 1 /* todo: remove float */ +#if 1 /* todo: remove float */ set_zero( hDiracDecBin->processMtxRe[j][k], nBins ); set_zero( hDiracDecBin->processMtxIm[j][k], nBins ); - set_zero(hDiracDecBin->processMtxRePrev[j][k], nBins); - set_zero(hDiracDecBin->processMtxImPrev[j][k], nBins); + set_zero( hDiracDecBin->processMtxRePrev[j][k], nBins ); + set_zero( hDiracDecBin->processMtxImPrev[j][k], nBins ); #endif - set16_fx(hDiracDecBin->processMtxRe_fx[j][k], 0, nBins); - set16_fx(hDiracDecBin->processMtxIm_fx[j][k], 0, nBins); - set16_fx(hDiracDecBin->processMtxRePrev_fx[j][k], 0, nBins); - set16_fx(hDiracDecBin->processMtxImPrev_fx[j][k], 0, nBins); + set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxRePrev_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxImPrev_fx[j][k], 0, nBins ); } - FOR ( k = 0; k < BINAURAL_CHANNELS; k++ ) + FOR( k = 0; k < BINAURAL_CHANNELS; k++ ) { -#if 1 /* todo: remove float */ +#if 1 /* todo: remove float */ set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins ); set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins ); #endif @@ -398,7 +418,7 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( #endif hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; - FOR ( bin = 0; bin < nBins; bin++ ) + FOR( bin = 0; bin < nBins; bin++ ) { float binCenterFreq, tmpFloat; binCenterFreq = ( (float) bin + CLDFB_HALF_BIN_FREQUENCY_OFFSET ) / (float) nBins * ( (float) output_Fs / 2.0f ); @@ -430,7 +450,7 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) ); } - if ( hDiracDecBin->hReverb == NULL ) + if ( hDiracDecBin->hReverb == NULL ) { /* Todo Philips: Room acoustics should be passed here once the underlying part works. Probably enough to pick it from st_ivas but you know best. */ if ( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, st_ivas->hHrtfParambin ) ) != IVAS_ERR_OK ) @@ -462,30 +482,29 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( ivas_dirac_dec_decorr_close( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state ); } - if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) - { - return error; - } + if ( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ) != IVAS_ERR_OK ) + { + return error; + } - if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) ) - { - Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX]; - ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins ); + if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) ) + { + Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX]; + ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins ); - IF( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), - &( hDiracDecBin->h_freq_domain_decorr_ap_state ), - nBins, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - frequency_axis_fx, - BINAURAL_CHANNELS, - output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - + IF( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), + &( hDiracDecBin->h_freq_domain_decorr_ap_state ), + nBins, + BINAURAL_CHANNELS, + BINAURAL_CHANNELS, + DIRAC_SYNTHESIS_PSD_LS, + frequency_axis_fx, + BINAURAL_CHANNELS, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; } + } hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); @@ -509,7 +528,7 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( n_samples_granularity = NS2SA( st_ivas->hDecoderConfig->output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); /* Use the same granularity as tdrend */ } - IF ( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels( st_ivas ), nchan_to_allocate, nchan_to_allocate, n_samples_granularity ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels( st_ivas ), nchan_to_allocate, nchan_to_allocate, n_samples_granularity ) ) != IVAS_ERR_OK ) { return error; } @@ -529,27 +548,27 @@ void ivas_dirac_dec_close_binaural_data( ) { - IF (hBinaural == NULL || *hBinaural == NULL) + IF( hBinaural == NULL || *hBinaural == NULL ) { return; } - IF ((*hBinaural)->hReverb != NULL) + IF( ( *hBinaural )->hReverb != NULL ) { #ifdef IVAS_FLOAT_FIXED - ivas_binaural_reverb_close_fx(&((*hBinaural)->hReverb)); + ivas_binaural_reverb_close_fx( &( ( *hBinaural )->hReverb ) ); #else - ivas_binaural_reverb_close(&((*hBinaural)->hReverb)); + ivas_binaural_reverb_close( &( ( *hBinaural )->hReverb ) ); #endif } - ivas_td_decorr_dec_close(&((*hBinaural)->hTdDecorr)); - IF ((*hBinaural)->h_freq_domain_decorr_ap_params != NULL) + ivas_td_decorr_dec_close( &( ( *hBinaural )->hTdDecorr ) ); + IF( ( *hBinaural )->h_freq_domain_decorr_ap_params != NULL ) { - ivas_dirac_dec_decorr_close(&(*hBinaural)->h_freq_domain_decorr_ap_params, &(*hBinaural)->h_freq_domain_decorr_ap_state); + ivas_dirac_dec_decorr_close( &( *hBinaural )->h_freq_domain_decorr_ap_params, &( *hBinaural )->h_freq_domain_decorr_ap_state ); } - free(*hBinaural); + free( *hBinaural ); *hBinaural = NULL; return; @@ -560,18 +579,18 @@ void ivas_dirac_dec_close_binaural_data( ) { - IF ( hBinaural == NULL || *hBinaural == NULL ) + IF( hBinaural == NULL || *hBinaural == NULL ) { return; } - IF ( ( *hBinaural )->hReverb != NULL ) + IF( ( *hBinaural )->hReverb != NULL ) { ivas_binaural_reverb_close( &( ( *hBinaural )->hReverb ) ); } ivas_td_decorr_dec_close( &( ( *hBinaural )->hTdDecorr ) ); - IF ( ( *hBinaural )->h_freq_domain_decorr_ap_params != NULL ) + IF( ( *hBinaural )->h_freq_domain_decorr_ap_params != NULL ) { ivas_dirac_dec_decorr_close( &( *hBinaural )->h_freq_domain_decorr_ap_params, &( *hBinaural )->h_freq_domain_decorr_ap_state ); } @@ -594,7 +613,7 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs_fx( ) { Word16 i, j; - IF ( hHrtfParambin != NULL && *hHrtfParambin != NULL ) + IF( hHrtfParambin != NULL && *hHrtfParambin != NULL ) { /* Tables already loaded from file */ return IVAS_ERR_OK; @@ -603,13 +622,13 @@ ivas_error ivas_dirac_dec_binaural_copy_hrtfs_fx( { /* Initialise tables from ROM */ HRTFS_PARAMBIN *hrtfParambin; - IF ( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL ) + IF( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" ); } - FOR ( i = 0; i < BINAURAL_CHANNELS; i++ ) + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) { - FOR ( j = 0; j < HRTF_SH_CHANNELS; j++ ) + FOR( j = 0; j < HRTF_SH_CHANNELS; j++ ) { Copy( hrtfShCoeffsRe_fx[i][j], hrtfParambin->hrtfShCoeffsRe_fx[i][j], HRTF_NUM_BINS ); Copy( hrtfShCoeffsIm_fx[i][j], hrtfParambin->hrtfShCoeffsIm_fx[i][j], HRTF_NUM_BINS ); @@ -791,15 +810,15 @@ void ivas_dirac_dec_binaural_render( *------------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED void ivas_dirac_dec_binaural_sba_gain_fx( - Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output */ + Word32 *output[], /* i/o: synthesized core-coder transport channels/DirAC output */ const Word16 nchan_remapped, /* i : num channels after remapping of TCs */ const Word16 output_frame /* i : output frame length */ ) { Word16 n; - Word16 gain;/*Q-14*/ + Word16 gain; /*Q-14*/ - IF ( EQ_16(nchan_remapped , 1) ) + IF( EQ_16( nchan_remapped, 1 ) ) { gain = 23681; move16(); @@ -810,7 +829,7 @@ void ivas_dirac_dec_binaural_sba_gain_fx( move16(); } - FOR ( n = 0; n < nchan_remapped; n++ ) + FOR( n = 0; n < nchan_remapped; n++ ) { v_multc_fixed_16( output[n], gain, output[n], output_frame ); } @@ -863,10 +882,12 @@ static void ivas_dirac_dec_binaural_internal( int16_t slot, ch, numInChannels; float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 4; j++) { - set_zero(Cldfb_RealBuffer_in[i][j], 60); - set_zero(Cldfb_ImagBuffer_in[i][j], 60); + for ( int i = 0; i < 6; i++ ) + { + for ( int j = 0; j < 4; j++ ) + { + set_zero( Cldfb_RealBuffer_in[i][j], 60 ); + set_zero( Cldfb_ImagBuffer_in[i][j], 60 ); } } int16_t nchanSeparateChannels; @@ -1068,7 +1089,6 @@ static void ivas_dirac_dec_binaural_internal( } - nchanSeparateChannels = 0; if ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) { @@ -1099,77 +1119,71 @@ static void ivas_dirac_dec_binaural_internal( const int16_t nchan_transport, const int16_t subframe ) { - - //////////////////////////////////////////////////////////////////////////// +#if 1 double maxim = 0; Word16 q_input = 11; - IF(st_ivas->hTcBuffer->tc[nchan_transport]) - FOR(Word16 ind = 0; ind < st_ivas->cldfbAnaDec[1]->no_channels * st_ivas->cldfbAnaDec[1]->no_col; ind++) + IF( st_ivas->hTcBuffer->tc[nchan_transport] ) + FOR( Word16 ind = 0; ind < st_ivas->cldfbAnaDec[1]->no_channels * st_ivas->cldfbAnaDec[1]->no_col; ind++ ) { - st_ivas->hTcBuffer->tc_fx[nchan_transport][ind] = (Word32)(st_ivas->hTcBuffer->tc[nchan_transport][ind] * (1 << q_input)); + st_ivas->hTcBuffer->tc_fx[nchan_transport][ind] = (Word32) ( st_ivas->hTcBuffer->tc[nchan_transport][ind] * ( 1 << q_input ) ); } - FOR(Word16 cha = 0; cha < 3 + max(1, st_ivas->nchan_ism); cha++) { - FOR(Word16 ind = 0; ind < st_ivas->hTcBuffer->n_samples_available; ind++) IF(st_ivas->hTcBuffer->tc[cha]) + FOR( Word16 cha = 0; cha < 3 + max( 1, st_ivas->nchan_ism ); cha++ ) + { + FOR( Word16 ind = 0; ind < st_ivas->hTcBuffer->n_samples_available; ind++ ) + IF( st_ivas->hTcBuffer->tc[cha] ) { - st_ivas->hTcBuffer->tc_fx[cha][ind] = (Word32)(st_ivas->hTcBuffer->tc[cha][ind] * (1 << q_input)); + st_ivas->hTcBuffer->tc_fx[cha][ind] = (Word32) ( st_ivas->hTcBuffer->tc[cha][ind] * ( 1 << q_input ) ); } } - FOR(Word16 cha = 0; cha < 3 + max(1, st_ivas->nchan_ism); cha++) { - IF(st_ivas->cldfbAnaDec[cha] && st_ivas->cldfbAnaDec[cha]->cldfb_state) - FOR(Word16 ind = 0; ind < st_ivas->cldfbAnaDec[cha]->cldfb_state_length; ind++) + FOR( Word16 cha = 0; cha < 3 + max( 1, st_ivas->nchan_ism ); cha++ ) + { + IF( st_ivas->cldfbAnaDec[cha] && st_ivas->cldfbAnaDec[cha]->cldfb_state ) + FOR( Word16 ind = 0; ind < st_ivas->cldfbAnaDec[cha]->cldfb_state_length; ind++ ) { - st_ivas->cldfbAnaDec[cha]->cldfb_state_fx[ind] = (Word32)(st_ivas->cldfbAnaDec[cha]->cldfb_state[ind] * (1 << q_input)); + st_ivas->cldfbAnaDec[cha]->cldfb_state_fx[ind] = (Word32) ( st_ivas->cldfbAnaDec[cha]->cldfb_state[ind] * ( 1 << q_input ) ); } } - //IF(st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0] && st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->likelihood_noisy_speech_flt >= (1 << 0)) assert(0); - //IF(st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0]) st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->likelihood_noisy_speech = (Word16)(st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->likelihood_noisy_speech_flt * (32767)); st_ivas->cldfbAnaDec[1]->q_scale = 15; - IF(abs_s((Word16)st_ivas->cldfbAnaDec[1]->scale_flt) != 0) - st_ivas->cldfbAnaDec[1]->q_scale = norm_s((Word16)st_ivas->cldfbAnaDec[1]->scale_flt); - st_ivas->cldfbAnaDec[1]->scale = (Word16)(st_ivas->cldfbAnaDec[1]->scale_flt * (1 << st_ivas->cldfbAnaDec[1]->q_scale)); + IF( abs_s( (Word16) st_ivas->cldfbAnaDec[1]->scale_flt ) != 0 ) + st_ivas->cldfbAnaDec[1]->q_scale = norm_s( (Word16) st_ivas->cldfbAnaDec[1]->scale_flt ); + st_ivas->cldfbAnaDec[1]->scale = (Word16) ( st_ivas->cldfbAnaDec[1]->scale_flt * ( 1 << st_ivas->cldfbAnaDec[1]->q_scale ) ); maxim = 0; - IF(st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0]) - FOR(Word16 ind = 0; ind < FFTCLDFBLEN; ind++) + IF( st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0] ) + FOR( Word16 ind = 0; ind < FFTCLDFBLEN; ind++ ) { - maxim = fmax(maxim, fabs(st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind])); + maxim = fmax( maxim, fabs( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind] ) ); } - IF(st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0]) + IF( st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0] ) st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp = 0; - IF(st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0] && L_abs((Word32)maxim)!=0) st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp = 31 - norm_l((Word32)maxim); - IF(st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0]) - FOR(Word16 ind = 0; ind < FFTCLDFBLEN; ind++) + IF( st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0] && L_abs( (Word32) maxim ) != 0 ) + st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp = 31 - norm_l( (Word32) maxim ); + IF( st_ivas->hSCE[0] && st_ivas->hSCE[0]->hCoreCoder[0] ) + FOR( Word16 ind = 0; ind < FFTCLDFBLEN; ind++ ) { - st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel[ind] = (Word32)(st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind] * (1<<(31 - st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp))); + st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel[ind] = (Word32) ( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel_flt[ind] * ( 1 << ( 31 - st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp ) ) ); } Word16 q_cldfb[6][CLDFB_SLOTS_PER_SUBFRAME] = { 0 }; - FOR(Word16 ind = 0; ind < 6; ind++) + FOR( Word16 ind = 0; ind < 6; ind++ ) { - FOR(Word16 ind2 = 0; ind2 < 4; ind2++) + FOR( Word16 ind2 = 0; ind2 < 4; ind2++ ) { q_cldfb[ind][ind2] = q_input; } } - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + IF(st_ivas->hMasa) + { + st_ivas->hMasa->data.dir_decode_quality_fx = float_to_fix16(st_ivas->hMasa->data.dir_decode_quality, 14); + } +#endif DIRAC_DEC_BIN_HANDLE hDiracDecBin; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; PARAMBIN_REND_CONFIG config_data; Word16 slot, ch, numInChannels; - float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 4; j++) { - set_zero(Cldfb_RealBuffer_in[i][j], 60); - set_zero(Cldfb_ImagBuffer_in[i][j], 60); - set32_fx(Cldfb_RealBuffer_in_fx[i][j], 0, 60); - set32_fx(Cldfb_ImagBuffer_in_fx[i][j], 0, 60); - } - } Word16 nchanSeparateChannels; Word32 Rmat_fx[3][3]; - float Rmat[3][3]; Word16 max_band_decorr; DIFFUSE_DISTRIBUTION_DATA diffuseDistData; Word16 nBins, offsetSamples; @@ -1190,9 +1204,11 @@ static void ivas_dirac_dec_binaural_internal( config_data.nchan_transport = st_ivas->nchan_transport; move16(); config_data.qualityBasedSmFactor = st_ivas->hMasa != NULL ? st_ivas->hMasa->data.dir_decode_quality : 1.0f; + config_data.qualityBasedSmFactor_fx = st_ivas->hMasa != NULL ? L_shl_sat(st_ivas->hMasa->data.dir_decode_quality_fx, 17) : ONE_IN_Q31; + move32(); config_data.processReverb = st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0; move16(); - IF ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + IF( st_ivas->ivas_format == MASA_ISM_FORMAT ) { config_data.ism_mode = st_ivas->ism_mode; } @@ -1203,55 +1219,44 @@ static void ivas_dirac_dec_binaural_internal( /* The input channel number at this processing function (not nchan_transport) */ numInChannels = BINAURAL_CHANNELS; - IF ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) + IF( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) { - numInChannels = add(numInChannels, 1); + numInChannels = add( numInChannels, 1 ); } - ELSE IF ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + ELSE IF( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { - numInChannels = add(numInChannels, st_ivas->nchan_ism); + numInChannels = add( numInChannels, st_ivas->nchan_ism ); } - Rmat_fx[0][0] = ONE_IN_Q31; - move32(); + Rmat_fx[0][0] = ONE_IN_Q30; Rmat_fx[0][1] = 0; - move32(); Rmat_fx[0][2] = 0; - move32(); + move32(); move32(); move32(); Rmat_fx[1][0] = 0; - move32(); - Rmat_fx[1][1] = ONE_IN_Q31; - move32(); + Rmat_fx[1][1] = ONE_IN_Q30; Rmat_fx[1][2] = 0; - move32(); + move32(); move32(); move32(); Rmat_fx[2][0] = 0; - move32(); Rmat_fx[2][1] = 0; - move32(); - Rmat_fx[2][2] = ONE_IN_Q31; - move32(); - - - Rmat[0][0] = 1.0f; - Rmat[0][1] = 0.0f; - Rmat[0][2] = 0.0f; - - Rmat[1][0] = 0.0f; - Rmat[1][1] = 1.0f; - Rmat[1][2] = 0.0f; - - Rmat[2][0] = 0.0f; - Rmat[2][1] = 0.0f; - Rmat[2][2] = 1.0f; + Rmat_fx[2][2] = ONE_IN_Q30; + move32(); move32(); move32(); + FOR ( i = 0; i < 6; i++ ) + { + FOR ( j = 0; j < 4; j++ ) + { + set32_fx( Cldfb_RealBuffer_in_fx[i][j], 0, 60 ); + set32_fx( Cldfb_ImagBuffer_in_fx[i][j], 0, 60 ); + } + } /* CLDFB Analysis of input */ - FOR ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) { - FOR ( ch = 0; ch < numInChannels; ch++ ) + FOR( ch = 0; ch < numInChannels; ch++ ) { - IF ( ch == 0 || nchan_transport == 2 ) + IF( ch == 0 || nchan_transport == 2 ) { q_cldfb[ch][slot] = q_input; move16(); @@ -1261,7 +1266,7 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_ImagBuffer_in_fx[ch][slot], nBins, st_ivas->cldfbAnaDec[ch], &q_cldfb[ch][slot] ); } - ELSE IF ( config_data.nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */ + ELSE IF( config_data.nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */ { /* At mono input duplicate the channel to dual-mono */ mvl2l( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins ); @@ -1272,55 +1277,55 @@ static void ivas_dirac_dec_binaural_internal( ELSE /* when nchan_transport == 1 and ch == 1 */ { /* CNA and HB FD-CNG*/ - IF ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) + IF( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag ) { Word16 numCoreBands, b; Word16 slotInFrame; numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands; move16(); - slotInFrame = add(hSpatParamRendCom->slots_rendered, slot); + slotInFrame = add( hSpatParamRendCom->slots_rendered, slot ); generate_masking_noise_dirac_ivas_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, - st_ivas->cldfbAnaDec[1], - st_ivas->hTcBuffer->tc_fx[nchan_transport], - Cldfb_RealBuffer_in_fx[2][slot], Cldfb_ImagBuffer_in_fx[2][slot], - slotInFrame, - st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, - ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag, - 11, &q_cldfb[2][slot] ); + st_ivas->cldfbAnaDec[1], + st_ivas->hTcBuffer->tc_fx[nchan_transport], + Cldfb_RealBuffer_in_fx[2][slot], Cldfb_ImagBuffer_in_fx[2][slot], + slotInFrame, + st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, + ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag, + 11, &q_cldfb[2][slot] ); generate_masking_noise_dirac_ivas_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom, - st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/ - NULL, - Cldfb_RealBuffer_in_fx[1][slot], Cldfb_ImagBuffer_in_fx[1][slot], - slotInFrame, - st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, - ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag, - 0, &q_cldfb[1][slot] ); + st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/ + NULL, + Cldfb_RealBuffer_in_fx[1][slot], Cldfb_ImagBuffer_in_fx[1][slot], + slotInFrame, + st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna, + ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag, + 0, &q_cldfb[1][slot] ); /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/ - FOR ( b = 0; b < numCoreBands; b++ ) + FOR( b = 0; b < numCoreBands; b++ ) { - Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add(L_shr(Cldfb_RealBuffer_in_fx[0][slot][b], q_cldfb[0][slot] - q_input + 5), L_shr(Cldfb_RealBuffer_in_fx[2][slot][b], q_cldfb[2][slot] - q_input + 5)), 23170/* INV_SQRT2 in Q15*/ ); + Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add( L_shr( Cldfb_RealBuffer_in_fx[0][slot][b], q_cldfb[0][slot] - q_input + 5 ), L_shr( Cldfb_RealBuffer_in_fx[2][slot][b], q_cldfb[2][slot] - q_input + 5 ) ), 23170 /* INV_SQRT2 in Q15*/ ); Cldfb_RealBuffer_in_fx[1][slot][b] = Cldfb_RealBuffer_in_fx[0][slot][b]; move32(); - Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add(L_shr(Cldfb_ImagBuffer_in_fx[0][slot][b], q_cldfb[0][slot] - q_input + 5), L_shr(Cldfb_ImagBuffer_in_fx[2][slot][b], q_cldfb[2][slot] - q_input + 5)), 23170 ); + Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add( L_shr( Cldfb_ImagBuffer_in_fx[0][slot][b], q_cldfb[0][slot] - q_input + 5 ), L_shr( Cldfb_ImagBuffer_in_fx[2][slot][b], q_cldfb[2][slot] - q_input + 5 ) ), 23170 ); Cldfb_ImagBuffer_in_fx[1][slot][b] = Cldfb_ImagBuffer_in_fx[0][slot][b]; move32(); } q_cldfb[1][slot] = q_input - 5; q_cldfb[0][slot] = q_input - 5; /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/ - FOR ( ; b < nBins; b++ ) + FOR( ; b < nBins; b++ ) { - Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1(Cldfb_RealBuffer_in_fx[0][slot][b], 23170); - Cldfb_RealBuffer_in_fx[1][slot][b] = L_add(L_add(Cldfb_RealBuffer_in_fx[0][slot][b], L_shr(Cldfb_RealBuffer_in_fx[1][slot][b], 1)), Cldfb_RealBuffer_in_fx[0][slot][b]); - Cldfb_RealBuffer_in_fx[0][slot][b] = L_add(Cldfb_RealBuffer_in_fx[0][slot][b], L_shr(Cldfb_RealBuffer_in_fx[2][slot][b], 1)); + Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( Cldfb_RealBuffer_in_fx[0][slot][b], 23170 ); + Cldfb_RealBuffer_in_fx[1][slot][b] = L_add( L_add( Cldfb_RealBuffer_in_fx[0][slot][b], L_shr( Cldfb_RealBuffer_in_fx[1][slot][b], 1 ) ), Cldfb_RealBuffer_in_fx[0][slot][b] ); + Cldfb_RealBuffer_in_fx[0][slot][b] = L_add( Cldfb_RealBuffer_in_fx[0][slot][b], L_shr( Cldfb_RealBuffer_in_fx[2][slot][b], 1 ) ); - Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1(Cldfb_ImagBuffer_in_fx[0][slot][b], 23170); - Cldfb_ImagBuffer_in_fx[1][slot][b] = L_add(Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr(Cldfb_ImagBuffer_in_fx[1][slot][b], 1)); - Cldfb_ImagBuffer_in_fx[0][slot][b] = L_add(Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr(Cldfb_ImagBuffer_in_fx[2][slot][b], 1)); + Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( Cldfb_ImagBuffer_in_fx[0][slot][b], 23170 ); + Cldfb_ImagBuffer_in_fx[1][slot][b] = L_add( Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr( Cldfb_ImagBuffer_in_fx[1][slot][b], 1 ) ); + Cldfb_ImagBuffer_in_fx[0][slot][b] = L_add( Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr( Cldfb_ImagBuffer_in_fx[2][slot][b], 1 ) ); } } ELSE @@ -1338,9 +1343,9 @@ static void ivas_dirac_dec_binaural_internal( } } - IF ( hDiracDecBin->useTdDecorr ) + IF( hDiracDecBin->useTdDecorr ) { - FOR ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ ) + FOR( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ ) { q_cldfb[ch][slot] = q_input; cldfbAnalysis_ts_fx_fixed_q( @@ -1348,8 +1353,8 @@ static void ivas_dirac_dec_binaural_internal( Cldfb_RealBuffer_in_fx[ch][slot], Cldfb_ImagBuffer_in_fx[ch][slot], nBins, st_ivas->cldfbAnaDec[ch], &q_cldfb[ch][slot] ); - IF ( config_data.nchan_transport == 1 && - ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) ) + IF( config_data.nchan_transport == 1 && + ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) ) { v_multc_fixed_16( Cldfb_RealBuffer_in_fx[ch][slot], 23170, Cldfb_RealBuffer_in_fx[ch][slot], nBins ); v_multc_fixed_16( Cldfb_ImagBuffer_in_fx[ch][slot], 23170, Cldfb_ImagBuffer_in_fx[ch][slot], nBins ); @@ -1358,160 +1363,193 @@ static void ivas_dirac_dec_binaural_internal( } } - ////////////////////////////////////////////////////////////////////////////////////////////// - FOR(Word16 cha = 0; cha < 3 + max(1, st_ivas->nchan_ism); cha++) IF(st_ivas->cldfbAnaDec[cha] && st_ivas->cldfbAnaDec[cha]->cldfb_state) - FOR(Word16 ind = 0; ind < st_ivas->cldfbAnaDec[cha]->cldfb_state_length; ind++) - { - st_ivas->cldfbAnaDec[cha]->cldfb_state[ind] = (float)(st_ivas->cldfbAnaDec[cha]->cldfb_state_fx[ind]) / (float)(1 << q_input); - } - if (st_ivas->hSpar != NULL) - { - //floatToFixed_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_prev[0][0][0][0], &st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0], Q30, sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx) / sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0])); - //st_ivas->hSpar->hMdDec->Q_mixer_mat = 30; - //for (int ii = 0; ii < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; ii++) - //{ - // for (int jj = 0; jj < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; jj++) - // { - // floatToFixed_arrL(&st_ivas->hSpar->hMdDec->mixer_mat[ii][jj][0], - // &st_ivas->hSpar->hMdDec->mixer_mat_fx[ii][jj][0], - // Q30, - // st_ivas->hSpar->hMdDec->mix_mat_dim_2); - // } - //} - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) + IF ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) { hDiracDecBin->hDiffuseDist = &diffuseDistData; ivas_spar_param_to_masa_param_mapping_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe ); ivas_sba_prototype_renderer_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe ); } - - //////////////////to be deletede from here - if (st_ivas->hDiracDecBin != NULL) - { - DIFFUSE_DISTRIBUTION_HANDLE hDiffuseDist = st_ivas->hDiracDecBin->hDiffuseDist; - IF(hDiffuseDist != NULL) - { - fixedToFloat_arrL(hDiffuseDist->diffuseRatioX_fx, hDiffuseDist->diffuseRatioX, Q31, CLDFB_NO_CHANNELS_MAX); - fixedToFloat_arrL(hDiffuseDist->diffuseRatioY_fx, hDiffuseDist->diffuseRatioY, Q31, CLDFB_NO_CHANNELS_MAX); - fixedToFloat_arrL(hDiffuseDist->diffuseRatioZ_fx, hDiffuseDist->diffuseRatioZ, Q31, CLDFB_NO_CHANNELS_MAX); - } - } - - - if (st_ivas->hSpar != NULL) - { - //fixedToFloat_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0], &st_ivas->hSpar->hMdDec->mixer_mat_prev[0][0][0][0], Q30, sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx) / sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0])); - //st_ivas->hSpar->hMdDec->Q_mixer_mat = 30; - //for (int ii = 0; ii < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; ii++) - //{ - // for (int jj = 0; jj < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; jj++) - // { - // fixedToFloat_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_fx[ii][jj][0], - // &st_ivas->hSpar->hMdDec->mixer_mat[ii][jj][0], - // Q30, - // st_ivas->hSpar->hMdDec->mix_mat_dim_2); - // } - //} - } - - FOR(Word16 cha = 0; cha < 6; cha++) FOR(slot = 0; slot < 4; slot++) - FOR(Word16 ind = 0; ind < 60; ind++) + Word16 q_inp = Q6; + FOR( Word16 cha = 0; cha < 6; cha++ ) { - Cldfb_RealBuffer_in[cha][slot][ind] = (float)Cldfb_RealBuffer_in_fx[cha][slot][ind] / (float)(1 << (q_cldfb[cha][slot])); - Cldfb_ImagBuffer_in[cha][slot][ind] = (float)Cldfb_ImagBuffer_in_fx[cha][slot][ind] / (float)(1 << (q_cldfb[cha][slot])); + FOR( slot = 0; slot < 4; slot++ ) + { + scale_sig32(Cldfb_RealBuffer_in_fx[cha][slot], 60, sub(q_inp, q_cldfb[cha][slot])); + scale_sig32(Cldfb_ImagBuffer_in_fx[cha][slot], 60, sub(q_inp, q_cldfb[cha][slot])); + } } - - //////////////////to be deletedeto here - if ( st_ivas->ivas_format == MASA_ISM_FORMAT && nchan_transport == 2 && st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + IF( st_ivas->ivas_format == MASA_ISM_FORMAT && nchan_transport == 2 && st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) { - ivas_omasa_preProcessStereoTransportsForMovedObjects( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, subframe ); + /* Un-tested function. No test-case is hitting.*/ + ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, &q_inp, nBins, subframe ); } IF( hCombinedOrientationData ) { - FOR( i = 0; i < 3; i++ ) + FOR( i = 0; i < 3; i++ ) { - FOR( j = 0; j < 3; j++ ) + FOR( j = 0; j < 3; j++ ) { -#ifdef IVAS_FLOAT_FIXED - Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30// -#endif - Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j]; + Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30// } } IF( EQ_16( nchan_transport, 2 ) ) { -#ifdef IVAS_FLOAT_FIXED - Word16 q_inp = Q6; - FOR( Word16 cha = 0; cha < 2; cha++ ) - FOR( slot = 0; slot < 4; slot++ ) - FOR( Word16 ind = 0; ind < 60; ind++ ) - { - Cldfb_RealBuffer_in_fx[cha][slot][ind] = float_to_fix( Cldfb_RealBuffer_in[cha][slot][ind], q_inp ); - Cldfb_ImagBuffer_in_fx[cha][slot][ind] = float_to_fix( Cldfb_ImagBuffer_in[cha][slot][ind], q_inp ); - } adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); - FOR( Word16 cha = 0; cha < 2; cha++ ) - FOR( slot = 0; slot < 4; slot++ ) - FOR( Word16 ind = 0; ind < 60; ind++ ) - { - Cldfb_RealBuffer_in[cha][slot][ind] = fix_to_float( Cldfb_RealBuffer_in_fx[cha][slot][ind], q_inp ); - Cldfb_ImagBuffer_in[cha][slot][ind] = fix_to_float( Cldfb_ImagBuffer_in_fx[cha][slot][ind], q_inp ); - } -#else - adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat ); - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat ); -#endif } } - ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe, - hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, st_ivas->hMasaIsmData ); +#if 1 + Word16 q_earlyPartEneCorrection = Q_factor_arrL( hDiracDecBin->earlyPartEneCorrection, hSpatParamRendCom->num_freq_bands ); + hDiracDecBin->q_earlyPartEneCorrection = q_earlyPartEneCorrection; + floatToFixed_arr32( hDiracDecBin->earlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection_fx, q_earlyPartEneCorrection, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherence, hDiracDecBin->diffuseFieldCoherence_fx, Q31, hSpatParamRendCom->num_freq_bands ); - if ( config_data.ivas_format == ISM_FORMAT ) + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { - max_band_decorr = 0; + f2me( hDiracDecBin->ChCrossRePrev[j], &hDiracDecBin->ChCrossRePrev_fx[j], &hDiracDecBin->ChCrossRePrev_e[j] ); + f2me( hDiracDecBin->ChCrossImPrev[j], &hDiracDecBin->ChCrossImPrev_fx[j], &hDiracDecBin->ChCrossImPrev_e[j] ); + f2me( hDiracDecBin->ChCrossReOutPrev[j], &hDiracDecBin->ChCrossReOutPrev_fx[j], &hDiracDecBin->ChCrossReOutPrev_e[j] ); + f2me( hDiracDecBin->ChCrossImOutPrev[j], &hDiracDecBin->ChCrossImOutPrev_fx[j], &hDiracDecBin->ChCrossImOutPrev_e[j] ); + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + f2me( hDiracDecBin->ChEnePrev[i][j], &hDiracDecBin->ChEnePrev_fx[i][j], &hDiracDecBin->ChEnePrev_e[i][j] ); + f2me( hDiracDecBin->ChEneOutPrev[i][j], &hDiracDecBin->ChEneOutPrev_fx[i][j], &hDiracDecBin->ChEneOutPrev_e[i][j] ); + } } - else if ( hDiracDecBin->useTdDecorr ) + FOR( i = 0; i < hSpatParamRendCom->dirac_md_buffer_length; i++ ) + { + IF( hSpatParamRendCom->energy_ratio1 ) + floatToFixed_arrL32( hSpatParamRendCom->energy_ratio1[i], hSpatParamRendCom->energy_ratio1_fx[i], Q30, hSpatParamRendCom->num_freq_bands ); + IF( hSpatParamRendCom->energy_ratio2 ) + floatToFixed_arrL32( hSpatParamRendCom->energy_ratio2[i], hSpatParamRendCom->energy_ratio2_fx[i], Q30, hSpatParamRendCom->num_freq_bands ); + } + IF( st_ivas->hMasaIsmData ) + FOR( i = 0; i < 4; i++ ) + { + FOR( j = 0; j < 6; j++ ) + { + floatToFixed_arrL32( st_ivas->hMasaIsmData->energy_ratio_ism[i][j], st_ivas->hMasaIsmData->energy_ratio_ism_fx[i][j], Q30, 60 ); + } + } + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherence, hDiracDecBin->diffuseFieldCoherence_fx, 31, hSpatParamRendCom->num_freq_bands ); + IF( hDiracDecBin->hDiffuseDist ) + { + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceX, hDiracDecBin->diffuseFieldCoherenceX_fx, 31, 9 ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceY, hDiracDecBin->diffuseFieldCoherenceY_fx, 31, 9 ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceZ, hDiracDecBin->diffuseFieldCoherenceZ_fx, 31, 9 ); + } +#endif + Word16 shift = 31; + Word32 Cldfb_RealBuffer_inTmp_fx[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Cldfb_ImagBuffer_inTmp_fx[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + shift = s_min(shift, getScaleFactor32(Cldfb_RealBuffer_in_fx[i][j], CLDFB_NO_CHANNELS_MAX)); + shift = s_min(shift, getScaleFactor32(Cldfb_ImagBuffer_in_fx[i][j], CLDFB_NO_CHANNELS_MAX)); + } + } + + Word16 q = q_inp + shift; + + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + FOR( Word16 k = 0; k < 60; k++ ) + { + Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); + Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); + } + } + } + + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_inTmp_fx, Cldfb_ImagBuffer_inTmp_fx, Rmat_fx, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, st_ivas->hMasaIsmData, q ); + + IF ( config_data.ivas_format == ISM_FORMAT ) + { + max_band_decorr = 0; + move16(); + } + ELSE IF ( hDiracDecBin->useTdDecorr ) { max_band_decorr = CLDFB_NO_CHANNELS_MAX; + move16(); } - else + ELSE { max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr; + move16(); } - nchanSeparateChannels = 0; - if ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) + move16(); + IF ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) { nchanSeparateChannels = 1; + move16(); } - else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + ELSE IF ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { - nchanSeparateChannels = (uint8_t) st_ivas->nchan_ism; + nchanSeparateChannels = (UWord8) st_ivas->nchan_ism; + move16(); + } + +#if 1 + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hDiracDecBin->ChEnePrev[i][j] = me2f( hDiracDecBin->ChEnePrev_fx[i][j], hDiracDecBin->ChEnePrev_e[i][j] ); + hDiracDecBin->ChEne[i][j] = me2f( hDiracDecBin->ChEne_fx[i][j], hDiracDecBin->ChEne_e[i][j] ); + hDiracDecBin->ChEneOut[i][j] = me2f( hDiracDecBin->ChEneOut_fx[i][j], hDiracDecBin->ChEneOut_e[i][j] ); + hDiracDecBin->ChEneOutPrev[i][j] = me2f( hDiracDecBin->ChEneOutPrev_fx[i][j], hDiracDecBin->ChEneOutPrev_e[i][j] ); + } + } + + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hDiracDecBin->ChCrossRePrev[j] = me2f( hDiracDecBin->ChCrossRePrev_fx[j], hDiracDecBin->ChCrossRePrev_e[j] ); + hDiracDecBin->ChCrossImPrev[j] = me2f( hDiracDecBin->ChCrossImPrev_fx[j], hDiracDecBin->ChCrossImPrev_e[j] ); + hDiracDecBin->ChCrossRe[j] = me2f( hDiracDecBin->ChCrossRe_fx[j], hDiracDecBin->ChCrossRe_e[j] ); + hDiracDecBin->ChCrossIm[j] = me2f( hDiracDecBin->ChCrossIm_fx[j], hDiracDecBin->ChCrossIm_e[j] ); + hDiracDecBin->ChCrossReOut[j] = me2f( hDiracDecBin->ChCrossReOut_fx[j], hDiracDecBin->ChCrossReOut_e[j] ); + hDiracDecBin->ChCrossImOut[j] = me2f( hDiracDecBin->ChCrossImOut_fx[j], hDiracDecBin->ChCrossImOut_e[j] ); + hDiracDecBin->ChCrossReOutPrev[j] = me2f( hDiracDecBin->ChCrossReOutPrev_fx[j], hDiracDecBin->ChCrossReOutPrev_e[j] ); + hDiracDecBin->ChCrossImOutPrev[j] = me2f( hDiracDecBin->ChCrossImOutPrev_fx[j], hDiracDecBin->ChCrossImOutPrev_e[j] ); } + fixedToFloat_arrL( hDiracDecBin->frameMeanDiffuseness_fx, hDiracDecBin->frameMeanDiffuseness, 29, CLDFB_NO_CHANNELS_MAX ); + FOR( Word16 cha = 0; cha < 3 + max( 1, st_ivas->nchan_ism ); cha++ ) + IF( st_ivas->cldfbAnaDec[cha] && st_ivas->cldfbAnaDec[cha]->cldfb_state ) + FOR( Word16 ind = 0; ind < st_ivas->cldfbAnaDec[cha]->cldfb_state_length; ind++ ) + { + st_ivas->cldfbAnaDec[cha]->cldfb_state[ind] = (float) ( st_ivas->cldfbAnaDec[cha]->cldfb_state_fx[ind] ) / (float) ( 1 << q_input ); + } +#endif + + //TODO: To be removed once below function is fixed + float Rmat[3][3]; + for(i=0;i<3;i++) + { + fixedToFloat_arrL32(Rmat_fx[i], Rmat[i], Q30, 3); + } ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData ); -#ifdef IVAS_FLOAT_FIXED +#if 1 Word32 *output_fx[MAX_OUTPUT_CHANNELS]; Word32 output_fx_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; Word16 q_out; Word16 q_mat = 15; - Word16 q_inp = Q6; + q_inp = Q6; FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { output_fx[ch] = output_fx_buff[ch]; @@ -1536,11 +1574,7 @@ static void ivas_dirac_dec_binaural_internal( q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxImPrev[ch][slot], nBins ) ); } } - q_mat = sub(q_mat, 1) ; //guardbits// - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - output_fx[ch] = output_fx_buff[ch]; - } + q_mat = sub( q_mat, 1 ); // guardbits// FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) @@ -1563,27 +1597,21 @@ static void ivas_dirac_dec_binaural_internal( floatToFixed_arrL( st_ivas->cldfbSynDec[ch]->cldfb_state, st_ivas->cldfbSynDec[ch]->cldfb_state_fx, Q11, st_ivas->cldfbSynDec[ch]->p_filter_length ); st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11; } - FOR( Word16 cha = 0; cha < 6; cha++ ) - FOR( slot = 0; slot < 4; slot++ ) - FOR( Word16 ind = 0; ind < 60; ind++ ) - { - Cldfb_RealBuffer_in_fx[cha][slot][ind] = float_to_fix( Cldfb_RealBuffer_in[cha][slot][ind], q_inp); - Cldfb_ImagBuffer_in_fx[cha][slot][ind] = float_to_fix( Cldfb_ImagBuffer_in[cha][slot][ind], q_inp); - } - ivas_dirac_dec_binaural_process_output_fx(hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat); +#endif + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); + + hDiracDecBin->hDiffuseDist = NULL; + + hSpatParamRendCom->slots_rendered = add(hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe]); + hSpatParamRendCom->subframes_rendered = add(hSpatParamRendCom->subframes_rendered, 1); +#if 1 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { fixedToFloat_arrL32( output_fx[ch], output_f[ch], q_out, imult1616( nBins, hSpatParamRendCom->subframe_nbslots[subframe] ) ); fixedToFloat_arrL32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_state, st_ivas->cldfbSynDec[ch]->Q_cldfb_state, st_ivas->cldfbSynDec[ch]->p_filter_length ); } -#else - ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, config_data.processReverb, subframe ); #endif - hDiracDecBin->hDiffuseDist = NULL; - - hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe]; - hSpatParamRendCom->subframes_rendered++; return; } @@ -1667,8 +1695,8 @@ static void ivas_dirac_dec_decorrelate_slot_fx( offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); FOR( bin = 0; bin < num_freq_bands; bin++ ) { - protoFrame_fx[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; - protoFrame_fx[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; + protoFrame_fx[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin]; + protoFrame_fx[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin]; } } @@ -1698,11 +1726,12 @@ static void ivas_dirac_dec_decorrelate_slot_fx( decIm[ch][bin] = decorrelatedFrameInterleaved_fx[( bin * BINAURAL_CHANNELS ) + offset + 1]; } } - //q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame // + // q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame // return; } #endif +#ifndef IVAS_FLOAT_FIXED static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, @@ -2170,915 +2199,1179 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric return; } - -static void ivas_dirac_dec_binaural_determine_processing_matrices( +#else +static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, - const int16_t max_band_decorr, - float Rmat[3][3], - const int16_t subframe, - const int16_t isHeadtracked, - const int16_t nchanSeparateChannels, - const MASA_ISM_DATA_HANDLE hMasaIsmData ) + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 Rmat_fx[3][3], + const Word16 subframe, + const Word16 isHeadtracked, + const MASA_ISM_DATA_HANDLE hMasaIsmData, + Word16 q) { - int16_t chA, chB, bin; - int16_t separateCenterChannelRendering; - int16_t nBins; - int16_t dirac_read_idx; - PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS]; - int16_t idx; - ISM_MODE ism_mode; + Word16 ch, slot, bin; + Word16 separateCenterChannelRendering; + Word16 nBins, idx, shift; + Word32 frameMeanDiffusenessEneWeight_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 IIReneLimiterFactor_fx; // Q26 + Word32 qualityBasedSmFactor_fx; + Word32 lowBitRateEQ_fx[CLDFB_NO_CHANNELS_MAX]; + UWord8 applyLowBitRateEQ; + Word16 dirac_read_idx; + Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 q_subFrameTotalEne; + PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE]; IVAS_FORMAT ivas_format; MC_MODE mc_mode; - int32_t ivas_total_brate; - int16_t nchan_transport; + Word32 ivas_total_brate; + Word16 nchan_transport; + Word16 gainCacheBaseIndex; + Word16 q_earlyPartEneCorrection; + q_earlyPartEneCorrection = hDiracDecBin->q_earlyPartEneCorrection; + separateCenterChannelRendering = hConfig->separateCenterChannelRendering; + move16(); ivas_format = hConfig->ivas_format; - separateCenterChannelRendering = nchanSeparateChannels > 0; mc_mode = hConfig->mc_mode; ivas_total_brate = hConfig->ivas_total_brate; + move32(); nchan_transport = hConfig->nchan_transport; + move16(); + qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; + qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); + nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ + move16(); - ism_mode = hConfig->ism_mode; + set32_fx( hDiracDecBin->ChCrossRe_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossIm_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossReOut_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossImOut_fx, 0, nBins ); - dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + set16_fx( hDiracDecBin->ChCrossRe_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossIm_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossReOut_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossImOut_e, 0, nBins ); + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + set32_fx( hDiracDecBin->ChEne_fx[ch], 0, nBins ); + set32_fx( hDiracDecBin->ChEneOut_fx[ch], 0, nBins ); - for ( idx = 0; idx < MAX_NUM_OBJECTS; idx++ ) + set16_fx( hDiracDecBin->ChEne_e[ch], 0, nBins ); + set16_fx( hDiracDecBin->ChEneOut_e[ch], 0, nBins ); + } + set32_fx( hDiracDecBin->frameMeanDiffuseness_fx, 0, nBins ); + + set32_fx( frameMeanDiffusenessEneWeight_fx, 0, CLDFB_NO_CHANNELS_MAX ); + + FOR( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ ) { gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */ + move16(); } - for ( bin = 0; bin < nBins; bin++ ) + /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */ + applyLowBitRateEQ = 0; + IF( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) { - float tmpMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain; - float CxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */ - float realizedOutputEne, targetOutputEne, missingOutputEne; - float CrEneL, CrEneR; /* Cr = residual decorrelated sound covariance matrix */ - float CrCrossRe, CrCrossIm; - float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* M = mixing matrix; Mdec = residual decorrelated signal mixing matrix */ - float prototypeMtx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { 1.0f, 0.05f }, { 0.05f, 1.0f } }; /* Prototype matrix determines a reference signal in mixing matrix determination */ - - CrEneL = 0.0f; - CrEneR = 0.0f; - - /* Formulate main processing matrix M */ - formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], - hDiracDecBin->ChCrossRe[bin], hDiracDecBin->ChCrossIm[bin], - hDiracDecBin->ChEneOut[0][bin], hDiracDecBin->ChEneOut[1][bin], - hDiracDecBin->ChCrossReOut[bin], hDiracDecBin->ChCrossImOut[bin], - prototypeMtx, Mre, Mim, -#ifdef IVAS_FLOAT_FIXED - fix16_to_float(hDiracDecBin->reqularizationFactor_fx,Q14) ); -#else - hDiracDecBin->reqularizationFactor ); -#endif - - /* Load estimated covariance matrix to the [2][2] matrix form */ - CxRe[0][0] = hDiracDecBin->ChEne[0][bin]; - CxRe[1][1] = hDiracDecBin->ChEne[1][bin]; - CxRe[1][0] = hDiracDecBin->ChCrossRe[bin]; - CxRe[0][1] = hDiracDecBin->ChCrossRe[bin]; - CxIm[0][0] = 0.0f; - CxIm[1][1] = 0.0f; - CxIm[1][0] = hDiracDecBin->ChCrossIm[bin]; - CxIm[0][1] = -hDiracDecBin->ChCrossIm[bin]; - - /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */ - matrixMul( Mre, Mim, CxRe, CxIm, tmpMtxRe, tmpMtxIm ); - matrixTransp2Mul( tmpMtxRe, tmpMtxIm, Mre, Mim, resultMtxRe, resultMtxIm ); - - /* When below the frequency limit where decorrelation is applied, we inject the decorrelated - * residual (or missing) signal component. The procedure is active when there are not enough independent - * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */ - if ( bin < max_band_decorr ) + applyLowBitRateEQ = 1; + IF( EQ_32( ivas_total_brate, IVAS_16k4 ) ) { - float decorrelationReductionFactor; - - /* Subtract the resulting covariance matrix from the target covariance matrix to determine - * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e., - * a residual covariance matrix. */ - CrEneL = max( 0.0f, hDiracDecBin->ChEneOut[0][bin] - resultMtxRe[0][0] ); - CrEneR = max( 0.0f, hDiracDecBin->ChEneOut[1][bin] - resultMtxRe[1][1] ); - CrCrossRe = hDiracDecBin->ChCrossReOut[bin] - resultMtxRe[1][0]; - CrCrossIm = hDiracDecBin->ChCrossImOut[bin] - resultMtxIm[1][0]; - - /* The amount of the decorrelated sound is further controlled based on the spatial metadata, - * by determining an energy-suppressed residual covariance matrix that is a control parameter - * that guides the processing of the decorrelated sound to a residual signal. - * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/ - if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) - { - decorrelationReductionFactor = 1.0f; - } - else if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) || ( ivas_format == MASA_FORMAT && nchan_transport == 1 ) ) - { - decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ) ); - } - else if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 1 ) + FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) { - decorrelationReductionFactor = 1.0f; + lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = L_add( L_shr( lowBitRateBinauralEQ_fx[bin], 1 ), ONE_IN_Q30 ); // Q31 } - else + } + ELSE + { + FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) { - decorrelationReductionFactor = fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ); + lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ_fx[bin]; // Q31 + move32(); } - CrEneL *= decorrelationReductionFactor; - CrEneR *= decorrelationReductionFactor; - CrCrossRe *= decorrelationReductionFactor; - CrCrossIm *= decorrelationReductionFactor; - - /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain - * the residual signal (that has the residual covariance matrix) */ - formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], - 0.0f, 0.0f, /* Decorrelated signal has ideally no cross-terms */ - CrEneL, CrEneR, - CrCrossRe, CrCrossIm, - prototypeMtx, MdecRe, MdecIm, 0.2f ); } - else + } + + /* Formulate input and target covariance matrices for this subframe */ + set32_fx( subFrameTotalEne_fx, 0, CLDFB_NO_CHANNELS_MAX ); + dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + move16(); + + /* Calculate input covariance matrix */ + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + { + FOR( bin = 0; bin < nBins; bin++ ) { - for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], + L_add( L_shr( Mpy_32_32( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ), 1 ), L_shr( Mpy_32_32( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ), 1 ) ), sub( 63, shl( q, 1 ) ), &hDiracDecBin->ChCrossRe_e[bin] ); + hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], + L_sub( L_shr( Mpy_32_32( inRe_fx[0][slot][bin], inIm_fx[1][slot][bin] ), 1 ), L_shr( Mpy_32_32( inIm_fx[0][slot][bin], inRe_fx[1][slot][bin] ), 1 ) ), sub( 63, shl( q, 1 ) ), &hDiracDecBin->ChCrossIm_e[bin] ); + + inRe_fx[0][slot][bin] = L_shr( inRe_fx[0][slot][bin], 2 ); + inRe_fx[1][slot][bin] = L_shr( inRe_fx[1][slot][bin], 2 ); + inIm_fx[0][slot][bin] = L_shr( inIm_fx[0][slot][bin], 2 ); + inIm_fx[1][slot][bin] = L_shr( inIm_fx[1][slot][bin], 2 ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - set_zero( MdecRe[chA], BINAURAL_CHANNELS ); - set_zero( MdecIm[chA], BINAURAL_CHANNELS ); + Word32 instEne_fx; + + instEne_fx = Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ); // 2q - 31 + instEne_fx = L_add( instEne_fx, Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // 2q - 31 + hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], instEne_fx, sub( 66, shl( q, 1 ) ), &hDiracDecBin->ChEne_e[ch][bin] ); + subFrameTotalEne_fx[bin] = L_add( subFrameTotalEne_fx[bin], instEne_fx ); // 2q - 31 } } + } - /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */ - realizedOutputEne = CrEneL + CrEneR + resultMtxRe[0][0] + resultMtxRe[1][1]; - targetOutputEne = hDiracDecBin->ChEneOut[0][bin] + hDiracDecBin->ChEneOut[1][bin]; - missingOutputEne = fmaxf( 0.0f, targetOutputEne - realizedOutputEne ); + q = sub( q, 2 ); + q_subFrameTotalEne = sub( shl( q, 1 ), 31 ); - gain = sqrtf( ( resultMtxRe[0][0] + resultMtxRe[1][1] + missingOutputEne ) / - fmaxf( 1e-12f, resultMtxRe[0][0] + resultMtxRe[1][1] ) ); - gain = fminf( 4.0f, gain ); + /* Apply EQ at low bit rates */ + IF( NE_16( applyLowBitRateEQ, 0 ) ) + { + Word16 lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1; - for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + FOR( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ ) { - for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) - { - Mre[chA][chB] *= gain; - Mim[chA][chB] *= gain; - } + subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[bin] ); // 2q -31 + } + FOR( ; bin < nBins; bin++ ) + { + subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[lastEqBin] ); // 2q -31 } + } - /* Store processing matrices */ - for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + IF( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 2 ) + { + Word32 tempRe, tempIm; + Word32 subFrameSumEne_fx[CLDFB_NO_CHANNELS_MAX]; + + scale_sig32( subFrameTotalEne_fx, nBins, -2 ); + q_subFrameTotalEne = sub( q_subFrameTotalEne, 1 ); + + set32_fx( subFrameSumEne_fx, 0, CLDFB_NO_CHANNELS_MAX ); + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) { - for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) + FOR( bin = 0; bin < nBins; bin++ ) { - hDiracDecBin->processMtxRePrev[chA][chB][bin] = hDiracDecBin->processMtxRe[chA][chB][bin]; - hDiracDecBin->processMtxImPrev[chA][chB][bin] = hDiracDecBin->processMtxIm[chA][chB][bin]; - hDiracDecBin->processMtxDecRePrev[chA][chB][bin] = hDiracDecBin->processMtxDecRe[chA][chB][bin]; - hDiracDecBin->processMtxDecImPrev[chA][chB][bin] = hDiracDecBin->processMtxDecIm[chA][chB][bin]; - - hDiracDecBin->processMtxRe[chA][chB][bin] = Mre[chA][chB]; - hDiracDecBin->processMtxIm[chA][chB][bin] = Mim[chA][chB]; - hDiracDecBin->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB]; - hDiracDecBin->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB]; + tempRe = L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ); // q + tempIm = L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ); // q + subFrameSumEne_fx[bin] = L_add( subFrameSumEne_fx[bin], L_add( L_shr( Mpy_32_32( tempRe, tempRe ), 1 ), L_shr( Mpy_32_32( tempIm, tempIm ), 1 ) ) ); // 2q -31 } } - - if ( separateCenterChannelRendering ) + FOR( bin = 0; bin < nBins; bin++ ) { - /* The rendering of the separate center channel in masa + mono mode. - * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */ - float lRealp, lImagp, rRealp, rImagp; - float gainFactor; - int16_t aziDeg = 0; - int16_t eleDeg = 0; - uint8_t instantChange = 0; + subFrameTotalEne_fx[bin] = L_max( subFrameTotalEne_fx[bin], subFrameSumEne_fx[bin] ); // 2q -31 + } + } - if ( ivas_format == MASA_ISM_FORMAT ) + /* Determine target covariance matrix containing target binaural properties */ + FOR( bin = 0; bin < nBins; bin++ ) + { + Word32 diffuseness_fx = ONE_IN_Q30; /* ratio1 and ratio2 are subtracted from diffuseness further below */ + Word32 diffusenessValForDecorrelationReduction_fx = ONE_IN_Q30; + Word32 diffEneValForDecorrelationReduction_fx; + Word16 q_diffEneValForDecorrelationReduction; + Word16 surCoh_fx = 0, spreadCoh_fx = 0; /* Default values if spreadSurroundCoherenceApplied == false */ + Word32 diffEne_fx, dirEne_fx, meanEnePerCh_fx; + Word16 q_meanEnePerCh; + Word16 q_diffEne, q_dirEne; + Word16 dirIndex; + + /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f. + * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the + * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match + * the early spectrum of the BRIR data, using the spectral correction data in + * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */ + meanEnePerCh_fx = Mpy_32_32( hDiracDecBin->earlyPartEneCorrection_fx[bin], subFrameTotalEne_fx[bin] ); // Q( 2q - 31 ) + q_meanEnePerCh = sub(add(q_earlyPartEneCorrection, q_subFrameTotalEne), 30); + /* Determine direct part target covariance matrix (for 1 or 2 directions) */ + FOR( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ ) + { + Word16 aziDeg, eleDeg; + Word32 lRealp_fx, lImagp_fx, rRealp_fx, rImagp_fx; + Word32 lRealpTmp_fx, lImagpTmp_fx, rRealpTmp_fx, rImagpTmp_fx; + Word32 hrtfEne_fx[BINAURAL_CHANNELS], hrtfCrossRe_fx, hrtfCrossIm_fx, ratio_fx; + UWord8 isIsmDirection = 0; + + IF( EQ_16( dirIndex, 0 ) ) /* For first of the two simultaneous directions */ { - gainFactor = 0.7943f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] ); + aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin]; + move16(); + eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin]; + move16(); + ratio_fx = hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin]; + move32(); + spreadCoh_fx = hSpatParamRendCom->spreadCoherence_fx[dirac_read_idx][bin]; + move16(); + gainCacheBaseIndex = 0; + move16(); } - else + ELSE IF( ivas_format != MASA_ISM_FORMAT || ( ivas_format == MASA_ISM_FORMAT && LT_16( dirIndex, hSpatParamRendCom->numParametricDirections ) ) ) /* For second of the two simultaneous directions */ { - gainFactor = 0.8414f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] ); + IF( LT_32( ( ratio_fx = hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin] ), 10737418 /* 0.01 in Q30 */ ) ) + { + /* This touches only MASA path where second direction always has smaller ratio and + * for non-2dir it is zero. As the whole direction contribution is multiplied with + * the ratio, a very small ratio does not contribute any energy to output. Thus, + * it is better to save complexity. */ + continue; + } + aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin]; + move16(); + eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin]; + move16(); + spreadCoh_fx = hSpatParamRendCom->spreadCoherence2_fx[dirac_read_idx][bin]; + move16(); + gainCacheBaseIndex = 3; + move16(); } - - for ( chB = 0; chB < nchanSeparateChannels; chB++ ) + ELSE /* For object directions of MASA_ISM_FORMAT */ { - if ( ivas_format == MASA_ISM_FORMAT ) + isIsmDirection = 1; + move16(); + UWord16 ismDirIndex; + ismDirIndex = sub(dirIndex, hSpatParamRendCom->numParametricDirections); + assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" ); + IF( hMasaIsmData->ism_is_edited[ismDirIndex] ) { - if ( ism_mode == ISM_MASA_MODE_DISC ) - { - aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx]; - eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx]; - } - else - { - aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx]; - eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx]; - instantChange = 1; - } + aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex]; + move16(); + eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex]; + move16(); + } + ELSE + { + aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx]; + move16(); + eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx]; + move16(); } + ratio_fx = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin]; + move32(); + spreadCoh_fx = 0; + move16(); + gainCacheBaseIndex = add( 6, ismDirIndex ); + } - for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + diffuseness_fx = L_sub( diffuseness_fx, ratio_fx ); /* diffuseness = 1 - ratio1 - ratio2 */ + + IF( LT_32( diffuseness_fx, 0 ) ) + { + diffuseness_fx = 0; + move32(); + } + IF( isIsmDirection ) + { + /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */ + diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, L_shr( ratio_fx, 1 ) ); + } + ELSE + { + diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, ratio_fx ); + } + + IF( separateCenterChannelRendering ) + { + /* In masa + mono rendering mode, the center directions originate from phantom sources, so the + * spread coherence is increased */ + Word16 azi_scaled, ele_scaled; + Word32 doaVectorX_fx, num, den; + Word16 e = 0, spatialAngleDeg_fx, altSpreadCoh_fx; + + azi_scaled = i_mult( aziDeg, 91 ); + ele_scaled = i_mult( eleDeg, 91 ); + doaVectorX_fx = L_mult( getCosWord16R2( azi_scaled ), getCosWord16R2( ele_scaled ) ); + num = Sqrt32( L_sub( ONE_IN_Q31, Mpy_32_32( doaVectorX_fx, doaVectorX_fx ) ), &e ); + den = doaVectorX_fx; + spatialAngleDeg_fx = BASOP_util_atan2( num, den, e ); // Q13 + Word16 numr, num_e = 0, denr, den_e; + num_e = norm_s( spatialAngleDeg_fx ) - 1; + numr = shl( spatialAngleDeg_fx, num_e ); + denr = 17157; + move16(); + den_e = 4; + move16(); + altSpreadCoh_fx = sub( 32767, shl_sat( div_s( numr, denr ), sub( den_e, num_e ) ) ); // 4289 = pi/6 in Q13 + spreadCoh_fx = s_max( spreadCoh_fx, altSpreadCoh_fx ); + } + + getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex], isHeadtracked ); + + Word16 q_lr = Q28; + move16(); + IF( hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + { + /* Synthesizing spread coherence is not needed for stereo loudspeaker output, + * as directional sound is reproduced with two loudspeakers in any case */ + spreadCoh_fx = 0; + move32(); + } + + IF( spreadCoh_fx > 0 ) + { + Word32 centerMul_fx, sidesMul_fx; + Word32 hrtfEneCenter_fx, hrtfEneSides_fx, hrtfEneRealized_fx; + Word16 eneCorrectionFactor_fx, eneCorrectionFactor_e; + Word16 w1_fx, w2_fx, w3_fx, eq_fx; + + hrtfEneCenter_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), // Q25 + L_add( Mpy_32_32( lImagp_fx, lImagp_fx ), // Q25 + L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), // Q25 + Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q25 + + /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing. + * The following formulas determine the gains for these sources. + * spreadCoh = 0: Only panning + * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi) + * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */ + IF( LT_16( spreadCoh_fx, 16384 ) ) { - hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin]; - hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin]; + /* 0.0f < spreadCoh < 0.5f */ + sidesMul_fx = L_mult0( spreadCoh_fx, 9459 ); /* 2*sqrt(1/3) in Q13 = 9459 */ // Q28 + centerMul_fx = L_add( L_sub( ONE_IN_Q28, L_shl( spreadCoh_fx, 14 ) ), sidesMul_fx ); // Q28 + } + ELSE + { + /* 0.5f <= spreadCoh < 1.0f */ + // centerMul = 2.0f - ( 2.0f * spreadCoh ); + centerMul_fx = L_shl( sub( 32767, spreadCoh_fx ), 14 ); // Q28 + sidesMul_fx = Isqrt( L_add( L_shr( centerMul_fx, 22 ), L_shl( 2, Q6 ) ) ); // Q28 + centerMul_fx = L_shl( Mpy_32_32( centerMul_fx, sidesMul_fx ), 3 ); // Q28 } - getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked ); + /* Apply the gain for the center source of the three coherent sources */ + lRealp_fx = Mpy_32_32( lRealp_fx, centerMul_fx ); // Q25 + lImagp_fx = Mpy_32_32( lImagp_fx, centerMul_fx ); // Q25 + rRealp_fx = Mpy_32_32( rRealp_fx, centerMul_fx ); // Q25 + rImagp_fx = Mpy_32_32( rImagp_fx, centerMul_fx ); // Q25 - hDiracDecBin->processMtxRe[0][chB + 2][bin] = lRealp * gainFactor; - hDiracDecBin->processMtxIm[0][chB + 2][bin] = lImagp * gainFactor; - hDiracDecBin->processMtxRe[1][chB + 2][bin] = rRealp * gainFactor; - hDiracDecBin->processMtxIm[1][chB + 2][bin] = rImagp * gainFactor; + /* Apply the gain for the left source of the three coherent sources */ + getDirectPartGains_fx( bin, aziDeg + 30, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 1], isHeadtracked ); - if ( instantChange ) + hrtfEneSides_fx = L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ), // Q25 + L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ), // Q25 + L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ), // Q25 + Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ); // Q25 + lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) ); // Q25 + lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) ); // Q25 + rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) ); // Q25 + rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) ); // Q25 + + /* Apply the gain for the right source of the three coherent sources. + * -30 degrees to 330 wrapping due to internal functions. */ + + getDirectPartGains_fx( bin, aziDeg + 330, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 2], isHeadtracked ); + + hrtfEneSides_fx = L_add( hrtfEneSides_fx, + L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ), // Q25 + L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ), // Q25 + L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ), // Q25 + Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ) ); // Q25 + lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) ); // Q25 + lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) ); // Q25 + rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) ); // Q25 + rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) ); // Q25 + + /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */ + hrtfEneRealized_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), // Q19 + L_add( Mpy_32_32( lImagp_fx, lImagp_fx ), // Q19 + L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), // Q19 + Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q19 + + eneCorrectionFactor_fx = BASOP_Util_Divide3232_Scale( L_add( Mpy_32_32( hrtfEneSides_fx, Mpy_32_32( sidesMul_fx, sidesMul_fx ) ), + Mpy_32_32( hrtfEneCenter_fx, Mpy_32_32( centerMul_fx, centerMul_fx ) ) ), + L_max( 1, hrtfEneRealized_fx ), &eneCorrectionFactor_e ); + + /* Weighting factors to determine appropriate target spectrum for spread coherent sound */ + IF( LT_16( spreadCoh_fx, 16384 ) ) { - for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + w1_fx = sub( 32767, shl( spreadCoh_fx, 1 ) ); + w2_fx = shl( spreadCoh_fx, 1 ); + w3_fx = 0; + move16(); + } + ELSE + { + w1_fx = 0; + move16(); + w2_fx = shl( sub( 32767, spreadCoh_fx ), 1 ); + w3_fx = shl( sub( spreadCoh_fx, 16384 ), 1 ); + } + + IF( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) ) + { + idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + + /* Apply the target spectrum to the eneCorrectionFactor */ + IF( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */ { - hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin]; - hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin]; + eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 8192 ), shr( mult_r( add( w2_fx, w3_fx ), spreadCohEne1_fx[idx] ), 1 ) ) ); + eneCorrectionFactor_e = add( eneCorrectionFactor_e, 2 ); } + ELSE + { + eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 4096 ), add( shr( mult_r( w2_fx, spreadCohEne05_fx[idx] ), 1 ), shr( mult_r( w3_fx, spreadCohEne1_fx[idx] ), 2 ) ) ) ); + eneCorrectionFactor_e = add( eneCorrectionFactor_e, 3 ); + } + } + + /* Equalize the spread coherent combined HRTFs */ + Word16 tmp, tmp_e; + tmp_e = eneCorrectionFactor_e; + tmp = Sqrt16( eneCorrectionFactor_fx, &tmp_e ); + IF( shr( tmp, sub( 15, tmp_e ) ) >= 4 ) + { + eq_fx = 32767; // Q13 + move16(); } + ELSE + { + eq_fx = shl( tmp, sub( tmp_e, 2 ) ); // Q13 + } + + lRealp_fx = Mpy_32_16_1( lRealp_fx, eq_fx ); // Q23 + lImagp_fx = Mpy_32_16_1( lImagp_fx, eq_fx ); // Q23 + rRealp_fx = Mpy_32_16_1( rRealp_fx, eq_fx ); // Q23 + rImagp_fx = Mpy_32_16_1( rImagp_fx, eq_fx ); // Q23 + q_lr = Q23; + move16(); } - } - } - return; -} + hrtfEne_fx[0] = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), Mpy_32_32( lImagp_fx, lImagp_fx ) ); // Q( 2*q_lr - 31 ) + hrtfEne_fx[1] = L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), Mpy_32_32( rImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 ) + hrtfCrossRe_fx = L_add( Mpy_32_32( lRealp_fx, rRealp_fx ), Mpy_32_32( lImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 ) + hrtfCrossIm_fx = L_add( Mpy_32_32( -lImagp_fx, rRealp_fx ), Mpy_32_32( lRealp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 ) + /* Add direct part (1 or 2) covariance matrix */ + dirEne_fx = Mpy_32_32( ratio_fx, meanEnePerCh_fx ); // Q(q_meanEnePerCh - 1) + shift = norm_l( dirEne_fx ); + dirEne_fx = L_shl( dirEne_fx, shift ); + q_dirEne = add( sub( q_meanEnePerCh, 1 ), shift ); -#ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_binaural_process_output_fx( - DIRAC_DEC_BIN_HANDLE hDiracDecBin, - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, - HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], - Word32 *output_fx[], - Word16 *q_out, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - const Word16 q_input, - const Word16 max_band_decorr, - const Word16 numInChannels, - const Word16 processReverb, - const Word16 subframe, - const Word16 q_mat) -{ - Word16 slot, bin, chA, chB; - Word16 nBins; - Word16 offsetSamples; - Word16 nSlots; + hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[0] ), sub( 31, q_dirEne + shl( q_lr, 1 ) - 62 ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Dir ene part*/ + hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[1] ), sub( 31, q_dirEne + shl( q_lr, 1 ) - 62 ), &hDiracDecBin->ChEneOut_e[1][bin] ); + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossRe_fx ), sub( 31, q_dirEne + shl( q_lr, 1 ) - 62 ), &hDiracDecBin->ChCrossReOut_e[bin] ); /* Dir cross re */ + hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossIm_fx ), sub( 31, q_dirEne + shl( q_lr, 1 ) - 62 ), &hDiracDecBin->ChCrossImOut_e[bin] ); /* Dir cross im */ + } - nBins = hSpatParamRendCom->num_freq_bands; - offsetSamples = 0; - nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + /* Add diffuse / ambient part covariance matrix */ + diffuseness_fx = L_max( 0, diffuseness_fx ); // Q30 + diffEne_fx = Mpy_32_32( diffuseness_fx, meanEnePerCh_fx ); // Q(2q - 32) + shift = norm_l( diffEne_fx ); + diffEne_fx = L_shl( diffEne_fx, shift ); + q_diffEne = add( shift, sub( q_meanEnePerCh, 1 ) ); - Word32 decSlotRe_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - Word32 outSlotRe_fx[CLDFB_NO_CHANNELS_MAX], outSlotIm_fx[CLDFB_NO_CHANNELS_MAX]; - Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - Word16 q_inp[6][CLDFB_SLOTS_PER_SUBFRAME]; - Word16 interpVal_fx; - Word32 *decSlotRePointer_fx; - Word32 *decSlotImPointer_fx; - Word16 q_inp_mix, q_reverb = 31; + surCoh_fx = hSpatParamRendCom->surroundingCoherence_fx[dirac_read_idx][bin]; // Q15 + move16(); + diffusenessValForDecorrelationReduction_fx = L_max( 0, diffusenessValForDecorrelationReduction_fx ); // Q30 + diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffusenessValForDecorrelationReduction_fx, meanEnePerCh_fx ); // Q(2q - 32) + q_diffEneValForDecorrelationReduction = sub( shl( q, 1 ), 32 ); - IF( processReverb ) - { - /* Process second / room effect part of binaural output when needed */ - ivas_binaural_reverb_processSubframe_fx( hDiracDecBin->hReverb, numInChannels, nSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx ); - } + IF( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) ) + { + IF( !hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + { + Word32 spectrumModVal; - // scaling input and reverb to same q// - // input scaling is to maintain precision in ivas_dirac_dec_decorrelate_slot fn// - Word16 shift = s_min( L_norm_arr( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length ), L_norm_arr( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length ) ); - q_inp_mix = 31; - FOR( Word16 i = 0; i < 6; i++ ) - { - FOR( Word16 j = 0; j < nSlots; j++ ) + idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */ + spectrumModVal = L_add( L_sub( ONE_IN_Q28, L_shl( surCoh_fx, 14 ) ), L_mult( surCoh_fx, surCohEne_fx[idx] ) ); // Q29 + diffEne_fx = Mpy_32_32( diffEne_fx, spectrumModVal ); // Q-2 + q_diffEne = sub( q_diffEne, 2 ); + /* Modify also the value for decorrelation reduction */ + diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffEneValForDecorrelationReduction_fx, spectrumModVal ); // Q-2 + q_diffEneValForDecorrelationReduction = sub( q_diffEneValForDecorrelationReduction, 2 ); + } + } + hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Diff ene part*/ + hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[1][bin] ); + + IF( hDiracDecBin->renderStereoOutputInsteadOfBinaural ) { - q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); - IF( ( processReverb ) && ( i < 2 ) ) + /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */ + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_16_1( diffEne_fx, surCoh_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] ); + } + ELSE /* When rendering binaural, ambience has frequency dependent ICC. */ + { + IF( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && LT_16( bin, BINAURAL_COHERENCE_DIFFERENCE_BINS ) ) { - q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) ); - q_inp[i][j] = s_min( q_reverb, q_inp[i][j] ); + Word32 diffuseFieldCoherence_fx; + diffuseFieldCoherence_fx = L_add( L_add( Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioX_fx[bin], hDiracDecBin->diffuseFieldCoherenceX_fx[bin] ), Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioY_fx[bin], hDiracDecBin->diffuseFieldCoherenceY_fx[bin] ) ), Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioZ_fx[bin], hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] ) ); + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( L_add( Mpy_32_16_1( diffuseFieldCoherence_fx, sub( 32767, surCoh_fx ) ), L_shl( surCoh_fx, 16 ) ), diffEne_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] ); + } + ELSE + { + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( L_add( Mpy_32_16_1( hDiracDecBin->diffuseFieldCoherence_fx[bin], sub( 32767, surCoh_fx ) ), L_shl( surCoh_fx, 16 ) ), diffEne_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] ); } - q_inp_mix = s_min( q_inp[i][j], q_inp_mix ); } + + /* Store parameters for formulating average diffuseness over frame */ + hDiracDecBin->frameMeanDiffuseness_fx[bin] = L_add( hDiracDecBin->frameMeanDiffuseness_fx[bin], L_shl( diffEneValForDecorrelationReduction_fx, sub( q_meanEnePerCh, q_diffEneValForDecorrelationReduction ) ) ); // Q(q_meanEnePerCh) + frameMeanDiffusenessEneWeight_fx[bin] = L_add( frameMeanDiffusenessEneWeight_fx[bin], meanEnePerCh_fx ); } - - q_inp_mix = sub( q_inp_mix, 3 ); // gaurded bits// - Word16 cldfb_state_shift = sub( add( add( q_inp_mix, q_mat ), sub( q_input, 16 ) ), cldfbSynDec[0]->Q_cldfb_state ); - IF( GT_16( cldfb_state_shift, shift ) ) + /* Formulate average diffuseness over frame */ + Word16 e; + FOR( bin = 0; bin < nBins; bin++ ) { - q_inp_mix = q_inp_mix + shift - cldfb_state_shift; - cldfb_state_shift = shift; + e = 0; + move16(); + hDiracDecBin->frameMeanDiffuseness_fx[bin] = BASOP_Util_Divide3232_Scale( hDiracDecBin->frameMeanDiffuseness_fx[bin], L_max( EPSILLON_FX, frameMeanDiffusenessEneWeight_fx[bin] ), &e ); + hDiracDecBin->frameMeanDiffuseness_fx[bin] = L_shl( hDiracDecBin->frameMeanDiffuseness_fx[bin], 14 + e ); // Q29 } - FOR( Word16 i = 0; i < 6; i++ ) + /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */ + IF( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) { - FOR( Word16 j = 0; j < nSlots; j++ ) - { - - scale_sig32(inRe_fx[i][j], nBins, q_inp_mix); - scale_sig32(inIm_fx[i][j], nBins, q_inp_mix); - IF( processReverb && ( i < 2 ) ) - { - scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); - scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); - } - } + IIReneLimiterFactor_fx = L_add( L_shl( 16, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26 + } + ELSE + { + IIReneLimiterFactor_fx = L_add( L_shl( 8, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26 } - // scaling cldfb states to q_result-1// - scale_sig32( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length, cldfb_state_shift ); - scale_sig32( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length, cldfb_state_shift ); - - q_inp_mix = add( q_inp_mix, q_input ); - - interpVal_fx = 0; - Word16 q_result = sub( add( q_inp_mix, q_mat ), 15 ); // setting it prior// - cldfbSynDec[0]->Q_cldfb_state = sub( q_result, 1 ); - cldfbSynDec[1]->Q_cldfb_state = sub( q_result, 1 ); - - FOR( slot = 0; slot < nSlots; slot++ ) + FOR( bin = 0; bin < nBins; bin++ ) { - IF( NE_16( slot, sub( nSlots, 1 ) ) ) + Word32 IIReneLimiter_fx; + + /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that + * the energy history (IIR) must not be more than double of the current frame energy. This provides more + * robust performance at energy offsets when compared to typical IIR averaging. */ + Word16 num_e, den_e; + Word32 num, den; + num = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_fx[1][bin], hDiracDecBin->ChEne_e[1][bin], &num_e ); + num = Mpy_32_32( num, IIReneLimiterFactor_fx ); + den_e = 0; + move16(); + den = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEnePrev_fx[0][bin], hDiracDecBin->ChEnePrev_e[0][bin], hDiracDecBin->ChEnePrev_fx[1][bin], hDiracDecBin->ChEnePrev_e[1][bin], &den_e ); + den = L_max( 1, den ); + IIReneLimiter_fx = BASOP_Util_Divide3232_Scale_cadence( num, den, &e ); + e = add( sub( num_e, den_e ), add( 5, e ) ); + IF( L_shr_sat( IIReneLimiter_fx, 31 - e ) > 0 ) { - interpVal_fx = add( interpVal_fx, slot_fx[nSlots - 1] ); + IIReneLimiter_fx = ONE_IN_Q31; } ELSE { - interpVal_fx = 32767; - } - IF( !hDiracDecBin->useTdDecorr && (GT_16(max_band_decorr , 0)) ) - { - ivas_dirac_dec_decorrelate_slot_fx( hDiracDecBin, nBins, slot, inRe_fx, inIm_fx, q_inp_mix, decSlotRe_fx, decSlotIm_fx ); + IIReneLimiter_fx = L_shl( IIReneLimiter_fx, e ); } - FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) - { - Word32 *outSlotRePr_fx, *outSlotImPr_fx; /* Pointers needed for function call compatibility */ - - set_zero_fx( outSlotRe_fx, CLDFB_NO_CHANNELS_MAX ); - set_zero_fx( outSlotIm_fx, CLDFB_NO_CHANNELS_MAX ); - - /* Processing of the first / HRTF part of the binaural output. */ - FOR( chB = 0; chB < numInChannels; chB++ ) - { - IF( LT_16( chB, BINAURAL_CHANNELS ) ) - { - /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs. - * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this - * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the - * pointers to buffers. */ - IF( hDiracDecBin->useTdDecorr ) - { - decSlotRePointer_fx = inRe_fx[chB + 2][slot]; - decSlotImPointer_fx = inIm_fx[chB + 2][slot]; - } - ELSE - { - decSlotRePointer_fx = decSlotRe_fx[chB]; - decSlotImPointer_fx = decSlotIm_fx[chB]; - } - } - ELSE - { - decSlotRePointer_fx = NULL; /* below these pointers are used only for chB < 2 */ - decSlotImPointer_fx = NULL; - } - - - FOR( bin = 0; bin < nBins; bin++ ) - { - Word16 gain; - - /* Mixing using the formulated processing matrix M */ - gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxRe_fx[chA][chB][bin] ) ); // Q11 - - outSlotRe_fx[bin] = L_add( outSlotRe_fx[bin], Mpy_32_16_1( inRe_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result - outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( inIm_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result - - gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxIm_fx[chA][chB][bin] ) ); // Q11 - - // interpVal * hDiracDecBin->processMtxIm[chA][chB][bin]; - outSlotRe_fx[bin] = L_sub( outSlotRe_fx[bin], Mpy_32_16_1( inIm_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result - outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( inRe_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result - - - /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */ - IF( bin < max_band_decorr && chB < 2 ) - { - gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] ) ); - // interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin]; - outSlotRe_fx[bin] = L_add( outSlotRe_fx[bin], Mpy_32_16_1( decSlotRePointer_fx[bin], gain ) ); // q_inp_mix-4//q_result - outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( decSlotImPointer_fx[bin], gain ) ); // q_inp_mix-4//q_result - - - gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] ) ); - outSlotRe_fx[bin] = L_sub( outSlotRe_fx[bin], Mpy_32_16_1( decSlotImPointer_fx[bin], gain ) ); // q_inp_mix-4//q_result - outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( decSlotRePointer_fx[bin], gain ) ); // q_inp_mix-4//q_result - } - } - } + hDiracDecBin->ChCrossRe_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossRe_fx[bin], qualityBasedSmFactor_fx ); + hDiracDecBin->ChCrossIm_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossIm_fx[bin], qualityBasedSmFactor_fx ); + hDiracDecBin->ChCrossReOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossReOut_fx[bin], qualityBasedSmFactor_fx ); + hDiracDecBin->ChCrossImOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossImOut_fx[bin], qualityBasedSmFactor_fx ); + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEne_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEne_fx[ch][bin], qualityBasedSmFactor_fx ); + hDiracDecBin->ChEneOut_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEneOut_fx[ch][bin], qualityBasedSmFactor_fx ); + } - IF( processReverb ) - { - /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */ - v_add_fx( outSlotRe_fx, reverbRe_fx[chA][slot], outSlotRe_fx, CLDFB_NO_CHANNELS_MAX ); - v_add_fx( outSlotIm_fx, reverbIm_fx[chA][slot], outSlotIm_fx, CLDFB_NO_CHANNELS_MAX ); - } + hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], Mpy_32_32( hDiracDecBin->ChCrossRePrev_fx[bin], IIReneLimiter_fx ), hDiracDecBin->ChCrossRePrev_e[bin], &hDiracDecBin->ChCrossRe_e[bin] ); + hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImPrev_fx[bin], IIReneLimiter_fx ), hDiracDecBin->ChCrossImPrev_e[bin], &hDiracDecBin->ChCrossIm_e[bin] ); + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossReOutPrev_fx[bin], IIReneLimiter_fx ), hDiracDecBin->ChCrossReOutPrev_e[bin], &hDiracDecBin->ChCrossReOut_e[bin] ); + hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImOutPrev_fx[bin], IIReneLimiter_fx ), hDiracDecBin->ChCrossImOutPrev_e[bin], &hDiracDecBin->ChCrossImOut_e[bin] ); + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEnePrev_fx[ch][bin], IIReneLimiter_fx ), hDiracDecBin->ChEnePrev_e[ch][bin], &hDiracDecBin->ChEne_e[ch][bin] ); + hDiracDecBin->ChEneOut_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[ch][bin], hDiracDecBin->ChEneOut_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEneOutPrev_fx[ch][bin], IIReneLimiter_fx ), hDiracDecBin->ChEneOutPrev_e[ch][bin], &hDiracDecBin->ChEneOut_e[ch][bin] ); + } - outSlotRePr_fx = &( outSlotRe_fx[0] ); - outSlotImPr_fx = &( outSlotIm_fx[0] ); + /* Store energy values and coefficients for next round */ + hDiracDecBin->ChCrossRePrev_fx[bin] = hDiracDecBin->ChCrossRe_fx[bin]; + move32(); + hDiracDecBin->ChCrossImPrev_fx[bin] = hDiracDecBin->ChCrossIm_fx[bin]; + move32(); + hDiracDecBin->ChCrossReOutPrev_fx[bin] = hDiracDecBin->ChCrossReOut_fx[bin]; + move32(); + hDiracDecBin->ChCrossImOutPrev_fx[bin] = hDiracDecBin->ChCrossImOut_fx[bin]; + move32(); + hDiracDecBin->ChCrossRePrev_e[bin] = hDiracDecBin->ChCrossRe_e[bin]; + move16(); + hDiracDecBin->ChCrossImPrev_e[bin] = hDiracDecBin->ChCrossIm_e[bin]; + move16(); + hDiracDecBin->ChCrossReOutPrev_e[bin] = hDiracDecBin->ChCrossReOut_e[bin]; + move16(); + hDiracDecBin->ChCrossImOutPrev_e[bin] = hDiracDecBin->ChCrossImOut_e[bin]; + move16(); - cldfbSynthesis_ivas_fx( &outSlotRePr_fx, &outSlotImPr_fx, &( output_fx[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); - cldfbSynDec[chA]->Q_cldfb_state = sub( q_result, 1 ); + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin]; + move32(); + hDiracDecBin->ChEneOutPrev_fx[ch][bin] = hDiracDecBin->ChEneOut_fx[ch][bin]; + move32(); + hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin]; + move16(); + hDiracDecBin->ChEneOutPrev_e[ch][bin] = hDiracDecBin->ChEneOut_e[ch][bin]; + move16(); } } - *q_out = sub( q_result, 1 ); + return; } +#endif -#else -static void ivas_dirac_dec_binaural_process_output( +static void ivas_dirac_dec_binaural_determine_processing_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, - HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], - float *output_f[], - float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, - const int16_t numInChannels, - const int16_t processReverb, - const int16_t subframe ) + float Rmat[3][3], + const int16_t subframe, + const int16_t isHeadtracked, + const int16_t nchanSeparateChannels, + const MASA_ISM_DATA_HANDLE hMasaIsmData ) { - int16_t slot, bin, chA, chB; + int16_t chA, chB, bin; + int16_t separateCenterChannelRendering; int16_t nBins; - float outSlotRe[CLDFB_NO_CHANNELS_MAX], outSlotIm[CLDFB_NO_CHANNELS_MAX]; - float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; - float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float interpVal; - float *decSlotRePointer; - float *decSlotImPointer; - int16_t offsetSamples; - int16_t nSlots; + int16_t dirac_read_idx; + PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS]; + int16_t idx; + ISM_MODE ism_mode; + IVAS_FORMAT ivas_format; + MC_MODE mc_mode; + int32_t ivas_total_brate; + int16_t nchan_transport; - nBins = hSpatParamRendCom->num_freq_bands; - offsetSamples = 0; - nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + ivas_format = hConfig->ivas_format; + separateCenterChannelRendering = nchanSeparateChannels > 0; + mc_mode = hConfig->mc_mode; + ivas_total_brate = hConfig->ivas_total_brate; + nchan_transport = hConfig->nchan_transport; + nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ - if ( processReverb ) + ism_mode = hConfig->ism_mode; + + dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + + for ( idx = 0; idx < MAX_NUM_OBJECTS; idx++ ) { - /* Process second / room effect part of binaural output when needed */ - ivas_binaural_reverb_processSubframe( hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm ); + gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */ } - interpVal = 0.0f; - for ( slot = 0; slot < nSlots; slot++ ) + for ( bin = 0; bin < nBins; bin++ ) { - interpVal += 1.0f / (float) nSlots; - if ( !hDiracDecBin->useTdDecorr && max_band_decorr > 0 ) - { - ivas_dirac_dec_decorrelate_slot( hDiracDecBin, nBins, slot, inRe, inIm, decSlotRe, decSlotIm ); - } + float tmpMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain; + float CxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */ + float realizedOutputEne, targetOutputEne, missingOutputEne; + float CrEneL, CrEneR; /* Cr = residual decorrelated sound covariance matrix */ + float CrCrossRe, CrCrossIm; + float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* M = mixing matrix; Mdec = residual decorrelated signal mixing matrix */ + float prototypeMtx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { 1.0f, 0.05f }, { 0.05f, 1.0f } }; /* Prototype matrix determines a reference signal in mixing matrix determination */ - for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) - { - float *outSlotRePr, *outSlotImPr; /* Pointers needed for function call compatibility */ + CrEneL = 0.0f; + CrEneR = 0.0f; - set_zero( outSlotRe, CLDFB_NO_CHANNELS_MAX ); - set_zero( outSlotIm, CLDFB_NO_CHANNELS_MAX ); + /* Formulate main processing matrix M */ + formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], + hDiracDecBin->ChCrossRe[bin], hDiracDecBin->ChCrossIm[bin], + hDiracDecBin->ChEneOut[0][bin], hDiracDecBin->ChEneOut[1][bin], + hDiracDecBin->ChCrossReOut[bin], hDiracDecBin->ChCrossImOut[bin], + prototypeMtx, Mre, Mim, +#ifdef IVAS_FLOAT_FIXED + fix16_to_float( hDiracDecBin->reqularizationFactor_fx, Q14 ) ); +#else + hDiracDecBin->reqularizationFactor ); +#endif - /* Processing of the first / HRTF part of the binaural output. */ - for ( chB = 0; chB < numInChannels; chB++ ) - { - if ( chB < BINAURAL_CHANNELS ) - { - /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs. - * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this - * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the - * pointers to buffers. */ - if ( hDiracDecBin->useTdDecorr ) - { - decSlotRePointer = inRe[chB + 2][slot]; - decSlotImPointer = inIm[chB + 2][slot]; - } - else - { - decSlotRePointer = decSlotRe[chB]; - decSlotImPointer = decSlotIm[chB]; - } - } - else - { - decSlotRePointer = NULL; /* below these pointers are used only for chB < 2 */ - decSlotImPointer = NULL; - } + /* Load estimated covariance matrix to the [2][2] matrix form */ + CxRe[0][0] = hDiracDecBin->ChEne[0][bin]; + CxRe[1][1] = hDiracDecBin->ChEne[1][bin]; + CxRe[1][0] = hDiracDecBin->ChCrossRe[bin]; + CxRe[0][1] = hDiracDecBin->ChCrossRe[bin]; + CxIm[0][0] = 0.0f; + CxIm[1][1] = 0.0f; + CxIm[1][0] = hDiracDecBin->ChCrossIm[bin]; + CxIm[0][1] = -hDiracDecBin->ChCrossIm[bin]; + /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */ + matrixMul( Mre, Mim, CxRe, CxIm, tmpMtxRe, tmpMtxIm ); + matrixTransp2Mul( tmpMtxRe, tmpMtxIm, Mre, Mim, resultMtxRe, resultMtxIm ); - for ( bin = 0; bin < nBins; bin++ ) - { - float gain; + /* When below the frequency limit where decorrelation is applied, we inject the decorrelated + * residual (or missing) signal component. The procedure is active when there are not enough independent + * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */ + if ( bin < max_band_decorr ) + { + float decorrelationReductionFactor; - /* Mixing using the formulated processing matrix M */ - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxRePrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxRe[chA][chB][bin]; - outSlotRe[bin] += gain * inRe[chB][slot][bin]; - outSlotIm[bin] += gain * inIm[chB][slot][bin]; + /* Subtract the resulting covariance matrix from the target covariance matrix to determine + * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e., + * a residual covariance matrix. */ + CrEneL = max( 0.0f, hDiracDecBin->ChEneOut[0][bin] - resultMtxRe[0][0] ); + CrEneR = max( 0.0f, hDiracDecBin->ChEneOut[1][bin] - resultMtxRe[1][1] ); + CrCrossRe = hDiracDecBin->ChCrossReOut[bin] - resultMtxRe[1][0]; + CrCrossIm = hDiracDecBin->ChCrossImOut[bin] - resultMtxIm[1][0]; - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxImPrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxIm[chA][chB][bin]; - outSlotRe[bin] -= gain * inIm[chB][slot][bin]; - outSlotIm[bin] += gain * inRe[chB][slot][bin]; + /* The amount of the decorrelated sound is further controlled based on the spatial metadata, + * by determining an energy-suppressed residual covariance matrix that is a control parameter + * that guides the processing of the decorrelated sound to a residual signal. + * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/ + if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE ) + { + decorrelationReductionFactor = 1.0f; + } + else if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) || ( ivas_format == MASA_FORMAT && nchan_transport == 1 ) ) + { + decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ) ); + } + else if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 1 ) + { + decorrelationReductionFactor = 1.0f; + } + else + { + decorrelationReductionFactor = fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ); + } + CrEneL *= decorrelationReductionFactor; + CrEneR *= decorrelationReductionFactor; + CrCrossRe *= decorrelationReductionFactor; + CrCrossIm *= decorrelationReductionFactor; - /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */ - if ( bin < max_band_decorr && chB < 2 ) - { - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecRePrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin]; - outSlotRe[bin] += gain * decSlotRePointer[bin]; - outSlotIm[bin] += gain * decSlotImPointer[bin]; + /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain + * the residual signal (that has the residual covariance matrix) */ + formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin], + 0.0f, 0.0f, /* Decorrelated signal has ideally no cross-terms */ + CrEneL, CrEneR, + CrCrossRe, CrCrossIm, + prototypeMtx, MdecRe, MdecIm, 0.2f ); + } + else + { + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + set_zero( MdecRe[chA], BINAURAL_CHANNELS ); + set_zero( MdecIm[chA], BINAURAL_CHANNELS ); + } + } - gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecImPrev[chA][chB][bin] + - interpVal * hDiracDecBin->processMtxDecIm[chA][chB][bin]; - outSlotRe[bin] -= gain * decSlotImPointer[bin]; - outSlotIm[bin] += gain * decSlotRePointer[bin]; - } - } + /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */ + realizedOutputEne = CrEneL + CrEneR + resultMtxRe[0][0] + resultMtxRe[1][1]; + targetOutputEne = hDiracDecBin->ChEneOut[0][bin] + hDiracDecBin->ChEneOut[1][bin]; + missingOutputEne = fmaxf( 0.0f, targetOutputEne - realizedOutputEne ); + + gain = sqrtf( ( resultMtxRe[0][0] + resultMtxRe[1][1] + missingOutputEne ) / + fmaxf( 1e-12f, resultMtxRe[0][0] + resultMtxRe[1][1] ) ); + gain = fminf( 4.0f, gain ); + + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) + { + Mre[chA][chB] *= gain; + Mim[chA][chB] *= gain; } + } - if ( processReverb ) + /* Store processing matrices */ + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ ) { - /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */ - v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX ); - v_add( outSlotIm, reverbIm[chA][slot], outSlotIm, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->processMtxRePrev[chA][chB][bin] = hDiracDecBin->processMtxRe[chA][chB][bin]; + hDiracDecBin->processMtxImPrev[chA][chB][bin] = hDiracDecBin->processMtxIm[chA][chB][bin]; + hDiracDecBin->processMtxDecRePrev[chA][chB][bin] = hDiracDecBin->processMtxDecRe[chA][chB][bin]; + hDiracDecBin->processMtxDecImPrev[chA][chB][bin] = hDiracDecBin->processMtxDecIm[chA][chB][bin]; + + hDiracDecBin->processMtxRe[chA][chB][bin] = Mre[chA][chB]; + hDiracDecBin->processMtxIm[chA][chB][bin] = Mim[chA][chB]; + hDiracDecBin->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB]; + hDiracDecBin->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB]; } + } - outSlotRePr = &( outSlotRe[0] ); - outSlotImPr = &( outSlotIm[0] ); + if ( separateCenterChannelRendering ) + { + /* The rendering of the separate center channel in masa + mono mode. + * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */ + float lRealp, lImagp, rRealp, rImagp; + float gainFactor; + int16_t aziDeg = 0; + int16_t eleDeg = 0; + uint8_t instantChange = 0; - /* Inverse filter bank */ - cldfbSynthesis_ivas( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); + if ( ivas_format == MASA_ISM_FORMAT ) + { + gainFactor = 0.7943f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] ); + } + else + { + gainFactor = 0.8414f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] ); + } + + for ( chB = 0; chB < nchanSeparateChannels; chB++ ) + { + if ( ivas_format == MASA_ISM_FORMAT ) + { + if ( ism_mode == ISM_MASA_MODE_DISC ) + { + aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx]; + eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx]; + } + else + { + aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx]; + eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx]; + instantChange = 1; + } + } + + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin]; + hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin]; + } + + getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked ); + + hDiracDecBin->processMtxRe[0][chB + 2][bin] = lRealp * gainFactor; + hDiracDecBin->processMtxIm[0][chB + 2][bin] = lImagp * gainFactor; + hDiracDecBin->processMtxRe[1][chB + 2][bin] = rRealp * gainFactor; + hDiracDecBin->processMtxIm[1][chB + 2][bin] = rImagp * gainFactor; + + if ( instantChange ) + { + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin]; + hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin]; + } + } + } } } return; } -#endif + #ifdef IVAS_FLOAT_FIXED -static void adaptTransportSignalsHeadtracked_fx( - COMBINED_ORIENTATION_HANDLE hHeadTrackData, +static void ivas_dirac_dec_binaural_process_output_fx( + DIRAC_DEC_BIN_HANDLE hDiracDecBin, + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, + HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], + Word32 *output_fx[], + Word16 *q_out, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - Word16 q_inp, - const Word16 nBins, - const Word16 nSlots, - Word32 Rmat[3][3] ) + const Word16 q_input, + const Word16 max_band_decorr, + const Word16 numInChannels, + const Word16 processReverb, + const Word16 subframe, + const Word16 q_mat ) { - Word16 slot, ch, bin, louderCh; - Word32 mono_factor_ILD, mono_factor; - Word32 y_val, mono_factor_rotation, ene_proc, ene_target, ILD; - Word16 max_band; - Word32 eqVal; - Word16 band_idx, bin_lo, bin_hi, norm, shift = 31; - Word16 q_chEneIIR = 0, q_procChEneIIR = 0; - Word32 temp_div; - Word16 e_div; + Word16 slot, bin, chA, chB; + Word16 nBins; + Word16 offsetSamples; + Word16 nSlots; + nBins = hSpatParamRendCom->num_freq_bands; + offsetSamples = 0; + nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + + Word32 decSlotRe_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 outSlotRe_fx[CLDFB_NO_CHANNELS_MAX], outSlotIm_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word16 q_inp[6][CLDFB_SLOTS_PER_SUBFRAME]; + Word16 interpVal_fx; + Word32 *decSlotRePointer_fx; + Word32 *decSlotImPointer_fx; + Word16 q_inp_mix, q_reverb = 31; + + + IF( processReverb ) + { + /* Process second / room effect part of binaural output when needed */ + ivas_binaural_reverb_processSubframe_fx( hDiracDecBin->hReverb, numInChannels, nSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx ); + } + + // scaling input and reverb to same q// + // input scaling is to maintain precision in ivas_dirac_dec_decorrelate_slot fn// + Word16 shift = s_min( L_norm_arr( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length ), L_norm_arr( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length ) ); + q_inp_mix = 31; FOR( Word16 i = 0; i < 6; i++ ) { FOR( Word16 j = 0; j < nSlots; j++ ) { - norm = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); - shift = s_min( norm, shift ); + q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); + IF( ( processReverb ) && ( i < 2 ) ) + { + q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) ); + q_inp[i][j] = s_min( q_reverb, q_inp[i][j] ); + } + q_inp_mix = s_min( q_inp[i][j], q_inp_mix ); } } - /* Determine head-orientation-based mono factor. - Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */ - - y_val = L_sub( ONE_IN_Q30, L_abs( Rmat[1][1] ) ); // Q30 - mono_factor_rotation = Mpy_32_16_1( L_sub( y_val, ADAPT_HTPROTO_ROT_LIM_0_FX ), TWO_POINT_FIVE_IN_Q13 ); // Q28 - mono_factor_rotation = L_max( 0, L_min( ONE_IN_Q28, mono_factor_rotation ) ); + q_inp_mix = sub( q_inp_mix, 3 ); // gaurded bits// - IF( EQ_32( mono_factor_rotation, ONE_IN_Q28 ) ) + Word16 cldfb_state_shift = sub( add( add( q_inp_mix, q_mat ), sub( q_input, 16 ) ), cldfbSynDec[0]->Q_cldfb_state ); + IF( GT_16( cldfb_state_shift, shift ) ) { - mono_factor_rotation = ONE_IN_Q31; + q_inp_mix = q_inp_mix + shift - cldfb_state_shift; + cldfb_state_shift = shift; } - ELSE + + FOR( Word16 i = 0; i < 6; i++ ) { - mono_factor_rotation = L_shl( mono_factor_rotation, 3 ); // Q31 + FOR( Word16 j = 0; j < nSlots; j++ ) + { + + scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); + scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); + IF( processReverb && ( i < 2 ) ) + { + scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); + scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); + } + } } - /* Adapt transport signals in frequency bands */ - /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */ + // scaling cldfb states to q_result-1// + scale_sig32( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length, cldfb_state_shift ); + scale_sig32( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length, cldfb_state_shift ); - max_band = 0; - WHILE( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins ) - { - max_band = add( max_band, 1 ); - } - - shift = sub( shift, 5 ); - // 5 is gaurded bits needed// - Word32 re, img, temp; - Word16 q_temp = 2 * ( q_inp + shift ) - 31; - FOR( band_idx = 0; band_idx < max_band; band_idx++ ) - { - Word32 ch_nrg[2]; /* storage for input signal channel energies */ - bin_lo = MASA_band_grouping_24[band_idx]; - bin_hi = s_min( MASA_band_grouping_24[band_idx + 1], (Word16) nBins ); - - FOR( ch = 0; ch < 2; ch++ ) - { - ch_nrg[ch] = 0; - FOR( slot = 0; slot < nSlots; slot++ ) - { - FOR( bin = bin_lo; bin < bin_hi; bin++ ) - { - re = L_shl( inRe_fx[ch][slot][bin], shift ); - img = L_shl( inIm_fx[ch][slot][bin], shift ); - - ch_nrg[ch] = L_add( ch_nrg[ch], ( L_add( Mpy_32_32( re, re ), Mpy_32_32( img, img ) ) ) ); // 2(q_inp +shift) -31 - } - } - hHeadTrackData->chEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->chEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); - temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); - IF( LT_16( hHeadTrackData->q_chEneIIR, q_temp ) ) - { - hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp, hHeadTrackData->q_chEneIIR ) ), hHeadTrackData->chEneIIR_fx[ch][band_idx] ); - } - ELSE - { - hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->chEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_chEneIIR, q_temp ) ), temp ); - } + q_inp_mix = add( q_inp_mix, q_input ); - hHeadTrackData->chEneIIR[ch][band_idx] = fixedToFloat_32( hHeadTrackData->chEneIIR_fx[ch][band_idx], s_min( hHeadTrackData->q_chEneIIR, q_temp ) ); - } - q_chEneIIR = s_min( hHeadTrackData->q_chEneIIR, q_temp ); - /* Determine ILD */ + interpVal_fx = 0; + Word16 q_result = sub( add( q_inp_mix, q_mat ), 15 ); // setting it prior// + cldfbSynDec[0]->Q_cldfb_state = sub( q_result, 1 ); + cldfbSynDec[1]->Q_cldfb_state = sub( q_result, 1 ); - IF( EQ_32( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ) ) ) + FOR( slot = 0; slot < nSlots; slot++ ) + { + IF( NE_16( slot, sub( nSlots, 1 ) ) ) { - ILD = 0; + interpVal_fx = add( interpVal_fx, slot_fx[nSlots - 1] ); } ELSE { - temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ), &e_div ) ); - - temp = BASOP_Util_Log2( temp_div ); // Q25 - IF( GE_16( e_div, 0 ) ) - temp = L_add( temp, L_shl( e_div, 25 ) ); // Q25 - ELSE - temp = L_sub( temp, L_shl( abs( e_div ), 25 ) ); // Q25 - - temp = Mpy_32_32( temp, 646462464 ); // logx base 10 = 0.30103* logx base 2// - ILD = L_abs( Mpy_32_16_1( temp, 20480 ) ); // Q21 - } - IF( GT_32( hHeadTrackData->chEneIIR_fx[1][band_idx], hHeadTrackData->chEneIIR_fx[0][band_idx] ) ) - { - louderCh = 1; + interpVal_fx = 32767; } - ELSE + IF( !hDiracDecBin->useTdDecorr && ( GT_16( max_band_decorr, 0 ) ) ) { - louderCh = 0; + ivas_dirac_dec_decorrelate_slot_fx( hDiracDecBin, nBins, slot, inRe_fx, inIm_fx, q_inp_mix, decSlotRe_fx, decSlotIm_fx ); } - /* Determine ILD-based mono factor */ - mono_factor_ILD = Mpy_32_16_1( L_sub( ILD, ONE_IN_Q21 ), 10911 ); // Q23 - - mono_factor_ILD = L_max( 0, L_min( ONE_IN_Q21, mono_factor_ILD ) ); - - IF( EQ_32( mono_factor_ILD, ONE_IN_Q21 ) ) - mono_factor_ILD = ONE_IN_Q31; - ELSE - mono_factor_ILD = L_shl( mono_factor_ILD, 10 ); // Q31 + FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + Word32 *outSlotRePr_fx, *outSlotImPr_fx; /* Pointers needed for function call compatibility */ - /* Combine mono factors */ - mono_factor = Mpy_32_32( mono_factor_ILD, mono_factor_rotation ); // Q31 + set_zero_fx( outSlotRe_fx, CLDFB_NO_CHANNELS_MAX ); + set_zero_fx( outSlotIm_fx, CLDFB_NO_CHANNELS_MAX ); - /* Mix original audio and sum signal according to determined mono factor */ - FOR( ch = 0; ch < 2; ch++ ) - { - IF( NE_16( ch, louderCh ) ) + /* Processing of the first / HRTF part of the binaural output. */ + FOR( chB = 0; chB < numInChannels; chB++ ) { - Word32 band_nrg = 0; - - FOR( slot = 0; slot < nSlots; slot++ ) + IF( LT_16( chB, BINAURAL_CHANNELS ) ) { - FOR( bin = bin_lo; bin < bin_hi; bin++ ) + /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs. + * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this + * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the + * pointers to buffers. */ + IF( hDiracDecBin->useTdDecorr ) { - /* mono sum signal with the computed weight + rest from the original channel */ - inRe_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inRe_fx[ch][slot][bin] ) ) ); - inIm_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inIm_fx[ch][slot][bin] ) ) ); - re = L_shl( inRe_fx[ch][slot][bin], shift ); - img = L_shl( inIm_fx[ch][slot][bin], shift ); - band_nrg = L_add( band_nrg, ( L_add( Mpy_32_32( re, re ), Mpy_32_32( img, img ) ) ) ); // 2(q_inp +shift) -31 + decSlotRePointer_fx = inRe_fx[chB + 2][slot]; + decSlotImPointer_fx = inIm_fx[chB + 2][slot]; + } + ELSE + { + decSlotRePointer_fx = decSlotRe_fx[chB]; + decSlotImPointer_fx = decSlotIm_fx[chB]; } - } - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); - - hHeadTrackData->procChEneIIR[ch][band_idx] = fixedToFloat_32( hHeadTrackData->procChEneIIR_fx[ch][band_idx], hHeadTrackData->q_procChEneIIR ); - - if ( ( ch == 0 && band_idx == 1 ) || ( ch == 1 && band_idx == 0 ) ) - ch = ch; - - temp = Mpy_32_16_1( band_nrg, sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); - IF( LT_16( hHeadTrackData->q_procChEneIIR, q_temp ) ) - { - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp, hHeadTrackData->q_procChEneIIR ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); } ELSE { - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR, q_temp ) ), temp ); + decSlotRePointer_fx = NULL; /* below these pointers are used only for chB < 2 */ + decSlotImPointer_fx = NULL; } - } - ELSE - { - /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */ - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); - temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); - IF( LT_16( hHeadTrackData->q_procChEneIIR, q_temp ) ) - { - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp, hHeadTrackData->q_procChEneIIR ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); - } - ELSE + + FOR( bin = 0; bin < nBins; bin++ ) { - hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR, q_temp ) ), temp ); - } - } + Word16 gain; - hHeadTrackData->procChEneIIR[ch][band_idx] = fixedToFloat_32( hHeadTrackData->procChEneIIR_fx[ch][band_idx], s_min( hHeadTrackData->q_procChEneIIR, q_temp ) ); - } + /* Mixing using the formulated processing matrix M */ + gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxRe_fx[chA][chB][bin] ) ); // Q11 - q_procChEneIIR = s_min( hHeadTrackData->q_procChEneIIR, q_temp ); + outSlotRe_fx[bin] = L_add( outSlotRe_fx[bin], Mpy_32_16_1( inRe_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result + outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( inIm_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result - /* Equalize */ - ene_target = L_add( hHeadTrackData->chEneIIR_fx[0][band_idx], hHeadTrackData->chEneIIR_fx[1][band_idx] ); // q_chEneIIR// + gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxIm_fx[chA][chB][bin] ) ); // Q11 - ene_proc = L_add( hHeadTrackData->procChEneIIR_fx[0][band_idx], hHeadTrackData->procChEneIIR_fx[1][band_idx] ); // q_procChEneIIR// + // interpVal * hDiracDecBin->processMtxIm[chA][chB][bin]; + outSlotRe_fx[bin] = L_sub( outSlotRe_fx[bin], Mpy_32_16_1( inIm_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result + outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( inRe_fx[chB][slot][bin], gain ) ); // q_inp_mix-4//q_result - temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( ene_target, L_max( 1, ene_proc ), &e_div ) ); - e_div = e_div + ( q_procChEneIIR - q_chEneIIR ); - eqVal = Sqrt32( temp_div, &e_div ); + /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */ + IF( bin < max_band_decorr && chB < 2 ) + { + gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] ) ); + // interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin]; + outSlotRe_fx[bin] = L_add( outSlotRe_fx[bin], Mpy_32_16_1( decSlotRePointer_fx[bin], gain ) ); // q_inp_mix-4//q_result + outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( decSlotImPointer_fx[bin], gain ) ); // q_inp_mix-4//q_result - Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eqVal, e_div ); - IF( EQ_16( comp_flag, -1 ) ) - eqVal = 1073741824; // 4inQ28 - ELSE - { - eqVal = L_shl( eqVal, sub( e_div, 3 ) ); // Q28 - } - FOR( slot = 0; slot < nSlots; slot++ ) - { - FOR( ch = 0; ch < 2; ch++ ) - { - FOR( bin = bin_lo; bin < bin_hi; bin++ ) - { - if ( ( ch == 0 && slot == 0 ) ) - { - if ( bin == 1 ) - bin = bin; + gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] ) ); + outSlotRe_fx[bin] = L_sub( outSlotRe_fx[bin], Mpy_32_16_1( decSlotImPointer_fx[bin], gain ) ); // q_inp_mix-4//q_result + outSlotIm_fx[bin] = L_add( outSlotIm_fx[bin], Mpy_32_16_1( decSlotRePointer_fx[bin], gain ) ); // q_inp_mix-4//q_result } + } + } - Word16 temp_shift = s_min( norm_l( inRe_fx[ch][slot][bin] ), norm_l( inIm_fx[ch][slot][bin] ) ); - re = L_shl( inRe_fx[ch][slot][bin], temp_shift ); - img = L_shl( inIm_fx[ch][slot][bin], temp_shift ); - re = L_shr( Mpy_32_32( re, eqVal ), sub( temp_shift, 3 ) ); - img = L_shr( Mpy_32_32( img, eqVal ), sub( temp_shift, 3 ) ); - inRe_fx[ch][slot][bin] = re; // q_inp - inIm_fx[ch][slot][bin] = img; // q_inp - } + IF( processReverb ) + { + /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */ + v_add_fx( outSlotRe_fx, reverbRe_fx[chA][slot], outSlotRe_fx, CLDFB_NO_CHANNELS_MAX ); + v_add_fx( outSlotIm_fx, reverbIm_fx[chA][slot], outSlotIm_fx, CLDFB_NO_CHANNELS_MAX ); } - } - } - hHeadTrackData->q_chEneIIR = q_chEneIIR; - hHeadTrackData->q_procChEneIIR = q_procChEneIIR; + outSlotRePr_fx = &( outSlotRe_fx[0] ); + outSlotImPr_fx = &( outSlotIm_fx[0] ); + + cldfbSynthesis_ivas_fx( &outSlotRePr_fx, &outSlotImPr_fx, &( output_fx[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); + cldfbSynDec[chA]->Q_cldfb_state = sub( q_result, 1 ); + } + } + *q_out = sub( q_result, 1 ); return; } #else -static void adaptTransportSignalsHeadtracked( - COMBINED_ORIENTATION_HANDLE hHeadTrackData, +static void ivas_dirac_dec_binaural_process_output( + DIRAC_DEC_BIN_HANDLE hDiracDecBin, + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, + HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], + float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - const int16_t nBins, - const int16_t nSlots, - float Rmat[3][3] ) + const int16_t max_band_decorr, + const int16_t numInChannels, + const int16_t processReverb, + const int16_t subframe ) { - int16_t slot, ch, bin, louderCh; - float ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val, ene_proc, ene_target; - int16_t max_band; - float eqVal; - int16_t band_idx, bin_lo, bin_hi; - - /* Determine head-orientation-based mono factor. - Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */ - y_val = 1.0f - fabsf( Rmat[1][1] ); - mono_factor_rotation = ( y_val - ADAPT_HTPROTO_ROT_LIM_0 ) / ( ADAPT_HTPROTO_ROT_LIM_1 - ADAPT_HTPROTO_ROT_LIM_0 ); - mono_factor_rotation = fmaxf( 0.0f, fminf( 1.0f, mono_factor_rotation ) ); + int16_t slot, bin, chA, chB; + int16_t nBins; + float outSlotRe[CLDFB_NO_CHANNELS_MAX], outSlotIm[CLDFB_NO_CHANNELS_MAX]; + float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float interpVal; + float *decSlotRePointer; + float *decSlotImPointer; + int16_t offsetSamples; + int16_t nSlots; - /* Adapt transport signals in frequency bands */ - /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */ + nBins = hSpatParamRendCom->num_freq_bands; + offsetSamples = 0; + nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; - max_band = 0; - while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins ) + if ( processReverb ) { - max_band++; + /* Process second / room effect part of binaural output when needed */ + ivas_binaural_reverb_processSubframe( hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm ); } - for ( band_idx = 0; band_idx < max_band; band_idx++ ) + interpVal = 0.0f; + for ( slot = 0; slot < nSlots; slot++ ) { - float ch_nrg[2]; /* storage for input signal channel energies */ - bin_lo = MASA_band_grouping_24[band_idx]; - bin_hi = min( MASA_band_grouping_24[band_idx + 1], (int16_t) nBins ); - for ( ch = 0; ch < 2; ch++ ) + interpVal += 1.0f / (float) nSlots; + if ( !hDiracDecBin->useTdDecorr && max_band_decorr > 0 ) { - ch_nrg[ch] = 0.0f; - for ( slot = 0; slot < nSlots; slot++ ) - { - for ( bin = bin_lo; bin < bin_hi; bin++ ) - { - ch_nrg[ch] += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); - } - } - hHeadTrackData->chEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; - hHeadTrackData->chEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch]; + ivas_dirac_dec_decorrelate_slot( hDiracDecBin, nBins, slot, inRe, inIm, decSlotRe, decSlotIm ); } - /* Determine ILD */ - ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][band_idx] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][band_idx] ) ) ); - if ( hHeadTrackData->chEneIIR[1][band_idx] > hHeadTrackData->chEneIIR[0][band_idx] ) - { - louderCh = 1; - } - else + for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) { - louderCh = 0; - } - - /* Determine ILD-based mono factor */ - mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 ); - mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) ); + float *outSlotRePr, *outSlotImPr; /* Pointers needed for function call compatibility */ - /* Combine mono factors */ - mono_factor = mono_factor_ILD * mono_factor_rotation; + set_zero( outSlotRe, CLDFB_NO_CHANNELS_MAX ); + set_zero( outSlotIm, CLDFB_NO_CHANNELS_MAX ); - /* Mix original audio and sum signal according to determined mono factor */ - for ( ch = 0; ch < 2; ch++ ) - { - if ( ch != louderCh ) + /* Processing of the first / HRTF part of the binaural output. */ + for ( chB = 0; chB < numInChannels; chB++ ) { - float band_nrg = 0.0f; + if ( chB < BINAURAL_CHANNELS ) + { + /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs. + * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this + * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the + * pointers to buffers. */ + if ( hDiracDecBin->useTdDecorr ) + { + decSlotRePointer = inRe[chB + 2][slot]; + decSlotImPointer = inIm[chB + 2][slot]; + } + else + { + decSlotRePointer = decSlotRe[chB]; + decSlotImPointer = decSlotIm[chB]; + } + } + else + { + decSlotRePointer = NULL; /* below these pointers are used only for chB < 2 */ + decSlotImPointer = NULL; + } - for ( slot = 0; slot < nSlots; slot++ ) + + for ( bin = 0; bin < nBins; bin++ ) { - for ( bin = bin_lo; bin < bin_hi; bin++ ) + float gain; + + /* Mixing using the formulated processing matrix M */ + gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxRePrev[chA][chB][bin] + + interpVal * hDiracDecBin->processMtxRe[chA][chB][bin]; + outSlotRe[bin] += gain * inRe[chB][slot][bin]; + outSlotIm[bin] += gain * inIm[chB][slot][bin]; + + gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxImPrev[chA][chB][bin] + + interpVal * hDiracDecBin->processMtxIm[chA][chB][bin]; + outSlotRe[bin] -= gain * inIm[chB][slot][bin]; + outSlotIm[bin] += gain * inRe[chB][slot][bin]; + + /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */ + if ( bin < max_band_decorr && chB < 2 ) { - /* mono sum signal with the computed weight + rest from the original channel */ - inRe[ch][slot][bin] = mono_factor * ( inRe[0][slot][bin] + inRe[1][slot][bin] ) + ( 1.0f - mono_factor ) * inRe[ch][slot][bin]; - inIm[ch][slot][bin] = mono_factor * ( inIm[0][slot][bin] + inIm[1][slot][bin] ) + ( 1.0f - mono_factor ) * inIm[ch][slot][bin]; - band_nrg += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecRePrev[chA][chB][bin] + + interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin]; + outSlotRe[bin] += gain * decSlotRePointer[bin]; + outSlotIm[bin] += gain * decSlotImPointer[bin]; + + gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecImPrev[chA][chB][bin] + + interpVal * hDiracDecBin->processMtxDecIm[chA][chB][bin]; + outSlotRe[bin] -= gain * decSlotImPointer[bin]; + outSlotIm[bin] += gain * decSlotRePointer[bin]; } } - hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; - hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * band_nrg; } - else + + if ( processReverb ) { - /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */ - hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; - hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch]; + /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */ + v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX ); + v_add( outSlotIm, reverbIm[chA][slot], outSlotIm, CLDFB_NO_CHANNELS_MAX ); } - } - /* Equalize */ - ene_target = hHeadTrackData->chEneIIR[0][band_idx] + hHeadTrackData->chEneIIR[1][band_idx]; - ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx]; - eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) ); + outSlotRePr = &( outSlotRe[0] ); + outSlotImPr = &( outSlotIm[0] ); - for ( slot = 0; slot < nSlots; slot++ ) - { - for ( ch = 0; ch < 2; ch++ ) - { - for ( bin = bin_lo; bin < bin_hi; bin++ ) - { - inRe[ch][slot][bin] *= eqVal; - inIm[ch][slot][bin] *= eqVal; - } - } + /* Inverse filter bank */ + cldfbSynthesis_ivas( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); } } @@ -3087,34 +3380,26 @@ static void adaptTransportSignalsHeadtracked( #endif #ifdef IVAS_FLOAT_FIXED -static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( +static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word16 q_inp, const Word16 nBins, const Word16 nSlots, - Word32 Rmat_fx[3][3] ) + Word32 Rmat[3][3] ) { - Word16 slot, bin, ch; - Word32 tmpVal; - Word16 norm, e_div, shift = 31; - Word32 Re, Im, temp_div; - - /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */ - IF( EQ_16( (Word16) hHeadTrackData->lrSwitchedNext, (Word16) hHeadTrackData->lrSwitchedCurrent ) ) - { - Word32 thresholdDotProduct = 182536112; // 0.17 in Q30// /* Corresponds to 10-degree switching threshold */ - IF( EQ_16( (Word16) hHeadTrackData->lrSwitchedCurrent, 0 ) && ( LT_32( Rmat_fx[1][1], L_negate( thresholdDotProduct ) ) ) ) - { - hHeadTrackData->lrSwitchedNext = 1; - } - IF( EQ_16( (Word16) hHeadTrackData->lrSwitchedCurrent, 1 ) && ( GT_32( Rmat_fx[1][1], thresholdDotProduct ) ) ) - { - hHeadTrackData->lrSwitchedNext = 0; - } - } + Word16 slot, ch, bin, louderCh; + Word32 mono_factor_ILD, mono_factor; + Word32 y_val, mono_factor_rotation, ene_proc, ene_target, ILD; + Word16 max_band; + Word32 eqVal; + Word16 band_idx, bin_lo, bin_hi, norm, shift = 31; + Word16 q_chEneIIR = 0, q_procChEneIIR = 0; + Word32 temp_div; + Word16 e_div; - FOR( Word16 i = 0; i < 2; i++ ) + FOR( Word16 i = 0; i < 6; i++ ) { FOR( Word16 j = 0; j < nSlots; j++ ) { @@ -3123,116 +3408,217 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( } } - shift = sub( shift, 3 ); // guard bits// - /* When currently in interpolation */ - IF( NE_16( (Word16) hHeadTrackData->lrSwitchedNext, (Word16) hHeadTrackData->lrSwitchedCurrent ) ) - { - FOR( slot = 0; slot < nSlots; slot++ ) - { - Word32 switchOrderFactor, origOrderFactor; - Word16 e_switchOrderFactor, e_origOrderFactor; + /* Determine head-orientation-based mono factor. + Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */ - hHeadTrackData->lrSwitchInterpVal_fx = L_add( hHeadTrackData->lrSwitchInterpVal_fx, 2684354 ); /* Corresponds to 0.5 seconds interpolation time */ // Q14 + y_val = L_sub( ONE_IN_Q30, L_abs( Rmat[1][1] ) ); // Q30 + mono_factor_rotation = Mpy_32_16_1( L_sub( y_val, ADAPT_HTPROTO_ROT_LIM_0_FX ), TWO_POINT_FIVE_IN_Q13 ); // Q28 + mono_factor_rotation = L_max( 0, L_min( ONE_IN_Q28, mono_factor_rotation ) ); - IF( GT_32( hHeadTrackData->lrSwitchInterpVal_fx, 1072668096 ) ) - { - /* Stop interpolation, reset values */ - hHeadTrackData->lrSwitchInterpVal_fx = 0; - hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext; - } + IF( EQ_32( mono_factor_rotation, ONE_IN_Q28 ) ) + { + mono_factor_rotation = ONE_IN_Q31; + } + ELSE + { + mono_factor_rotation = L_shl( mono_factor_rotation, 3 ); // Q31 + } - /* Gains for determining portion of switched channel order and original channel order */ - tmpVal = Mpy_32_16_1( hHeadTrackData->lrSwitchInterpVal_fx, (Word16) hHeadTrackData->lrSwitchedNext ); // Q15 - tmpVal = L_add( tmpVal, Mpy_32_16_1( L_sub( ONE_IN_Q30, hHeadTrackData->lrSwitchInterpVal_fx ), (Word16) hHeadTrackData->lrSwitchedCurrent ) ); // Q15 + /* Adapt transport signals in frequency bands */ + /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */ - e_switchOrderFactor = 0; - e_origOrderFactor = 0; - IF( EQ_32( tmpVal, 32768 ) ) - tmpVal = ONE_IN_Q31; - ELSE - tmpVal = L_shl( tmpVal, 16 ); // Q31 - switchOrderFactor = Sqrt32( tmpVal, &e_switchOrderFactor ); - switchOrderFactor = L_shl( switchOrderFactor, e_switchOrderFactor ); // Q31 - origOrderFactor = Sqrt32( L_sub( ONE_IN_Q31, tmpVal ), &e_origOrderFactor ); // Q31 - origOrderFactor = L_shl( origOrderFactor, e_origOrderFactor ); - FOR( bin = 0; bin < nBins; bin++ ) - { - /* determine original order (1) signals and switched order (2) signals */ - Word32 re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS]; + max_band = 0; + WHILE( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins ) + { + max_band = add( max_band, 1 ); + } - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - re1[ch] = Mpy_32_32( inRe_fx[ch][slot][bin], origOrderFactor ); // q_inp - re2[ch] = Mpy_32_32( inRe_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp - im1[ch] = Mpy_32_32( inIm_fx[ch][slot][bin], origOrderFactor ); // q_inp - im2[ch] = Mpy_32_32( inIm_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp - } + shift = sub( shift, 5 ); + // 5 is gaurded bits needed// + Word32 re, img, temp; + Word16 q_temp = 2 * ( q_inp + shift ) - 31; + FOR( band_idx = 0; band_idx < max_band; band_idx++ ) + { + Word32 ch_nrg[2]; /* storage for input signal channel energies */ + bin_lo = MASA_band_grouping_24[band_idx]; + bin_hi = s_min( MASA_band_grouping_24[band_idx + 1], (Word16) nBins ); - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + FOR( ch = 0; ch < 2; ch++ ) + { + ch_nrg[ch] = 0; + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) { - Word32 eneRef, ene, eq; - - re1[ch] = L_shl( re1[ch], shift ); // q_inp+shift// - re2[ch] = L_shl( re2[ch], shift ); // q_inp+shift// - im1[ch] = L_shl( im1[ch], shift ); // q_inp+shift// - im2[ch] = L_shl( im2[ch], shift ); // q_inp+shift// + re = L_shl( inRe_fx[ch][slot][bin], shift ); + img = L_shl( inIm_fx[ch][slot][bin], shift ); - /* Interpolate / mix original and switched order signals */ - Re = L_add( re1[ch], re2[ch] ); // q_inp+shift// - Im = L_add( im1[ch], im2[ch] ); // q_inp+shift// + ch_nrg[ch] = L_add( ch_nrg[ch], ( L_add( Mpy_32_32( re, re ), Mpy_32_32( img, img ) ) ) ); // 2(q_inp +shift) -31 + } + } + hHeadTrackData->chEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->chEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); + temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); + IF( LT_16( hHeadTrackData->q_chEneIIR, q_temp ) ) + { + hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp, hHeadTrackData->q_chEneIIR ) ), hHeadTrackData->chEneIIR_fx[ch][band_idx] ); + } + ELSE + { + hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->chEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_chEneIIR, q_temp ) ), temp ); + } - /* Equalize interpolated signals to preserve energy per bin */ + hHeadTrackData->chEneIIR[ch][band_idx] = fixedToFloat_32( hHeadTrackData->chEneIIR_fx[ch][band_idx], s_min( hHeadTrackData->q_chEneIIR, q_temp ) ); + } + q_chEneIIR = s_min( hHeadTrackData->q_chEneIIR, q_temp ); + /* Determine ILD */ - eneRef = L_add( ( L_add( Mpy_32_32( re1[ch], re1[ch] ), Mpy_32_32( re2[ch], re2[ch] ) ) ), ( L_add( Mpy_32_32( im1[ch], im1[ch] ), Mpy_32_32( im2[ch], im2[ch] ) ) ) ); // 2*(q_inp+shift) -31// - ene = L_add( Mpy_32_32( Re, Re ), Mpy_32_32( Im, Im ) ); // 2*(q_inp+shift) -31// + IF( EQ_32( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ) ) ) + { + ILD = 0; + } + ELSE + { + temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ), &e_div ) ); - temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( eneRef, L_max( 1, ene ), &e_div ) ); + temp = BASOP_Util_Log2( temp_div ); // Q25 + IF( GE_16( e_div, 0 ) ) + temp = L_add( temp, L_shl( e_div, 25 ) ); // Q25 + ELSE + temp = L_sub( temp, L_shl( abs( e_div ), 25 ) ); // Q25 - eq = Sqrt32( temp_div, &e_div ); + temp = Mpy_32_32( temp, 646462464 ); // logx base 10 = 0.30103* logx base 2// + ILD = L_abs( Mpy_32_16_1( temp, 20480 ) ); // Q21 + } + IF( GT_32( hHeadTrackData->chEneIIR_fx[1][band_idx], hHeadTrackData->chEneIIR_fx[0][band_idx] ) ) + { + louderCh = 1; + } + ELSE + { + louderCh = 0; + } - Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eq, e_div ); - IF( EQ_16( comp_flag, -1 ) ) - eq = 1073741824; // 4inQ28 - ELSE + /* Determine ILD-based mono factor */ + mono_factor_ILD = Mpy_32_16_1( L_sub( ILD, ONE_IN_Q21 ), 10911 ); // Q23 + + mono_factor_ILD = L_max( 0, L_min( ONE_IN_Q21, mono_factor_ILD ) ); + + IF( EQ_32( mono_factor_ILD, ONE_IN_Q21 ) ) + mono_factor_ILD = ONE_IN_Q31; + ELSE + mono_factor_ILD = L_shl( mono_factor_ILD, 10 ); // Q31 + + /* Combine mono factors */ + mono_factor = Mpy_32_32( mono_factor_ILD, mono_factor_rotation ); // Q31 + + /* Mix original audio and sum signal according to determined mono factor */ + FOR( ch = 0; ch < 2; ch++ ) + { + IF( NE_16( ch, louderCh ) ) + { + Word32 band_nrg = 0; + + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) { - eq = L_shl( eq, sub( e_div, 3 ) ); // Q28 + /* mono sum signal with the computed weight + rest from the original channel */ + inRe_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inRe_fx[ch][slot][bin] ) ) ); + inIm_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inIm_fx[ch][slot][bin] ) ) ); + re = L_shl( inRe_fx[ch][slot][bin], shift ); + img = L_shl( inIm_fx[ch][slot][bin], shift ); + band_nrg = L_add( band_nrg, ( L_add( Mpy_32_32( re, re ), Mpy_32_32( img, img ) ) ) ); // 2(q_inp +shift) -31 } + } + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); - Re = L_shr( Mpy_32_32( Re, eq ), sub( shift, 3 ) ); // q_inp - Im = L_shr( Mpy_32_32( Im, eq ), sub( shift, 3 ) ); // q_inp + hHeadTrackData->procChEneIIR[ch][band_idx] = fixedToFloat_32( hHeadTrackData->procChEneIIR_fx[ch][band_idx], hHeadTrackData->q_procChEneIIR ); - inRe_fx[ch][slot][bin] = Re; - inIm_fx[ch][slot][bin] = Im; + if ( ( ch == 0 && band_idx == 1 ) || ( ch == 1 && band_idx == 0 ) ) + ch = ch; + + temp = Mpy_32_16_1( band_nrg, sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); + IF( LT_16( hHeadTrackData->q_procChEneIIR, q_temp ) ) + { + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp, hHeadTrackData->q_procChEneIIR ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); + } + ELSE + { + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR, q_temp ) ), temp ); + } + } + ELSE + { + /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */ + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); + + temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); + IF( LT_16( hHeadTrackData->q_procChEneIIR, q_temp ) ) + { + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp, hHeadTrackData->q_procChEneIIR ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); + } + ELSE + { + hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR, q_temp ) ), temp ); } } + + hHeadTrackData->procChEneIIR[ch][band_idx] = fixedToFloat_32( hHeadTrackData->procChEneIIR_fx[ch][band_idx], s_min( hHeadTrackData->q_procChEneIIR, q_temp ) ); } - } - ELSE - { - /* If not in interpolation, but in switched prototype situation, then switch left and right channels */ - IF( hHeadTrackData->lrSwitchedCurrent == 1 ) + + q_procChEneIIR = s_min( hHeadTrackData->q_procChEneIIR, q_temp ); + + /* Equalize */ + ene_target = L_add( hHeadTrackData->chEneIIR_fx[0][band_idx], hHeadTrackData->chEneIIR_fx[1][band_idx] ); // q_chEneIIR// + + ene_proc = L_add( hHeadTrackData->procChEneIIR_fx[0][band_idx], hHeadTrackData->procChEneIIR_fx[1][band_idx] ); // q_procChEneIIR// + + temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( ene_target, L_max( 1, ene_proc ), &e_div ) ); + e_div = e_div + ( q_procChEneIIR - q_chEneIIR ); + + eqVal = Sqrt32( temp_div, &e_div ); + + Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eqVal, e_div ); + IF( EQ_16( comp_flag, -1 ) ) + eqVal = 1073741824; // 4inQ28 + ELSE { - FOR( slot = 0; slot < nSlots; slot++ ) + eqVal = L_shl( eqVal, sub( e_div, 3 ) ); // Q28 + } + + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( ch = 0; ch < 2; ch++ ) { - FOR( bin = 0; bin < nBins; bin++ ) + FOR( bin = bin_lo; bin < bin_hi; bin++ ) { - tmpVal = inRe_fx[0][slot][bin]; - inRe_fx[0][slot][bin] = inRe_fx[1][slot][bin]; - inRe_fx[1][slot][bin] = tmpVal; - tmpVal = inIm_fx[0][slot][bin]; - inIm_fx[0][slot][bin] = inIm_fx[1][slot][bin]; - inIm_fx[1][slot][bin] = tmpVal; + if ( ( ch == 0 && slot == 0 ) ) + { + if ( bin == 1 ) + bin = bin; + } + + Word16 temp_shift = s_min( norm_l( inRe_fx[ch][slot][bin] ), norm_l( inIm_fx[ch][slot][bin] ) ); + re = L_shl( inRe_fx[ch][slot][bin], temp_shift ); + img = L_shl( inIm_fx[ch][slot][bin], temp_shift ); + + re = L_shr( Mpy_32_32( re, eqVal ), sub( temp_shift, 3 ) ); + img = L_shr( Mpy_32_32( img, eqVal ), sub( temp_shift, 3 ) ); + inRe_fx[ch][slot][bin] = re; // q_inp + inIm_fx[ch][slot][bin] = img; // q_inp } } } } + + hHeadTrackData->q_chEneIIR = q_chEneIIR; + hHeadTrackData->q_procChEneIIR = q_procChEneIIR; return; } -#endif - -static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( +#else +static void adaptTransportSignalsHeadtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], @@ -3240,54 +3626,316 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( const int16_t nSlots, float Rmat[3][3] ) { - int16_t slot, bin, ch; - float tmpVal; + int16_t slot, ch, bin, louderCh; + float ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val, ene_proc, ene_target; + int16_t max_band; + float eqVal; + int16_t band_idx, bin_lo, bin_hi; - /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */ - if ( hHeadTrackData->lrSwitchedNext == hHeadTrackData->lrSwitchedCurrent ) + /* Determine head-orientation-based mono factor. + Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */ + y_val = 1.0f - fabsf( Rmat[1][1] ); + mono_factor_rotation = ( y_val - ADAPT_HTPROTO_ROT_LIM_0 ) / ( ADAPT_HTPROTO_ROT_LIM_1 - ADAPT_HTPROTO_ROT_LIM_0 ); + mono_factor_rotation = fmaxf( 0.0f, fminf( 1.0f, mono_factor_rotation ) ); + + /* Adapt transport signals in frequency bands */ + /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */ + + max_band = 0; + while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins ) { - float thresholdDotProduct = 0.17f; /* Corresponds to 10-degree switching threshold */ - if ( ( hHeadTrackData->lrSwitchedCurrent == 0 ) && ( Rmat[1][1] < -thresholdDotProduct ) ) - { - hHeadTrackData->lrSwitchedNext = 1; - } - if ( ( hHeadTrackData->lrSwitchedCurrent == 1 ) && ( Rmat[1][1] > thresholdDotProduct ) ) - { - hHeadTrackData->lrSwitchedNext = 0; - } + max_band++; } - /* When currently in interpolation */ - if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent ) + for ( band_idx = 0; band_idx < max_band; band_idx++ ) { - for ( slot = 0; slot < nSlots; slot++ ) + float ch_nrg[2]; /* storage for input signal channel energies */ + bin_lo = MASA_band_grouping_24[band_idx]; + bin_hi = min( MASA_band_grouping_24[band_idx + 1], (int16_t) nBins ); + for ( ch = 0; ch < 2; ch++ ) { - float switchOrderFactor, origOrderFactor; - - hHeadTrackData->lrSwitchInterpVal += 0.0025f; /* Corresponds to 0.5 seconds interpolation time */ - - if ( hHeadTrackData->lrSwitchInterpVal > 0.999f ) + ch_nrg[ch] = 0.0f; + for ( slot = 0; slot < nSlots; slot++ ) { - /* Stop interpolation, reset values */ - hHeadTrackData->lrSwitchInterpVal = 0.0f; - hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext; + for ( bin = bin_lo; bin < bin_hi; bin++ ) + { + ch_nrg[ch] += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + } } + hHeadTrackData->chEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->chEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch]; + } - /* Gains for determining portion of switched channel order and original channel order */ - tmpVal = (float) hHeadTrackData->lrSwitchedNext * hHeadTrackData->lrSwitchInterpVal; - tmpVal += (float) hHeadTrackData->lrSwitchedCurrent * ( 1.0f - hHeadTrackData->lrSwitchInterpVal ); - switchOrderFactor = sqrtf( tmpVal ); - origOrderFactor = sqrtf( 1.0f - tmpVal ); + /* Determine ILD */ + ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][band_idx] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][band_idx] ) ) ); + if ( hHeadTrackData->chEneIIR[1][band_idx] > hHeadTrackData->chEneIIR[0][band_idx] ) + { + louderCh = 1; + } + else + { + louderCh = 0; + } - for ( bin = 0; bin < nBins; bin++ ) - { - /* determine original order (1) signals and switched order (2) signals */ - float re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS]; + /* Determine ILD-based mono factor */ + mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 ); + mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) ); - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - re1[ch] = inRe[ch][slot][bin] * origOrderFactor; - re2[ch] = inRe[1 - ch][slot][bin] * switchOrderFactor; + /* Combine mono factors */ + mono_factor = mono_factor_ILD * mono_factor_rotation; + + /* Mix original audio and sum signal according to determined mono factor */ + for ( ch = 0; ch < 2; ch++ ) + { + if ( ch != louderCh ) + { + float band_nrg = 0.0f; + + for ( slot = 0; slot < nSlots; slot++ ) + { + for ( bin = bin_lo; bin < bin_hi; bin++ ) + { + /* mono sum signal with the computed weight + rest from the original channel */ + inRe[ch][slot][bin] = mono_factor * ( inRe[0][slot][bin] + inRe[1][slot][bin] ) + ( 1.0f - mono_factor ) * inRe[ch][slot][bin]; + inIm[ch][slot][bin] = mono_factor * ( inIm[0][slot][bin] + inIm[1][slot][bin] ) + ( 1.0f - mono_factor ) * inIm[ch][slot][bin]; + band_nrg += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] ); + } + } + hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * band_nrg; + } + else + { + /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */ + hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC; + hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch]; + } + } + + /* Equalize */ + ene_target = hHeadTrackData->chEneIIR[0][band_idx] + hHeadTrackData->chEneIIR[1][band_idx]; + ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx]; + eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) ); + + for ( slot = 0; slot < nSlots; slot++ ) + { + for ( ch = 0; ch < 2; ch++ ) + { + for ( bin = bin_lo; bin < bin_hi; bin++ ) + { + inRe[ch][slot][bin] *= eqVal; + inIm[ch][slot][bin] *= eqVal; + } + } + } + } + + return; +} +#endif + +#ifdef IVAS_FLOAT_FIXED +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( + COMBINED_ORIENTATION_HANDLE hHeadTrackData, + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const Word16 nBins, + const Word16 nSlots, + Word32 Rmat_fx[3][3] ) +{ + Word16 slot, bin, ch; + Word32 tmpVal; + Word16 norm, e_div, shift = 31; + Word32 Re, Im, temp_div; + + /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */ + IF( EQ_16( (Word16) hHeadTrackData->lrSwitchedNext, (Word16) hHeadTrackData->lrSwitchedCurrent ) ) + { + Word32 thresholdDotProduct = 182536112; // 0.17 in Q30// /* Corresponds to 10-degree switching threshold */ + IF( EQ_16( (Word16) hHeadTrackData->lrSwitchedCurrent, 0 ) && ( LT_32( Rmat_fx[1][1], L_negate( thresholdDotProduct ) ) ) ) + { + hHeadTrackData->lrSwitchedNext = 1; + } + IF( EQ_16( (Word16) hHeadTrackData->lrSwitchedCurrent, 1 ) && ( GT_32( Rmat_fx[1][1], thresholdDotProduct ) ) ) + { + hHeadTrackData->lrSwitchedNext = 0; + } + } + + FOR( Word16 i = 0; i < 2; i++ ) + { + FOR( Word16 j = 0; j < nSlots; j++ ) + { + norm = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); + shift = s_min( norm, shift ); + } + } + + shift = sub( shift, 3 ); // guard bits// + /* When currently in interpolation */ + IF( NE_16( (Word16) hHeadTrackData->lrSwitchedNext, (Word16) hHeadTrackData->lrSwitchedCurrent ) ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + Word32 switchOrderFactor, origOrderFactor; + Word16 e_switchOrderFactor, e_origOrderFactor; + + hHeadTrackData->lrSwitchInterpVal_fx = L_add( hHeadTrackData->lrSwitchInterpVal_fx, 2684354 ); /* Corresponds to 0.5 seconds interpolation time */ // Q14 + + IF( GT_32( hHeadTrackData->lrSwitchInterpVal_fx, 1072668096 ) ) + { + /* Stop interpolation, reset values */ + hHeadTrackData->lrSwitchInterpVal_fx = 0; + hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext; + } + + /* Gains for determining portion of switched channel order and original channel order */ + tmpVal = Mpy_32_16_1( hHeadTrackData->lrSwitchInterpVal_fx, (Word16) hHeadTrackData->lrSwitchedNext ); // Q15 + tmpVal = L_add( tmpVal, Mpy_32_16_1( L_sub( ONE_IN_Q30, hHeadTrackData->lrSwitchInterpVal_fx ), (Word16) hHeadTrackData->lrSwitchedCurrent ) ); // Q15 + + e_switchOrderFactor = 0; + e_origOrderFactor = 0; + IF( EQ_32( tmpVal, 32768 ) ) + tmpVal = ONE_IN_Q31; + ELSE + tmpVal = L_shl( tmpVal, 16 ); // Q31 + switchOrderFactor = Sqrt32( tmpVal, &e_switchOrderFactor ); + switchOrderFactor = L_shl( switchOrderFactor, e_switchOrderFactor ); // Q31 + origOrderFactor = Sqrt32( L_sub( ONE_IN_Q31, tmpVal ), &e_origOrderFactor ); // Q31 + origOrderFactor = L_shl( origOrderFactor, e_origOrderFactor ); + FOR( bin = 0; bin < nBins; bin++ ) + { + /* determine original order (1) signals and switched order (2) signals */ + Word32 re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS]; + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + re1[ch] = Mpy_32_32( inRe_fx[ch][slot][bin], origOrderFactor ); // q_inp + re2[ch] = Mpy_32_32( inRe_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp + im1[ch] = Mpy_32_32( inIm_fx[ch][slot][bin], origOrderFactor ); // q_inp + im2[ch] = Mpy_32_32( inIm_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + Word32 eneRef, ene, eq; + + re1[ch] = L_shl( re1[ch], shift ); // q_inp+shift// + re2[ch] = L_shl( re2[ch], shift ); // q_inp+shift// + im1[ch] = L_shl( im1[ch], shift ); // q_inp+shift// + im2[ch] = L_shl( im2[ch], shift ); // q_inp+shift// + + /* Interpolate / mix original and switched order signals */ + Re = L_add( re1[ch], re2[ch] ); // q_inp+shift// + Im = L_add( im1[ch], im2[ch] ); // q_inp+shift// + + /* Equalize interpolated signals to preserve energy per bin */ + + eneRef = L_add( ( L_add( Mpy_32_32( re1[ch], re1[ch] ), Mpy_32_32( re2[ch], re2[ch] ) ) ), ( L_add( Mpy_32_32( im1[ch], im1[ch] ), Mpy_32_32( im2[ch], im2[ch] ) ) ) ); // 2*(q_inp+shift) -31// + ene = L_add( Mpy_32_32( Re, Re ), Mpy_32_32( Im, Im ) ); // 2*(q_inp+shift) -31// + + temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( eneRef, L_max( 1, ene ), &e_div ) ); + + eq = Sqrt32( temp_div, &e_div ); + + Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eq, e_div ); + IF( EQ_16( comp_flag, -1 ) ) + eq = 1073741824; // 4inQ28 + ELSE + { + eq = L_shl( eq, sub( e_div, 3 ) ); // Q28 + } + + Re = L_shr( Mpy_32_32( Re, eq ), sub( shift, 3 ) ); // q_inp + Im = L_shr( Mpy_32_32( Im, eq ), sub( shift, 3 ) ); // q_inp + + inRe_fx[ch][slot][bin] = Re; + inIm_fx[ch][slot][bin] = Im; + } + } + } + } + ELSE + { + /* If not in interpolation, but in switched prototype situation, then switch left and right channels */ + IF( hHeadTrackData->lrSwitchedCurrent == 1 ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = 0; bin < nBins; bin++ ) + { + tmpVal = inRe_fx[0][slot][bin]; + inRe_fx[0][slot][bin] = inRe_fx[1][slot][bin]; + inRe_fx[1][slot][bin] = tmpVal; + tmpVal = inIm_fx[0][slot][bin]; + inIm_fx[0][slot][bin] = inIm_fx[1][slot][bin]; + inIm_fx[1][slot][bin] = tmpVal; + } + } + } + } + + return; +} + +#endif + +static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( + COMBINED_ORIENTATION_HANDLE hHeadTrackData, + float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const int16_t nBins, + const int16_t nSlots, + float Rmat[3][3] ) +{ + int16_t slot, bin, ch; + float tmpVal; + + /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */ + if ( hHeadTrackData->lrSwitchedNext == hHeadTrackData->lrSwitchedCurrent ) + { + float thresholdDotProduct = 0.17f; /* Corresponds to 10-degree switching threshold */ + if ( ( hHeadTrackData->lrSwitchedCurrent == 0 ) && ( Rmat[1][1] < -thresholdDotProduct ) ) + { + hHeadTrackData->lrSwitchedNext = 1; + } + if ( ( hHeadTrackData->lrSwitchedCurrent == 1 ) && ( Rmat[1][1] > thresholdDotProduct ) ) + { + hHeadTrackData->lrSwitchedNext = 0; + } + } + + /* When currently in interpolation */ + if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent ) + { + for ( slot = 0; slot < nSlots; slot++ ) + { + float switchOrderFactor, origOrderFactor; + + hHeadTrackData->lrSwitchInterpVal += 0.0025f; /* Corresponds to 0.5 seconds interpolation time */ + + if ( hHeadTrackData->lrSwitchInterpVal > 0.999f ) + { + /* Stop interpolation, reset values */ + hHeadTrackData->lrSwitchInterpVal = 0.0f; + hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext; + } + + /* Gains for determining portion of switched channel order and original channel order */ + tmpVal = (float) hHeadTrackData->lrSwitchedNext * hHeadTrackData->lrSwitchInterpVal; + tmpVal += (float) hHeadTrackData->lrSwitchedCurrent * ( 1.0f - hHeadTrackData->lrSwitchInterpVal ); + switchOrderFactor = sqrtf( tmpVal ); + origOrderFactor = sqrtf( 1.0f - tmpVal ); + + for ( bin = 0; bin < nBins; bin++ ) + { + /* determine original order (1) signals and switched order (2) signals */ + float re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS]; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + re1[ch] = inRe[ch][slot][bin] * origOrderFactor; + re2[ch] = inRe[1 - ch][slot][bin] * switchOrderFactor; im1[ch] = inIm[ch][slot][bin] * origOrderFactor; im2[ch] = inIm[1 - ch][slot][bin] * switchOrderFactor; } @@ -3775,14 +4423,14 @@ static void formulate2x2MixingMatrix( const float regularizationFactor ) { /* - This function implements a 2x2 solution for an optimized spatial audio rendering algorithm - Vilkamo, J., Bäckström, T. and Kuntz, A., 2013. - "Optimized covariance domain framework for time–frequency processing of spatial audio." - Journal of the Audio Engineering Society, 61(6), pp.403-411. - - The result of the formulas below are the same as those in the publication, however, some - derivation details differ for as simple as possible 2x2 formulattion - */ + This function implements a 2x2 solution for an optimized spatial audio rendering algorithm + Vilkamo, J., Bäckström, T. and Kuntz, A., 2013. + "Optimized covariance domain framework for time–frequency processing of spatial audio." + Journal of the Audio Engineering Society, 61(6), pp.403-411. + + The result of the formulas below are the same as those in the publication, however, some + derivation details differ for as simple as possible 2x2 formulattion + */ int16_t chA, chB; float maxEne, maxEneDiv; float KyRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; @@ -3876,7 +4524,7 @@ static void formulate2x2MixingMatrix( matrixMul( tmpRe, tmpIm, Kxre, Kxim, Are, Aim ); /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx - For matrix A that is P = A(A'A)^0.5 + For matrix A that is P = A(A'A)^0.5 */ matrixTransp1Mul( Are, Aim, Are, Aim, tmpRe, tmpIm ); @@ -3916,6 +4564,145 @@ static void formulate2x2MixingMatrix( } +#ifdef IVAS_FLOAT_FIXED +static void getDirectPartGains_fx( + const Word16 bin, + Word16 aziDeg, + Word16 eleDeg, + Word32 *lRealp, + Word32 *lImagp, + Word32 *rRealp, + Word32 *rImagp, + const UWord8 renderStereoOutputInsteadOfBinaural, + Word32 Rmat[3][3], + PARAMBIN_HRTF_GAIN_CACHE *gainCache, + const Word16 isHeadtracked ) +{ + // float aziRad, eleRad; + Word32 y, mappedX; + Word16 aziRadMapped, A, A2, A3; + const Word16 LsAngleRad = 17157; // Q15 + Word32 *ptr_sin, *ptr_cos; + Word32 sin_val, cos_val; + Word16 e_mappedX; + + ptr_sin = &sine_table_Q31[180]; // sin[x] = sine_table_Q31[180 + x] + ptr_cos = cosine_table_Q31; + + IF( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */ + { + /* Convert azi and ele to an azi value of the cone of confusion */ + + // y = ( sinf( aziRad ) * cosf( eleRad ) ); + + IF( GT_16( abs_s( eleDeg ), 180 ) ) + { + // cos(180 + x) = -cos(x) + cos_val = -ptr_cos[sub( abs_s( eleDeg ), 180 )]; // Q31 + } + ELSE + { + cos_val = ptr_cos[abs_s( eleDeg )]; // Q31 + } + + IF( GT_16( aziDeg, 180 ) ) + { + // sin(180 + x) = -sin(x) + sin_val = -ptr_sin[sub( aziDeg, 180 )]; // Q31 + } + ELSE IF( LT_16( aziDeg, -180 ) ) + { + // sin(-(180 + x)) = sin(180 + x) = sinx + sin_val = ptr_sin[sub( abs_s( aziDeg ), 180 )]; // Q31 + } + ELSE + { + sin_val = ptr_sin[aziDeg]; // Q31 + } + + y = Mpy_32_32( sin_val, cos_val ); // Q31 + e_mappedX = 0; + mappedX = Sqrt32( L_max( 0, L_sub( ONE_IN_Q31, Mpy_32_32( y, y ) ) ), &e_mappedX ); + + aziRadMapped = BASOP_util_atan2( y, mappedX, negate(e_mappedX) ); // Q13 + + /* Determine the real valued amplitude panning gains */ + *lImagp = 0; + *rImagp = 0; + IF( GE_16( aziRadMapped, shr( LsAngleRad, 2 ) ) ) + { /* Left side */ + *lRealp = ONE_IN_Q31; + *rRealp = 0; + } + ELSE IF( LE_16( aziRadMapped, negate(shr( LsAngleRad, 2 )) ) ) + { /* Right side */ + *lRealp = 0; + *rRealp = ONE_IN_Q31; + } + ELSE /* Tangent panning law */ + { + Word16 e_div, div, e_a, e_a3, temp_16_1, temp_16_2, e_num, e_den; + div = BASOP_Util_Divide3232_Scale( y, mappedX, &e_div ); + e_div = e_div - e_mappedX; + + A = mult( div, INV_TAN30_FX ); + e_a = e_div + 1; + + e_num = BASOP_Util_Add_MantExp( A, e_a, -32767, 0, &temp_16_1 ); + e_den = BASOP_Util_Add_MantExp( A, e_a, 32767, 0, &temp_16_2 ); + IF( LE_16( temp_16_2, 0 ) ) + { + temp_16_2 = 32; + e_den = 0; + } + A2 = BASOP_Util_Divide1616_Scale( temp_16_1, temp_16_2, &e_div ); + e_div = e_div + sub( e_num, e_den ); + + e_den = BASOP_Util_Add_MantExp( mult( A2, A2 ), add( e_div, e_div ), 32767, 0, &temp_16_2 ); + A3 = BASOP_Util_Divide1616_Scale( 32767, temp_16_2, &e_a3 ); + e_a3 = e_a3 - e_den; + // A3 = 1.0f / ( A2 * A2 + 1.0f ); // Q15 + Word32 temp_32 = L_shr( L_deposit_h( A3 ), sub( 0, e_a3 ) ); + Word16 temp_e = 0; + e_a3 = 0; + *lRealp = Sqrt32( temp_32, &e_a3 ); + *rRealp = Sqrt32( L_sub( ONE_IN_Q31, temp_32 ), &temp_e ); + *lRealp = L_shr( *lRealp, sub( 0, e_a3 ) ); // Q31 + *rRealp = L_shr( *rRealp, sub( 0, temp_e ) ); // Q31 + } + + /* Scaling to have the same expected gain as for the HRTF rendering */ + *lRealp = Mpy_32_32( *lRealp, SQRT2_FIXED ); // Q30 + *rRealp = Mpy_32_32( *rRealp, SQRT2_FIXED ); // Q30 + + *lRealp = L_shr( *lRealp, 2 ); // Q28 + *rRealp = L_shr( *rRealp, 2 ); // Q28 + } + ELSE /* In regular binaural rendering mode */ + { + IF( EQ_16( aziDeg, gainCache->azi ) && EQ_16( eleDeg, gainCache->ele ) ) + { + hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE ); + } + ELSE + { + gainCache->azi = aziDeg; + gainCache->ele = eleDeg; + IF( isHeadtracked ) + { + // Word32 aziDeg_32, eleDeg_32; + rotateAziEle_fx( aziDeg, eleDeg, &aziDeg, &eleDeg, Rmat, 0 ); // need to be chnaged + // eleDeg = L_shr(eleDeg_32, 22); + // aziDeg = L_shr(aziDeg_32, 22); + } + hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE ); + } + } + + return; +} +#endif + static void getDirectPartGains( const int16_t bin, int16_t aziDeg, @@ -3990,6 +4777,65 @@ static void getDirectPartGains( } +#ifdef IVAS_FLOAT_FIXED +static void hrtfShGetHrtf_fx( + const Word16 bin, + const Word16 aziDeg, + const Word16 eleDeg, + Word32 *lRealp, + Word32 *lImagp, + Word32 *rRealp, + Word32 *rImagp, + PARAMBIN_HRTF_GAIN_CACHE *gainCache, + const Word16 useCachedValue ) +{ + Word16 k; + + *lRealp = 0; + *lImagp = 0; + *rRealp = 0; + *rImagp = 0; + + IF( useCachedValue ) + { + Word32 *shVec; + shVec = gainCache->shVec_fx; + + FOR( k = 0; k < HRTF_SH_CHANNELS; k++ ) + { + + *lRealp = L_add( *lRealp, L_shr( Mpy_32_16_1( shVec[k], hrtfShCoeffsRe_fx[0][k][bin] ), 1 ) ); // Q28 + *lImagp = L_add( *lImagp, Mpy_32_16_1( shVec[k], hrtfShCoeffsIm_fx[0][k][bin] ) ); // Q28 + *rRealp = L_add( *rRealp, L_shr( Mpy_32_16_1( shVec[k], hrtfShCoeffsRe_fx[1][k][bin] ), 1 ) ); // Q28 + *rImagp = L_add( *rImagp, Mpy_32_16_1( shVec[k], hrtfShCoeffsIm_fx[1][k][bin] ) ); // Q28 + } + } + ELSE + { + Word32 shVec[HRTF_SH_CHANNELS]; + + ivas_dirac_dec_get_response_fixed( aziDeg, + eleDeg, + shVec, + HRTF_SH_ORDER ); + + FOR( k = 0; k < HRTF_SH_CHANNELS; k++ ) + { + + *lRealp = L_add( *lRealp, L_shr( Mpy_32_16_1( shVec[k], hrtfShCoeffsRe_fx[0][k][bin] ), 1 ) ); // Q28 + *lImagp = L_add( *lImagp, Mpy_32_16_1( shVec[k], hrtfShCoeffsIm_fx[0][k][bin] ) ); // Q28 + *rRealp = L_add( *rRealp, L_shr( Mpy_32_16_1( shVec[k], hrtfShCoeffsRe_fx[1][k][bin] ), 1 ) ); // Q28 + + *rImagp = L_add( *rImagp, Mpy_32_16_1( shVec[k], hrtfShCoeffsIm_fx[1][k][bin] ) ); // Q28 + + gainCache->shVec_fx[k] = shVec[k]; // Q29 + } + } + + return; +} +#endif + static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, @@ -4117,31 +4963,31 @@ float configure_reqularization_factor( #ifdef IVAS_FLOAT_FIXED Word16 configure_reqularization_factor_fx( const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const Word32 ivas_total_brate /* i : IVAS total bitrate */ + const Word32 ivas_total_brate /* i : IVAS total bitrate */ ) { Word16 reqularizationFactor; reqularizationFactor = 16384; /* Default value */ move16(); - IF ( EQ_32( ivas_format, MASA_FORMAT ) ) + IF( EQ_32( ivas_format, MASA_FORMAT ) ) { - IF ( GE_32( ivas_total_brate, IVAS_160k ) ) + IF( GE_32( ivas_total_brate, IVAS_160k ) ) { reqularizationFactor = 6553; move16(); } - ELSE IF ( EQ_32( ivas_total_brate, IVAS_128k ) ) + ELSE IF( EQ_32( ivas_total_brate, IVAS_128k ) ) { reqularizationFactor = 8192; move16(); } - ELSE IF ( EQ_32( ivas_total_brate, IVAS_96k ) ) + ELSE IF( EQ_32( ivas_total_brate, IVAS_96k ) ) { reqularizationFactor = 9830; move16(); } - ELSE IF ( GE_32( ivas_total_brate, IVAS_64k ) ) + ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) ) { reqularizationFactor = 13107; move16(); @@ -4153,24 +4999,24 @@ Word16 configure_reqularization_factor_fx( } } - IF ( EQ_32( ivas_format, MC_FORMAT ) ) /* This is always McMASA for parametric binauralizer. */ + IF( EQ_32( ivas_format, MC_FORMAT ) ) /* This is always McMASA for parametric binauralizer. */ { - IF ( GE_32( ivas_total_brate, IVAS_96k ) ) + IF( GE_32( ivas_total_brate, IVAS_96k ) ) { reqularizationFactor = 6553; move16(); } - ELSE IF ( GE_32( ivas_total_brate, IVAS_80k ) ) + ELSE IF( GE_32( ivas_total_brate, IVAS_80k ) ) { reqularizationFactor = 8192; move16(); } - ELSE IF ( GE_32( ivas_total_brate, IVAS_64k ) ) + ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) ) { reqularizationFactor = 11468; move16(); } - ELSE IF ( GE_32( ivas_total_brate, IVAS_48k ) ) + ELSE IF( GE_32( ivas_total_brate, IVAS_48k ) ) { reqularizationFactor = 13107; move16(); @@ -4477,325 +5323,702 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( move32(); } } - - /* IIR average the energy measures and determine and apply energy-preserving equalizer */ - hMasaIsmData->preprocEneTarget_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneTarget_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); - move32(); - hMasaIsmData->preprocEneRealized_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneRealized_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); - move32(); - FOR( ch = 0; ch < 2; ch++ ) + + /* IIR average the energy measures and determine and apply energy-preserving equalizer */ + hMasaIsmData->preprocEneTarget_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneTarget_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); + move32(); + hMasaIsmData->preprocEneRealized_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneRealized_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); + move32(); + FOR( ch = 0; ch < 2; ch++ ) + { + hMasaIsmData->preprocEneTarget_fx[bin] = L_add( hMasaIsmData->preprocEneTarget_fx[bin], Madd_32_32( Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ), inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = -19 + move32(); + hMasaIsmData->preprocEneRealized_fx[bin] = L_add( hMasaIsmData->preprocEneRealized_fx[bin], Madd_32_32( Mpy_32_32( outSlotRe_fx[ch], outSlotRe_fx[ch] ), outSlotIm_fx[ch], outSlotIm_fx[ch] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = -19 + move32(); + } + temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->preprocEneTarget_fx[bin], L_max( EPSILON_FX, hMasaIsmData->preprocEneRealized_fx[bin] ), &eqVal_q_fx ); + eqVal_fx = Sqrt16( temp1, &eqVal_q_fx ); + temp1 = shl( 4, Q12 ); + IF( LT_16( eqVal_q_fx, Q12 ) ) + { + IF( GT_16( eqVal_fx, shr( temp1, sub( Q12, eqVal_q_fx ) ) ) ) + { + eqVal_fx = temp1; + move16(); + eqVal_q_fx = Q12; + move16(); + } + } + ELSE + { + IF( GT_16( shr( eqVal_fx, sub( eqVal_q_fx, Q12 ) ), temp1 ) ) + { + eqVal_fx = temp1; + move16(); + } + } + + FOR( ch = 0; ch < 2; ch++ ) + { + inRe_fx[ch][slot][bin] = Mpy_32_16_1( outSlotRe_fx[ch], eqVal_fx ); + move32(); + inIm_fx[ch][slot][bin] = Mpy_32_16_1( outSlotIm_fx[ch], eqVal_fx ); + move32(); + } + *cldfb_buf_q = sub( add( *cldfb_buf_q, eqVal_q_fx ), 15 ); + } + } + + return; +} +#endif +/*-------------------------------------------------------------------* + * ivas_omasa_preProcessStereoTransportsForMovedObjects() + * + * + *-------------------------------------------------------------------*/ + +void ivas_omasa_preProcessStereoTransportsForMovedObjects( + Decoder_Struct *st_ivas, + float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const int16_t nBins, + const int16_t subframe ) +{ + int16_t bin, ch, inCh, outCh, ismDirIndex, slot; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + MASA_ISM_DATA_HANDLE hMasaIsmData; + uint8_t enableCentering; + int16_t dirac_read_idx; + int16_t nSlots; + + hSpatParamRendCom = st_ivas->hSpatParamRendCom; + hMasaIsmData = st_ivas->hMasaIsmData; + + if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA3 ) + { + enableCentering = 0; + } + else + { + enableCentering = 1; + } + + /* Bypass processing until first object is moved */ + if ( hMasaIsmData->objectsMoved == 0 ) + { + for ( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ ) + { + if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) + { + hMasaIsmData->objectsMoved = 1; + } + } + if ( hMasaIsmData->objectsMoved == 0 ) + { + /* No objects have moved so far */ + return; + } + } + + /* Perform object-movement based processing */ + nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + + for ( bin = 0; bin < nBins; bin++ ) + { + float ismPreprocMtxNew[2][2]; + float ismPreprocMtxIncrement[2][2]; + float eneMove[2]; + float enePreserve[2]; + float ismRatioAcc; + float subframeEne; + float normEnes[2]; + float remainderNormEne; + + set_zero( ismPreprocMtxNew[0], 2 ); + set_zero( ismPreprocMtxNew[1], 2 ); + set_zero( ismPreprocMtxIncrement[0], 2 ); + set_zero( ismPreprocMtxIncrement[1], 2 ); + set_zero( eneMove, 2 ); + set_zero( enePreserve, 2 ); + ismRatioAcc = 0.0f; + subframeEne = 0.0f; + set_zero( normEnes, 2 ); + + /* Determine transport normalized energies and subframe energy */ + for ( slot = 0; slot < nSlots; slot++ ) + { + for ( ch = 0; ch < 2; ch++ ) + { + normEnes[ch] += inRe[ch][slot][bin] * inRe[ch][slot][bin]; + normEnes[ch] += inIm[ch][slot][bin] * inIm[ch][slot][bin]; + } + } + subframeEne = normEnes[0] + normEnes[1]; + normEnes[0] /= fmaxf( 1e-12f, subframeEne ); + normEnes[1] /= fmaxf( 1e-12f, subframeEne ); + + /* For each ismDir, formulate a mix-matrix that moves object audio signals between + * left and right channels when needed. Make a combined matrix by a ratio-weighted sum */ + for ( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ ) + { + float panGainsOut[2]; + float panGainsIn[2]; +#ifdef IVAS_FLOAT_FIXED + Word16 panGainsOut_fx[2]; + Word16 panGainsIn_fx[2]; +#endif + float ratio_float; + float panEnesOut[2]; + float panEnesIn[2]; + float centeringFactor; + + ratio_float = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin]; + + ismRatioAcc += ratio_float; + + /* Get input and output panning gains */ +#ifdef IVAS_FLOAT_FIXED + ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx], + hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx], + panGainsIn_fx ); + panGainsIn[0] = (float) panGainsIn_fx[0] / 32767; + panGainsIn[1] = (float) panGainsIn_fx[1] / 32767; +#else + ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx], + hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx], + panGainsIn ); +#endif + + if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) + { +#ifdef IVAS_FLOAT_FIXED + ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism_edited[ismDirIndex], + hMasaIsmData->elevation_ism_edited[ismDirIndex], + panGainsOut_fx ); + panGainsOut[0] = (float) panGainsOut_fx[0] / 32767; + panGainsOut[1] = (float) panGainsOut_fx[1] / 32767; +#else + ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism_edited[ismDirIndex], + hMasaIsmData->elevation_ism_edited[ismDirIndex], + panGainsOut ); +#endif + } + else + { + /* When not edited, input and output pan gains are the same */ + for ( ch = 0; ch < 2; ch++ ) + { + panGainsOut[ch] = panGainsIn[ch]; + } + } + + /* Determine pan enes */ + for ( ch = 0; ch < 2; ch++ ) + { + panEnesOut[ch] = panGainsOut[ch] * panGainsOut[ch]; + panEnesIn[ch] = panGainsIn[ch] * panGainsIn[ch]; + } + + if ( enableCentering ) + { + centeringFactor = fmaxf( 0.0f, 2.0f * fabsf( panEnesIn[0] - panEnesOut[0] ) - 1.0f ); + for ( ch = 0; ch < 2; ch++ ) + { + panEnesOut[ch] *= ( 1.0f - centeringFactor ); + panEnesOut[ch] += 0.5f * centeringFactor; + } + } + + for ( ch = 0; ch < 2; ch++ ) + { + float eneMoveThis; + float enePreserveThis; + eneMoveThis = fmaxf( 0.0f, panEnesIn[ch] - panEnesOut[ch] ); + enePreserveThis = panEnesIn[ch] - eneMoveThis; + + eneMove[ch] += ratio_float * eneMoveThis; + enePreserve[ch] += ratio_float * enePreserveThis; + + /* Subtract object parts from normEnes */ + normEnes[ch] -= panEnesIn[ch] * ratio_float; + } + } + + /* Any remaining (non-object) energy is set to be preserved at both channels */ + remainderNormEne = fmaxf( 0.0f, ( 1.0f - ismRatioAcc ) - normEnes[0] - normEnes[1] ); + for ( ch = 0; ch < 2; ch++ ) + { + enePreserve[ch] += fmaxf( 0.0f, normEnes[ch] + remainderNormEne / 2.0f ); + } + + /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix */ + for ( ch = 0; ch < 2; ch++ ) + { + float normVal; + hMasaIsmData->eneMoveIIR[ch][bin] *= STEREO_PREPROCESS_IIR_FACTOR; + hMasaIsmData->eneMoveIIR[ch][bin] += eneMove[ch] * subframeEne; + hMasaIsmData->enePreserveIIR[ch][bin] *= STEREO_PREPROCESS_IIR_FACTOR; + hMasaIsmData->enePreserveIIR[ch][bin] += enePreserve[ch] * subframeEne; + normVal = fmaxf( EPSILON, hMasaIsmData->eneMoveIIR[ch][bin] + hMasaIsmData->enePreserveIIR[ch][bin] ); + ismPreprocMtxNew[ch][ch] = sqrtf( hMasaIsmData->enePreserveIIR[ch][bin] / normVal ); + ismPreprocMtxNew[1 - ch][ch] = sqrtf( hMasaIsmData->eneMoveIIR[ch][bin] / normVal ); + } + + /* Get increment value for temporal interpolation */ + for ( inCh = 0; inCh < 2; inCh++ ) + { + for ( outCh = 0; outCh < 2; outCh++ ) + { + ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin] ) / (float) nSlots; + } + } + + /* Mix signals */ + for ( slot = 0; slot < nSlots; slot++ ) + { + float eqVal; + float outSlotRe[2]; + float outSlotIm[2]; + + set_zero( outSlotRe, 2 ); + set_zero( outSlotIm, 2 ); + + for ( outCh = 0; outCh < 2; outCh++ ) + { + for ( inCh = 0; inCh < 2; inCh++ ) + { + hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin] += ismPreprocMtxIncrement[outCh][inCh]; + outSlotRe[outCh] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin]; + outSlotIm[outCh] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin]; + } + } + + /* IIR average the energy measures and determine and apply energy-preserving equalizer */ + hMasaIsmData->preprocEneTarget[bin] *= STEREO_PREPROCESS_IIR_FACTOR; + hMasaIsmData->preprocEneRealized[bin] *= STEREO_PREPROCESS_IIR_FACTOR; + for ( ch = 0; ch < 2; ch++ ) + { + hMasaIsmData->preprocEneTarget[bin] += inRe[ch][slot][bin] * inRe[ch][slot][bin]; + hMasaIsmData->preprocEneTarget[bin] += inIm[ch][slot][bin] * inIm[ch][slot][bin]; + hMasaIsmData->preprocEneRealized[bin] += outSlotRe[ch] * outSlotRe[ch]; + hMasaIsmData->preprocEneRealized[bin] += outSlotIm[ch] * outSlotIm[ch]; + } + eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[bin] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[bin] ) ) ); + for ( ch = 0; ch < 2; ch++ ) + { + inRe[ch][slot][bin] = outSlotRe[ch] * eqVal; + inIm[ch][slot][bin] = outSlotIm[ch] * eqVal; + } + } + } + + return; +} + +#ifndef IVAS_FLOAT_FIXED +static void ivas_masa_ext_rend_parambin_internal( + MASA_EXT_REND_HANDLE hMasaExtRend, + COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, + float *output_f[], + const int16_t subframe ) +{ + DIRAC_DEC_BIN_HANDLE hDiracDecBin; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + PARAMBIN_REND_CONFIG config_data; + int16_t slot, ch, numInChannels; + float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Rmat[3][3]; + int16_t max_band_decorr; + int16_t nBins; + int16_t i, j; + int16_t nchan_transport; + +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[MAX_OUTPUT_CHANNELS]; + Word32 output_fx_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 Rmat_fx[3][3]; +#endif + + hDiracDecBin = hMasaExtRend->hDiracDecBin; + assert( hDiracDecBin ); + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; + nBins = hSpatParamRendCom->num_freq_bands; + + /* Setup internal config. MASA EXT renderer is quite strict. */ + config_data.separateCenterChannelRendering = 0; + config_data.ivas_format = MASA_FORMAT; + config_data.mc_mode = MC_MODE_NONE; + config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */ + config_data.nchan_transport = hMasaExtRend->nchan_input; + config_data.qualityBasedSmFactor = 1.0f; + config_data.processReverb = hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0; + config_data.ism_mode = ISM_MODE_NONE; + + /* Set nchan_transport to number of transport channels in MASA input */ + nchan_transport = hMasaExtRend->nchan_input; + + /* The input channel number at this processing function (not nchan_transport) */ + numInChannels = BINAURAL_CHANNELS; +#ifdef IVAS_FLOAT_FIXED + Rmat_fx[0][0] = ONE_IN_Q31; + move32(); + Rmat_fx[0][1] = 0; + move32(); + Rmat_fx[0][2] = 0; + move32(); + + Rmat_fx[1][0] = 0; + move32(); + Rmat_fx[1][1] = ONE_IN_Q31; + move32(); + Rmat_fx[1][2] = 0; + move32(); + + Rmat_fx[2][0] = 0; + move32(); + Rmat_fx[2][1] = 0; + move32(); + Rmat_fx[2][2] = ONE_IN_Q31; + move32(); +#endif + Rmat[0][0] = 1.0f; + Rmat[0][1] = 0.0f; + Rmat[0][2] = 0.0f; + + Rmat[1][0] = 0.0f; + Rmat[1][1] = 1.0f; + Rmat[1][2] = 0.0f; + + Rmat[2][0] = 0.0f; + Rmat[2][1] = 0.0f; + Rmat[2][2] = 1.0f; + + /* CLDFB Analysis of input */ + for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + { + for ( ch = 0; ch < numInChannels; ch++ ) + { + if ( ch == 0 || nchan_transport == 2 ) + { + cldfbAnalysis_ts_ivas( + &( output_f[ch][nBins * slot] ), + Cldfb_RealBuffer_in[ch][slot], + Cldfb_ImagBuffer_in[ch][slot], + nBins, hMasaExtRend->cldfbAnaRend[ch] ); + } + else /* when nchan_transport == 1 and ch == 1 */ { - hMasaIsmData->preprocEneTarget_fx[bin] = L_add( hMasaIsmData->preprocEneTarget_fx[bin], Madd_32_32( Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ), inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = -19 - move32(); - hMasaIsmData->preprocEneRealized_fx[bin] = L_add( hMasaIsmData->preprocEneRealized_fx[bin], Madd_32_32( Mpy_32_32( outSlotRe_fx[ch], outSlotRe_fx[ch] ), outSlotIm_fx[ch], outSlotIm_fx[ch] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = -19 - move32(); + /* At mono input duplicate the channel to dual-mono, and apply gain + correction to ensure same overall level as in stereo mode */ + v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins ); + v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins ); + + mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins ); + mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins ); } - temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->preprocEneTarget_fx[bin], L_max( EPSILON_FX, hMasaIsmData->preprocEneRealized_fx[bin] ), &eqVal_q_fx ); - eqVal_fx = Sqrt16( temp1, &eqVal_q_fx ); - temp1 = shl( 4, Q12 ); - IF( LT_16( eqVal_q_fx, Q12 ) ) + } + } + + Word16 q_inp = Q6; + if ( hCombinedOrientationData ) + { + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < 3; j++ ) { - IF( GT_16( eqVal_fx, shr( temp1, sub( Q12, eqVal_q_fx ) ) ) ) - { - eqVal_fx = temp1; - move16(); - eqVal_q_fx = Q12; - move16(); - } +#ifdef IVAS_FLOAT_FIXED + Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30// +#endif + Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j]; } - ELSE + } + + IF( EQ_16( nchan_transport, 2 ) ) + { +#ifdef IVAS_FLOAT_FIXED + FOR( Word16 cha = 0; cha < 2; cha++ ) + FOR( slot = 0; slot < 4; slot++ ) + FOR( Word16 ind = 0; ind < 60; ind++ ) { - IF( GT_16( shr( eqVal_fx, sub( eqVal_q_fx, Q12 ) ), temp1 ) ) - { - eqVal_fx = temp1; - move16(); - } + Cldfb_RealBuffer_in_fx[cha][slot][ind] = float_to_fix( Cldfb_RealBuffer_in[cha][slot][ind], q_inp ); + Cldfb_ImagBuffer_in_fx[cha][slot][ind] = float_to_fix( Cldfb_ImagBuffer_in[cha][slot][ind], q_inp ); } + adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); - FOR( ch = 0; ch < 2; ch++ ) + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); + FOR( Word16 cha = 0; cha < 2; cha++ ) + FOR( slot = 0; slot < 4; slot++ ) + FOR( Word16 ind = 0; ind < 60; ind++ ) { - inRe_fx[ch][slot][bin] = Mpy_32_16_1( outSlotRe_fx[ch], eqVal_fx ); - move32(); - inIm_fx[ch][slot][bin] = Mpy_32_16_1( outSlotIm_fx[ch], eqVal_fx ); - move32(); + Cldfb_RealBuffer_in[cha][slot][ind] = fix_to_float( Cldfb_RealBuffer_in_fx[cha][slot][ind], q_inp ); + Cldfb_ImagBuffer_in[cha][slot][ind] = fix_to_float( Cldfb_ImagBuffer_in_fx[cha][slot][ind], q_inp ); } - *cldfb_buf_q = sub( add( *cldfb_buf_q, eqVal_q_fx ), 15 ); - } - } +#else + adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat ); - return; -} + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat ); #endif -/*-------------------------------------------------------------------* - * ivas_omasa_preProcessStereoTransportsForMovedObjects() - * - * - *-------------------------------------------------------------------*/ - -void ivas_omasa_preProcessStereoTransportsForMovedObjects( - Decoder_Struct *st_ivas, - float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - const int16_t nBins, - const int16_t subframe ) -{ - int16_t bin, ch, inCh, outCh, ismDirIndex, slot; - SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; - MASA_ISM_DATA_HANDLE hMasaIsmData; - uint8_t enableCentering; - int16_t dirac_read_idx; - int16_t nSlots; - - hSpatParamRendCom = st_ivas->hSpatParamRendCom; - hMasaIsmData = st_ivas->hMasaIsmData; + } + } - if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA3 ) +#ifdef IVAS_FLOAT_FIXED +#if 1 + Word16 q_earlyPartEneCorrection = Q_factor_arrL( hDiracDecBin->earlyPartEneCorrection, hSpatParamRendCom->num_freq_bands ); + hDiracDecBin->q_earlyPartEneCorrection = q_earlyPartEneCorrection; + floatToFixed_arr32( hDiracDecBin->earlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection_fx, q_earlyPartEneCorrection, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherence, hDiracDecBin->diffuseFieldCoherence_fx, Q31, hSpatParamRendCom->num_freq_bands ); + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { - enableCentering = 0; + f2me( hDiracDecBin->ChCrossRePrev[j], &hDiracDecBin->ChCrossRePrev_fx[j], &hDiracDecBin->ChCrossRePrev_e[j] ); + f2me( hDiracDecBin->ChCrossImPrev[j], &hDiracDecBin->ChCrossImPrev_fx[j], &hDiracDecBin->ChCrossImPrev_e[j] ); + f2me( hDiracDecBin->ChCrossReOutPrev[j], &hDiracDecBin->ChCrossReOutPrev_fx[j], &hDiracDecBin->ChCrossReOutPrev_e[j] ); + f2me( hDiracDecBin->ChCrossImOutPrev[j], &hDiracDecBin->ChCrossImOutPrev_fx[j], &hDiracDecBin->ChCrossImOutPrev_e[j] ); + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + f2me( hDiracDecBin->ChEnePrev[i][j], &hDiracDecBin->ChEnePrev_fx[i][j], &hDiracDecBin->ChEnePrev_e[i][j] ); + f2me( hDiracDecBin->ChEneOutPrev[i][j], &hDiracDecBin->ChEneOutPrev_fx[i][j], &hDiracDecBin->ChEneOutPrev_e[i][j] ); + } } - else + FOR( i = 0; i < hSpatParamRendCom->dirac_md_buffer_length; i++ ) { - enableCentering = 1; + IF( hSpatParamRendCom->energy_ratio1 ) + floatToFixed_arrL32( hSpatParamRendCom->energy_ratio1[i], hSpatParamRendCom->energy_ratio1_fx[i], Q30, hSpatParamRendCom->num_freq_bands ); + IF( hSpatParamRendCom->energy_ratio2 ) + floatToFixed_arrL32( hSpatParamRendCom->energy_ratio2[i], hSpatParamRendCom->energy_ratio2_fx[i], Q30, hSpatParamRendCom->num_freq_bands ); } - - /* Bypass processing until first object is moved */ - if ( hMasaIsmData->objectsMoved == 0 ) + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherence, hDiracDecBin->diffuseFieldCoherence_fx, 31, hSpatParamRendCom->num_freq_bands ); + IF( hDiracDecBin->hDiffuseDist ) { - for ( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ ) - { - if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) - { - hMasaIsmData->objectsMoved = 1; - } - } - if ( hMasaIsmData->objectsMoved == 0 ) + floatToFixed_arr32( hDiracDecBin->hDiffuseDist->diffuseRatioX, hDiracDecBin->hDiffuseDist->diffuseRatioX_fx, 31, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceX, hDiracDecBin->diffuseFieldCoherenceX_fx, 31, 9 ); + floatToFixed_arr32( hDiracDecBin->hDiffuseDist->diffuseRatioY, hDiracDecBin->hDiffuseDist->diffuseRatioY_fx, 31, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceY, hDiracDecBin->diffuseFieldCoherenceY_fx, 31, 9 ); + floatToFixed_arr32( hDiracDecBin->hDiffuseDist->diffuseRatioZ, hDiracDecBin->hDiffuseDist->diffuseRatioZ_fx, 31, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceZ, hDiracDecBin->diffuseFieldCoherenceZ_fx, 31, 9 ); + } + config_data.qualityBasedSmFactor_fx = (Word32) ( config_data.qualityBasedSmFactor * ONE_IN_Q31 ); +#endif + Word16 shift = 31; + Word32 Cldfb_RealBuffer_inTmp_fx[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Cldfb_ImagBuffer_inTmp_fx[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 4; j++ ) { - /* No objects have moved so far */ - return; + shift = s_min(shift, getScaleFactor32(Cldfb_RealBuffer_in_fx[i][j], CLDFB_NO_CHANNELS_MAX)); + shift = s_min(shift, getScaleFactor32(Cldfb_ImagBuffer_in_fx[i][j], CLDFB_NO_CHANNELS_MAX)); } } - /* Perform object-movement based processing */ - nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; - dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + Word16 q = q_inp + shift; - for ( bin = 0; bin < nBins; bin++ ) + FOR( i = 0; i < 2; i++ ) { - float ismPreprocMtxNew[2][2]; - float ismPreprocMtxIncrement[2][2]; - float eneMove[2]; - float enePreserve[2]; - float ismRatioAcc; - float subframeEne; - float normEnes[2]; - float remainderNormEne; - - set_zero( ismPreprocMtxNew[0], 2 ); - set_zero( ismPreprocMtxNew[1], 2 ); - set_zero( ismPreprocMtxIncrement[0], 2 ); - set_zero( ismPreprocMtxIncrement[1], 2 ); - set_zero( eneMove, 2 ); - set_zero( enePreserve, 2 ); - ismRatioAcc = 0.0f; - subframeEne = 0.0f; - set_zero( normEnes, 2 ); - - /* Determine transport normalized energies and subframe energy */ - for ( slot = 0; slot < nSlots; slot++ ) + FOR( j = 0; j < 4; j++ ) { - for ( ch = 0; ch < 2; ch++ ) + FOR( Word16 k = 0; k < 60; k++ ) { - normEnes[ch] += inRe[ch][slot][bin] * inRe[ch][slot][bin]; - normEnes[ch] += inIm[ch][slot][bin] * inIm[ch][slot][bin]; + Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); + Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); } } - subframeEne = normEnes[0] + normEnes[1]; - normEnes[0] /= fmaxf( 1e-12f, subframeEne ); - normEnes[1] /= fmaxf( 1e-12f, subframeEne ); + } - /* For each ismDir, formulate a mix-matrix that moves object audio signals between - * left and right channels when needed. Make a combined matrix by a ratio-weighted sum */ - for ( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ ) + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, Rmat_fx, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, NULL, q ); +#if 1 + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { - float panGainsOut[2]; - float panGainsIn[2]; -#ifdef IVAS_FLOAT_FIXED - Word16 panGainsOut_fx[2]; - Word16 panGainsIn_fx[2]; -#endif - float ratio_float; - float panEnesOut[2]; - float panEnesIn[2]; - float centeringFactor; - - ratio_float = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin]; + hDiracDecBin->ChEnePrev[i][j] = me2f( hDiracDecBin->ChEnePrev_fx[i][j], hDiracDecBin->ChEnePrev_e[i][j] ); + hDiracDecBin->ChEne[i][j] = me2f( hDiracDecBin->ChEne_fx[i][j], hDiracDecBin->ChEne_e[i][j] ); + hDiracDecBin->ChEneOut[i][j] = me2f( hDiracDecBin->ChEneOut_fx[i][j], hDiracDecBin->ChEneOut_e[i][j] ); + hDiracDecBin->ChEneOutPrev[i][j] = me2f( hDiracDecBin->ChEneOutPrev_fx[i][j], hDiracDecBin->ChEneOutPrev_e[i][j] ); + } + } - ismRatioAcc += ratio_float; + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hDiracDecBin->ChCrossRePrev[j] = me2f( hDiracDecBin->ChCrossRePrev_fx[j], hDiracDecBin->ChCrossRePrev_e[j] ); + hDiracDecBin->ChCrossImPrev[j] = me2f( hDiracDecBin->ChCrossImPrev_fx[j], hDiracDecBin->ChCrossImPrev_e[j] ); + hDiracDecBin->ChCrossRe[j] = me2f( hDiracDecBin->ChCrossRe_fx[j], hDiracDecBin->ChCrossRe_e[j] ); + hDiracDecBin->ChCrossIm[j] = me2f( hDiracDecBin->ChCrossIm_fx[j], hDiracDecBin->ChCrossIm_e[j] ); + hDiracDecBin->ChCrossReOut[j] = me2f( hDiracDecBin->ChCrossReOut_fx[j], hDiracDecBin->ChCrossReOut_e[j] ); + hDiracDecBin->ChCrossImOut[j] = me2f( hDiracDecBin->ChCrossImOut_fx[j], hDiracDecBin->ChCrossImOut_e[j] ); + hDiracDecBin->ChCrossReOutPrev[j] = me2f( hDiracDecBin->ChCrossReOutPrev_fx[j], hDiracDecBin->ChCrossReOutPrev_e[j] ); + hDiracDecBin->ChCrossImOutPrev[j] = me2f( hDiracDecBin->ChCrossImOutPrev_fx[j], hDiracDecBin->ChCrossImOutPrev_e[j] ); + } + fixedToFloat_arrL( hDiracDecBin->frameMeanDiffuseness_fx, hDiracDecBin->frameMeanDiffuseness, 29, CLDFB_NO_CHANNELS_MAX ); - /* Get input and output panning gains */ -#ifdef IVAS_FLOAT_FIXED - ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx], - hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx], - panGainsIn_fx ); - panGainsIn[0] = (float) panGainsIn_fx[0] / 32767; - panGainsIn[1] = (float) panGainsIn_fx[1] / 32767; -#else - ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx], - hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx], - panGainsIn ); #endif - if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) - { -#ifdef IVAS_FLOAT_FIXED - ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism_edited[ismDirIndex], - hMasaIsmData->elevation_ism_edited[ismDirIndex], - panGainsOut_fx ); - panGainsOut[0] = (float) panGainsOut_fx[0] / 32767; - panGainsOut[1] = (float) panGainsOut_fx[1] / 32767; #else - ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism_edited[ismDirIndex], - hMasaIsmData->elevation_ism_edited[ismDirIndex], - panGainsOut ); + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, NULL ); #endif - } - else - { - /* When not edited, input and output pan gains are the same */ - for ( ch = 0; ch < 2; ch++ ) - { - panGainsOut[ch] = panGainsIn[ch]; - } - } + /* Always using CLDFB decorrelation in MASA EXT renderer */ + max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr; - /* Determine pan enes */ - for ( ch = 0; ch < 2; ch++ ) - { - panEnesOut[ch] = panGainsOut[ch] * panGainsOut[ch]; - panEnesIn[ch] = panGainsIn[ch] * panGainsIn[ch]; - } - if ( enableCentering ) - { - centeringFactor = fmaxf( 0.0f, 2.0f * fabsf( panEnesIn[0] - panEnesOut[0] ) - 1.0f ); - for ( ch = 0; ch < 2; ch++ ) - { - panEnesOut[ch] *= ( 1.0f - centeringFactor ); - panEnesOut[ch] += 0.5f * centeringFactor; - } - } + ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, + 0, NULL ); - for ( ch = 0; ch < 2; ch++ ) - { - float eneMoveThis; - float enePreserveThis; - eneMoveThis = fmaxf( 0.0f, panEnesIn[ch] - panEnesOut[ch] ); - enePreserveThis = panEnesIn[ch] - eneMoveThis; - eneMove[ch] += ratio_float * eneMoveThis; - enePreserve[ch] += ratio_float * enePreserveThis; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /* Subtract object parts from normEnes */ - normEnes[ch] -= panEnesIn[ch] * ratio_float; - } +#ifdef IVAS_FLOAT_FIXED + Word16 q_out; + Word16 q_mat = 15; + q_inp = Q6; + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + output_fx[ch] = output_fx_buff[ch]; + } + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) + { + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxDecRe[ch][slot], nBins ) ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxDecIm[ch][slot], nBins ) ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxDecRePrev[ch][slot], nBins ) ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxDecImPrev[ch][slot], nBins ) ); } - - /* Any remaining (non-object) energy is set to be preserved at both channels */ - remainderNormEne = fmaxf( 0.0f, ( 1.0f - ismRatioAcc ) - normEnes[0] - normEnes[1] ); - for ( ch = 0; ch < 2; ch++ ) + } + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < numInChannels; slot++ ) { - enePreserve[ch] += fmaxf( 0.0f, normEnes[ch] + remainderNormEne / 2.0f ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxRe[ch][slot], nBins ) ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxIm[ch][slot], nBins ) ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxRePrev[ch][slot], nBins ) ); + q_mat = s_min( q_mat, Q_factor_arr( hDiracDecBin->processMtxImPrev[ch][slot], nBins ) ); } - - /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix */ - for ( ch = 0; ch < 2; ch++ ) + } + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + output_fx[ch] = output_fx_buff[ch]; + } + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) { - float normVal; - hMasaIsmData->eneMoveIIR[ch][bin] *= STEREO_PREPROCESS_IIR_FACTOR; - hMasaIsmData->eneMoveIIR[ch][bin] += eneMove[ch] * subframeEne; - hMasaIsmData->enePreserveIIR[ch][bin] *= STEREO_PREPROCESS_IIR_FACTOR; - hMasaIsmData->enePreserveIIR[ch][bin] += enePreserve[ch] * subframeEne; - normVal = fmaxf( EPSILON, hMasaIsmData->eneMoveIIR[ch][bin] + hMasaIsmData->enePreserveIIR[ch][bin] ); - ismPreprocMtxNew[ch][ch] = sqrtf( hMasaIsmData->enePreserveIIR[ch][bin] / normVal ); - ismPreprocMtxNew[1 - ch][ch] = sqrtf( hMasaIsmData->eneMoveIIR[ch][bin] / normVal ); + floatToFixed_arr16( hDiracDecBin->processMtxDecRe[ch][slot], hDiracDecBin->processMtxDecRe_fx[ch][slot], q_mat, nBins ); + floatToFixed_arr16( hDiracDecBin->processMtxDecIm[ch][slot], hDiracDecBin->processMtxDecIm_fx[ch][slot], q_mat, nBins ); + floatToFixed_arr16( hDiracDecBin->processMtxDecRePrev[ch][slot], hDiracDecBin->processMtxDecRePrev_fx[ch][slot], q_mat, nBins ); + floatToFixed_arr16( hDiracDecBin->processMtxDecImPrev[ch][slot], hDiracDecBin->processMtxDecImPrev_fx[ch][slot], q_mat, nBins ); } - - /* Get increment value for temporal interpolation */ - for ( inCh = 0; inCh < 2; inCh++ ) + } + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < numInChannels; slot++ ) { - for ( outCh = 0; outCh < 2; outCh++ ) - { - ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin] ) / (float) nSlots; - } + floatToFixed_arr16( hDiracDecBin->processMtxRe[ch][slot], hDiracDecBin->processMtxRe_fx[ch][slot], q_mat, nBins ); + floatToFixed_arr16( hDiracDecBin->processMtxIm[ch][slot], hDiracDecBin->processMtxIm_fx[ch][slot], q_mat, nBins ); + floatToFixed_arr16( hDiracDecBin->processMtxRePrev[ch][slot], hDiracDecBin->processMtxRePrev_fx[ch][slot], q_mat, nBins ); + floatToFixed_arr16( hDiracDecBin->processMtxImPrev[ch][slot], hDiracDecBin->processMtxImPrev_fx[ch][slot], q_mat, nBins ); } + floatToFixed_arrL( hMasaExtRend->cldfbSynRend[ch]->cldfb_state, hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, Q11, hMasaExtRend->cldfbSynRend[ch]->p_filter_length ); + hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11; + } + FOR( Word16 cha = 0; cha < 6; cha++ ) + FOR( slot = 0; slot < 4; slot++ ) + FOR( Word16 ind = 0; ind < 60; ind++ ) + { + Cldfb_RealBuffer_in_fx[cha][slot][ind] = floatToFixed( Cldfb_RealBuffer_in[cha][slot][ind], Q6 ); + Cldfb_ImagBuffer_in_fx[cha][slot][ind] = floatToFixed( Cldfb_ImagBuffer_in[cha][slot][ind], Q6 ); + } + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); - /* Mix signals */ - for ( slot = 0; slot < nSlots; slot++ ) - { - float eqVal; - float outSlotRe[2]; - float outSlotIm[2]; + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + fixedToFloat_arrL32( output_fx[ch], output_f[ch], q_out, nBins * hSpatParamRendCom->subframe_nbslots[subframe] ); + fixedToFloat_arrL32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_state, hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state, hMasaExtRend->cldfbSynRend[ch]->p_filter_length ); + } +#else + ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, config_data.processReverb, subframe ); +#endif + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - set_zero( outSlotRe, 2 ); - set_zero( outSlotIm, 2 ); - for ( outCh = 0; outCh < 2; outCh++ ) - { - for ( inCh = 0; inCh < 2; inCh++ ) - { - hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin] += ismPreprocMtxIncrement[outCh][inCh]; - outSlotRe[outCh] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin]; - outSlotIm[outCh] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][bin]; - } - } + hDiracDecBin->hDiffuseDist = NULL; - /* IIR average the energy measures and determine and apply energy-preserving equalizer */ - hMasaIsmData->preprocEneTarget[bin] *= STEREO_PREPROCESS_IIR_FACTOR; - hMasaIsmData->preprocEneRealized[bin] *= STEREO_PREPROCESS_IIR_FACTOR; - for ( ch = 0; ch < 2; ch++ ) - { - hMasaIsmData->preprocEneTarget[bin] += inRe[ch][slot][bin] * inRe[ch][slot][bin]; - hMasaIsmData->preprocEneTarget[bin] += inIm[ch][slot][bin] * inIm[ch][slot][bin]; - hMasaIsmData->preprocEneRealized[bin] += outSlotRe[ch] * outSlotRe[ch]; - hMasaIsmData->preprocEneRealized[bin] += outSlotIm[ch] * outSlotIm[ch]; - } - eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[bin] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[bin] ) ) ); - for ( ch = 0; ch < 2; ch++ ) - { - inRe[ch][slot][bin] = outSlotRe[ch] * eqVal; - inIm[ch][slot][bin] = outSlotIm[ch] * eqVal; - } - } - } + hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe]; + hSpatParamRendCom->subframes_rendered++; return; -} - + } +#else static void ivas_masa_ext_rend_parambin_internal( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], - const int16_t subframe ) + const Word16 subframe ) { + DIRAC_DEC_BIN_HANDLE hDiracDecBin; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; PARAMBIN_REND_CONFIG config_data; - int16_t slot, ch, numInChannels; - float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Rmat[3][3]; - int16_t max_band_decorr; - int16_t nBins; - int16_t i, j; - int16_t nchan_transport; + Word16 slot, ch, numInChannels; + Word16 max_band_decorr; + Word16 nBins; + Word16 i, j; + Word16 nchan_transport; -#ifdef IVAS_FLOAT_FIXED +#if 1 + hDiracDecBin = hMasaExtRend->hDiracDecBin; + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; Word32 *output_fx[MAX_OUTPUT_CHANNELS]; Word32 output_fx_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word16 q_earlyPartEneCorrection = Q_factor_arrL( hDiracDecBin->earlyPartEneCorrection, hSpatParamRendCom->num_freq_bands ); + hDiracDecBin->q_earlyPartEneCorrection = q_earlyPartEneCorrection; + floatToFixed_arr32( hDiracDecBin->earlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection_fx, q_earlyPartEneCorrection, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherence, hDiracDecBin->diffuseFieldCoherence_fx, Q31, hSpatParamRendCom->num_freq_bands ); + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + f2me( hDiracDecBin->ChCrossRePrev[j], &hDiracDecBin->ChCrossRePrev_fx[j], &hDiracDecBin->ChCrossRePrev_e[j] ); + f2me( hDiracDecBin->ChCrossImPrev[j], &hDiracDecBin->ChCrossImPrev_fx[j], &hDiracDecBin->ChCrossImPrev_e[j] ); + f2me( hDiracDecBin->ChCrossReOutPrev[j], &hDiracDecBin->ChCrossReOutPrev_fx[j], &hDiracDecBin->ChCrossReOutPrev_e[j] ); + f2me( hDiracDecBin->ChCrossImOutPrev[j], &hDiracDecBin->ChCrossImOutPrev_fx[j], &hDiracDecBin->ChCrossImOutPrev_e[j] ); + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + f2me( hDiracDecBin->ChEnePrev[i][j], &hDiracDecBin->ChEnePrev_fx[i][j], &hDiracDecBin->ChEnePrev_e[i][j] ); + f2me( hDiracDecBin->ChEneOutPrev[i][j], &hDiracDecBin->ChEneOutPrev_fx[i][j], &hDiracDecBin->ChEneOutPrev_e[i][j] ); + } + } + FOR( i = 0; i < hSpatParamRendCom->dirac_md_buffer_length; i++ ) + { + IF( hSpatParamRendCom->energy_ratio1 ) + floatToFixed_arrL32( hSpatParamRendCom->energy_ratio1[i], hSpatParamRendCom->energy_ratio1_fx[i], Q30, hSpatParamRendCom->num_freq_bands ); + IF( hSpatParamRendCom->energy_ratio2 ) + floatToFixed_arrL32( hSpatParamRendCom->energy_ratio2[i], hSpatParamRendCom->energy_ratio2_fx[i], Q30, hSpatParamRendCom->num_freq_bands ); + } + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherence, hDiracDecBin->diffuseFieldCoherence_fx, 31, hSpatParamRendCom->num_freq_bands ); + IF( hDiracDecBin->hDiffuseDist ) + { + floatToFixed_arr32( hDiracDecBin->hDiffuseDist->diffuseRatioX, hDiracDecBin->hDiffuseDist->diffuseRatioX_fx, 31, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceX, hDiracDecBin->diffuseFieldCoherenceX_fx, 31, 9 ); + floatToFixed_arr32( hDiracDecBin->hDiffuseDist->diffuseRatioY, hDiracDecBin->hDiffuseDist->diffuseRatioY_fx, 31, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceY, hDiracDecBin->diffuseFieldCoherenceY_fx, 31, 9 ); + floatToFixed_arr32( hDiracDecBin->hDiffuseDist->diffuseRatioZ, hDiracDecBin->hDiffuseDist->diffuseRatioZ_fx, 31, hSpatParamRendCom->num_freq_bands ); + floatToFixed_arr32( hDiracDecBin->diffuseFieldCoherenceZ, hDiracDecBin->diffuseFieldCoherenceZ_fx, 31, 9 ); + } + FOR( ch = 0; ch < 2; ch++) + { + output_fx[ch] = output_fx_buff[ch]; + floatToFixed_arrL32(output_f[ch], output_fx[ch], Q11, L_FRAME48k); + floatToFixed_arrL32(hMasaExtRend->cldfbAnaRend[ch]->cldfb_state, hMasaExtRend->cldfbAnaRend[ch]->cldfb_state_fx, Q11, hMasaExtRend->cldfbAnaRend[ch]->p_filter_length - hMasaExtRend->cldfbAnaRend[ch]->no_channels); + } +#endif + Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 Rmat_fx[3][3]; -#endif hDiracDecBin = hMasaExtRend->hDiracDecBin; assert( hDiracDecBin ); @@ -4804,141 +6027,163 @@ static void ivas_masa_ext_rend_parambin_internal( /* Setup internal config. MASA EXT renderer is quite strict. */ config_data.separateCenterChannelRendering = 0; + move16(); config_data.ivas_format = MASA_FORMAT; config_data.mc_mode = MC_MODE_NONE; config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */ + move32(); config_data.nchan_transport = hMasaExtRend->nchan_input; + move16(); config_data.qualityBasedSmFactor = 1.0f; + config_data.qualityBasedSmFactor_fx = ONE_IN_Q31; + move32(); config_data.processReverb = hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0; + move16(); config_data.ism_mode = ISM_MODE_NONE; /* Set nchan_transport to number of transport channels in MASA input */ nchan_transport = hMasaExtRend->nchan_input; + move16(); /* The input channel number at this processing function (not nchan_transport) */ numInChannels = BINAURAL_CHANNELS; -#ifdef IVAS_FLOAT_FIXED - Rmat_fx[0][0] = ONE_IN_Q31; - move32(); + move16(); + + Rmat_fx[0][0] = ONE_IN_Q30; Rmat_fx[0][1] = 0; - move32(); Rmat_fx[0][2] = 0; - move32(); + move32(); move32(); move32(); Rmat_fx[1][0] = 0; - move32(); - Rmat_fx[1][1] = ONE_IN_Q31; - move32(); + Rmat_fx[1][1] = ONE_IN_Q30; Rmat_fx[1][2] = 0; - move32(); + move32(); move32(); move32(); Rmat_fx[2][0] = 0; - move32(); Rmat_fx[2][1] = 0; - move32(); - Rmat_fx[2][2] = ONE_IN_Q31; - move32(); -#endif - Rmat[0][0] = 1.0f; - Rmat[0][1] = 0.0f; - Rmat[0][2] = 0.0f; - - Rmat[1][0] = 0.0f; - Rmat[1][1] = 1.0f; - Rmat[1][2] = 0.0f; - - Rmat[2][0] = 0.0f; - Rmat[2][1] = 0.0f; - Rmat[2][2] = 1.0f; + Rmat_fx[2][2] = ONE_IN_Q30; + move32(); move32(); move32(); /* CLDFB Analysis of input */ - for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + + Word16 q_cldfb = Q11; + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) { - for ( ch = 0; ch < numInChannels; ch++ ) + FOR( ch = 0; ch < numInChannels; ch++ ) { - if ( ch == 0 || nchan_transport == 2 ) + IF( EQ_16(ch, 0) || EQ_16(nchan_transport, 2) ) { - cldfbAnalysis_ts_ivas( - &( output_f[ch][nBins * slot] ), - Cldfb_RealBuffer_in[ch][slot], - Cldfb_ImagBuffer_in[ch][slot], - nBins, hMasaExtRend->cldfbAnaRend[ch] ); + cldfbAnalysis_ts_fx_fixed_q( + &( output_fx[ch][nBins * slot] ), + Cldfb_RealBuffer_in_fx[ch][slot], + Cldfb_ImagBuffer_in_fx[ch][slot], + nBins, hMasaExtRend->cldfbAnaRend[ch], &q_cldfb); } - else /* when nchan_transport == 1 and ch == 1 */ + ELSE /* when nchan_transport == 1 and ch == 1 */ { /* At mono input duplicate the channel to dual-mono, and apply gain correction to ensure same overall level as in stereo mode */ - v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins ); - v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins ); + v_multc_fixed( Cldfb_RealBuffer_in_fx[0][slot], 151800249 /* INV_SQRT_2 in Q31 */, Cldfb_RealBuffer_in_fx[0][slot], nBins ); + v_multc_fixed( Cldfb_ImagBuffer_in_fx[0][slot], 151800249 /* INV_SQRT_2 in Q31 */, Cldfb_ImagBuffer_in_fx[0][slot], nBins ); - mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins ); - mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins ); + mvl2l( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins ); + mvl2l( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins ); } } } - - if ( hCombinedOrientationData ) + Word16 q_inp = Q6; + IF ( hCombinedOrientationData ) { - for ( i = 0; i < 3; i++ ) + FOR ( i = 0; i < 3; i++ ) { - for ( j = 0; j < 3; j++ ) + FOR ( j = 0; j < 3; j++ ) { -#ifdef IVAS_FLOAT_FIXED - Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30// -#endif - Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j]; + Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30// } } - IF(EQ_16(nchan_transport, 2)) + IF( EQ_16( nchan_transport, 2 ) ) { -#ifdef IVAS_FLOAT_FIXED - Word16 q_inp = Q6; - FOR(Word16 cha = 0; cha < 2; cha++) - FOR(slot = 0; slot < 4; slot++) - FOR(Word16 ind = 0; ind < 60; ind++) - { - Cldfb_RealBuffer_in_fx[cha][slot][ind] = float_to_fix(Cldfb_RealBuffer_in[cha][slot][ind], q_inp); - Cldfb_ImagBuffer_in_fx[cha][slot][ind] = float_to_fix(Cldfb_ImagBuffer_in[cha][slot][ind], q_inp); - } - adaptTransportSignalsHeadtracked_fx(hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx); - - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx(hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx); - FOR(Word16 cha = 0; cha < 2; cha++) - FOR(slot = 0; slot < 4; slot++) - FOR(Word16 ind = 0; ind < 60; ind++) - { - Cldfb_RealBuffer_in[cha][slot][ind] = fix_to_float(Cldfb_RealBuffer_in_fx[cha][slot][ind], q_inp); - Cldfb_ImagBuffer_in[cha][slot][ind] = fix_to_float(Cldfb_ImagBuffer_in_fx[cha][slot][ind], q_inp); - } -#else - adaptTransportSignalsHeadtracked(hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat); + adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); + ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); + } + } - ivas_dirac_dec_binaural_check_and_switch_transports_headtracked(hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat); -#endif + Word16 shift = 31; + Word32 Cldfb_RealBuffer_inTmp_fx[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Cldfb_ImagBuffer_inTmp_fx[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + shift = s_min(shift, getScaleFactor32(Cldfb_RealBuffer_in_fx[i][j], CLDFB_NO_CHANNELS_MAX)); + shift = s_min(shift, getScaleFactor32(Cldfb_ImagBuffer_in_fx[i][j], CLDFB_NO_CHANNELS_MAX)); } } + Word16 q = q_inp + shift; - ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, Rmat, subframe, - hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, NULL ); + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + FOR( Word16 k = 0; k < 60; k++ ) + { + Cldfb_RealBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_RealBuffer_in_fx[i][j][k], shift ); + Cldfb_ImagBuffer_inTmp_fx[i][j][k] = L_shl( Cldfb_ImagBuffer_in_fx[i][j][k], shift ); + } + } + } + + ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_inTmp_fx, Cldfb_ImagBuffer_inTmp_fx, Rmat_fx, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, NULL, q ); /* Always using CLDFB decorrelation in MASA EXT renderer */ max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr; +#if 1 + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hDiracDecBin->ChEnePrev[i][j] = me2f( hDiracDecBin->ChEnePrev_fx[i][j], hDiracDecBin->ChEnePrev_e[i][j] ); + hDiracDecBin->ChEne[i][j] = me2f( hDiracDecBin->ChEne_fx[i][j], hDiracDecBin->ChEne_e[i][j] ); + hDiracDecBin->ChEneOut[i][j] = me2f( hDiracDecBin->ChEneOut_fx[i][j], hDiracDecBin->ChEneOut_e[i][j] ); + hDiracDecBin->ChEneOutPrev[i][j] = me2f( hDiracDecBin->ChEneOutPrev_fx[i][j], hDiracDecBin->ChEneOutPrev_e[i][j] ); + } + } + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hDiracDecBin->ChCrossRePrev[j] = me2f( hDiracDecBin->ChCrossRePrev_fx[j], hDiracDecBin->ChCrossRePrev_e[j] ); + hDiracDecBin->ChCrossImPrev[j] = me2f( hDiracDecBin->ChCrossImPrev_fx[j], hDiracDecBin->ChCrossImPrev_e[j] ); + hDiracDecBin->ChCrossRe[j] = me2f( hDiracDecBin->ChCrossRe_fx[j], hDiracDecBin->ChCrossRe_e[j] ); + hDiracDecBin->ChCrossIm[j] = me2f( hDiracDecBin->ChCrossIm_fx[j], hDiracDecBin->ChCrossIm_e[j] ); + hDiracDecBin->ChCrossReOut[j] = me2f( hDiracDecBin->ChCrossReOut_fx[j], hDiracDecBin->ChCrossReOut_e[j] ); + hDiracDecBin->ChCrossImOut[j] = me2f( hDiracDecBin->ChCrossImOut_fx[j], hDiracDecBin->ChCrossImOut_e[j] ); + hDiracDecBin->ChCrossReOutPrev[j] = me2f( hDiracDecBin->ChCrossReOutPrev_fx[j], hDiracDecBin->ChCrossReOutPrev_e[j] ); + hDiracDecBin->ChCrossImOutPrev[j] = me2f( hDiracDecBin->ChCrossImOutPrev_fx[j], hDiracDecBin->ChCrossImOutPrev_e[j] ); + } + fixedToFloat_arrL( hDiracDecBin->frameMeanDiffuseness_fx, hDiracDecBin->frameMeanDiffuseness, 29, CLDFB_NO_CHANNELS_MAX ); - - ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe, - hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, - 0, NULL ); + FOR( ch = 0; ch < 2; ch++) + { + fixedToFloat_arrL32(hMasaExtRend->cldfbAnaRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbAnaRend[ch]->cldfb_state, Q11, hMasaExtRend->cldfbAnaRend[ch]->p_filter_length - hMasaExtRend->cldfbAnaRend[ch]->no_channels); + } +#endif - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float Rmat[3][3]; + for ( i = 0; i < 3; i++) // TODO: To be removed + { + fixedToFloat_arrL32(Rmat_fx[i], Rmat[i], Q30, 3); + } + ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, + 0, NULL ); -#ifdef IVAS_FLOAT_FIXED +#if 1 Word16 q_out; Word16 q_mat = 15; - Word16 q_inp = Q6; + q_inp = Q6; FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { output_fx[ch] = output_fx_buff[ch]; @@ -4964,10 +6209,6 @@ static void ivas_masa_ext_rend_parambin_internal( } } FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - output_fx[ch] = output_fx_buff[ch]; - } - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) { @@ -4989,40 +6230,34 @@ static void ivas_masa_ext_rend_parambin_internal( floatToFixed_arrL( hMasaExtRend->cldfbSynRend[ch]->cldfb_state, hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, Q11, hMasaExtRend->cldfbSynRend[ch]->p_filter_length ); hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11; } - FOR( Word16 cha = 0; cha < 6; cha++ ) - FOR( slot = 0; slot < 4; slot++ ) - FOR( Word16 ind = 0; ind < 60; ind++ ) - { - Cldfb_RealBuffer_in_fx[cha][slot][ind] = floatToFixed( Cldfb_RealBuffer_in[cha][slot][ind], Q6 ); - Cldfb_ImagBuffer_in_fx[cha][slot][ind] = floatToFixed( Cldfb_ImagBuffer_in[cha][slot][ind], Q6 ); - } - ivas_dirac_dec_binaural_process_output_fx(hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat); +#endif //Float to fix ends + + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); + + + hDiracDecBin->hDiffuseDist = NULL; + + hSpatParamRendCom->slots_rendered = add(hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe]); + hSpatParamRendCom->subframes_rendered = add(hSpatParamRendCom->subframes_rendered, 1); +#if 1// Fix to float FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { fixedToFloat_arrL32( output_fx[ch], output_f[ch], q_out, nBins * hSpatParamRendCom->subframe_nbslots[subframe] ); fixedToFloat_arrL32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_state, hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state, hMasaExtRend->cldfbSynRend[ch]->p_filter_length ); } -#else - ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, max_band_decorr, numInChannels, config_data.processReverb, subframe ); #endif - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - hDiracDecBin->hDiffuseDist = NULL; - - hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe]; - hSpatParamRendCom->subframes_rendered++; return; } +#endif void ivas_masa_ext_rend_parambin_render( MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA ext rend structure */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */ float *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output */ - const int16_t num_subframes ) /* i : number of subframes to render */ + const int16_t num_subframes ) /* i : number of subframes to render */ { int16_t subframe; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; diff --git a/lib_rend/ivas_mcmasa_ana.c b/lib_rend/ivas_mcmasa_ana.c index f5107381b..468a7ce8f 100644 --- a/lib_rend/ivas_mcmasa_ana.c +++ b/lib_rend/ivas_mcmasa_ana.c @@ -42,13 +42,20 @@ #include "ivas_rom_com.h" #include "wmc_auto.h" #include "ivas_prot_fx.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" +#include "ivas_rom_com_fx.h" +#endif // IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * Local constants *------------------------------------------------------------------------*/ #define NEAR_HORIZONTAL_PLANE_ELEVATION 17.5f +#define NEAR_HORIZONTAL_PLANE_ELEVATION_FX 73400320/*Q22*/ #define VERTICAL_ENERGY_RATIO_OFFSET 0.15f +#define VERTICAL_ENERGY_RATIO_OFFSET_FX 4915/*Q15*/ /*------------------------------------------------------------------------- @@ -60,7 +67,27 @@ typedef struct { float xr[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; float xi[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; +#ifdef IVAS_FLOAT_FIXED + Word32 xr_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word32 xi_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word16 xr_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];/*Stores exponent for xr_fx*/ + Word16 xi_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS];/*Stores exponent for xi_fx*/ +#endif // IVAS_FLOAT_FIXED } CovarianceMatrix; +#ifdef IVAS_FLOAT_FIXED +void ivas_mcmasa_param_est_ana_fx( + MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ + Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */ + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + Word16 q_data, + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_inp /* i : Number of input channels */ +); +#endif // IVAS_FLOAT_FIXED void ivas_mcmasa_param_est_ana( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48k], float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], const int16_t input_frame, const int16_t nchan_inp ); @@ -69,6 +96,35 @@ static void ivas_mcmasa_dmx( MCMASA_ANA_HANDLE hMcMasa, float data_f[][L_FRAME48 static void compute_cov_mtx( float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], float si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], const int16_t freq, const int16_t N, CovarianceMatrix *COVls ); static void computeVerticalDiffuseness( float **buffer_intensity, const float *buffer_energy, const int16_t num_freq_bands, float *diffuseness ); +#ifdef IVAS_FLOAT_FIXED +static void computeVerticalDiffuseness_fx( + Word32 **buffer_intensity, /* i : Intensity vectors */ + const Word32 *buffer_energy, /* i : Energy */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + Word32 *diffuseness, /* o : Estimated diffuseness */ + Word16 *buffer_intensity_e, + Word16 *buffer_energy_e ); +static void compute_cov_mtx_fx( + Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */ + Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */ + const Word16 freq, /* i : Freq to process */ + const Word16 N, /* i : Number of channels */ + CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */ + Word16 shift); +static void computeEvenLayout_fx( + const Word32 *ls_azimuth, + Word32 *ls_azimuth_even, + const Word16 numChannels ); + +static void ivas_mcmasa_dmx_fx( + MCMASA_ANA_HANDLE hMcMasa, + Word32 data_f_fx[][L_FRAME48k], + Word16 data_e, + const Word16 input_frame, + const Word16 nchan_transport, + const Word16 nchan_inp ); + +#endif // IVAS_FLOAT_FIXED static void computeEvenLayout( const float *ls_azimuth, float *ls_azimuth_even, const int16_t numChannels ); @@ -79,6 +135,279 @@ static void computeEvenLayout( const float *ls_azimuth, float *ls_azimuth_even, * *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_mcmasa_ana_open( + MCMASA_ANA_HANDLE *hMcMasaPtr, /* i/o: McMASA data handle pointer */ + const AUDIO_CONFIG inConfig, /* i : Input config */ + Word32 input_Fs /* i : Sampling frequency */ +) +{ + Word32 ls_azimuth_fx[MCMASA_MAX_ANA_CHANS]; + Word32 ls_elevation_fx[MCMASA_MAX_ANA_CHANS]; + Word32 ls_azimuth_even_fx[MCMASA_MAX_ANA_CHANS]; + Word32 left_min_fx, right_min_fx, azi_diff_fx; + Word16 i, j; + MCMASA_ANA_HANDLE hMcMasa; + Word16 nchan_inp; + Word16 numAnalysisChannels; + Word16 maxBin, input_frame; + ivas_error error; + + error = IVAS_ERR_OK; + + IF ( ( hMcMasa = (MCMASA_ANA_HANDLE) malloc( sizeof( MCMASA_ANA_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + IF ( EQ_16(inConfig , IVAS_AUDIO_CONFIG_5_1) ) + { + nchan_inp = 6; + Copy32( ls_azimuth_CICP6_fx, ls_azimuth_fx, nchan_inp - 1 ); + Copy32( ls_elevation_CICP6_fx, ls_elevation_fx, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 5; + hMcMasa->isHorizontalSetup = 1; + } + ELSE IF ( EQ_16(inConfig , IVAS_AUDIO_CONFIG_7_1) ) + { + nchan_inp = 8; + Copy32( ls_azimuth_CICP12_fx, ls_azimuth_fx, nchan_inp - 1 ); + Copy32( ls_elevation_CICP12_fx, ls_elevation_fx, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 7; + hMcMasa->isHorizontalSetup = 1; + } + ELSE IF( EQ_16(inConfig , IVAS_AUDIO_CONFIG_5_1_2) ) + { + nchan_inp = 8; + Copy32( ls_azimuth_CICP14_fx, ls_azimuth_fx, nchan_inp - 1 ); + Copy32( ls_elevation_CICP14_fx, ls_elevation_fx, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 5; + hMcMasa->isHorizontalSetup = 0; + } + ELSE IF ( EQ_16(inConfig , IVAS_AUDIO_CONFIG_5_1_4) ) + { + nchan_inp = 10; + Copy32( ls_azimuth_CICP16_fx, ls_azimuth_fx, nchan_inp - 1 ); + Copy32( ls_elevation_CICP16_fx, ls_elevation_fx, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 5; + hMcMasa->isHorizontalSetup = 0; + } + ELSE + { + nchan_inp = 12; + Copy32( ls_azimuth_CICP19_fx, ls_azimuth_fx, nchan_inp - 1 ); + Copy32( ls_elevation_CICP19_fx, ls_elevation_fx, nchan_inp - 1 ); + hMcMasa->numHorizontalChannels = 7; + hMcMasa->isHorizontalSetup = 0; + } + + numAnalysisChannels = sub(nchan_inp , 1); + + /* Determine the number of bands */ + hMcMasa->nbands = MASA_FREQUENCY_BANDS; + + /* Determine band grouping */ + Copy( MASA_band_grouping_24, hMcMasa->band_grouping, 24 + 1 ); + + maxBin = extract_l(W_extract_h(W_add(W_mult_32_32(input_Fs , INV_CLDFB_BANDWIDTH_Q31) , ONE_IN_Q31/*0.5f in Q31*/) )); + FOR ( i = 1; i < hMcMasa->nbands + 1; i++ ) + { + IF ( GE_16(hMcMasa->band_grouping[i] , maxBin) ) + { + hMcMasa->band_grouping[i] = maxBin; + hMcMasa->nbands = i; + break; + } + } + + /* Determine block grouping */ + Copy( DirAC_block_grouping, hMcMasa->block_grouping, MAX_PARAM_SPATIAL_SUBFRAMES + 1 ); + + /* open/initialize CLDFB */ + hMcMasa->num_Cldfb_instances = numAnalysisChannels; + FOR ( i = 0; i < hMcMasa->num_Cldfb_instances; i++ ) + { + IF ( ( error = openCldfb_ivas( &( hMcMasa->cldfbAnaEnc[i] ), CLDFB_ANALYSIS, input_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* intensity 3-dim */ + FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { +#if 1/*TODO: To be removed later*/ + if ( ( hMcMasa->direction_vector_m[i] = (float **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + if ( ( hMcMasa->direction_vector_m[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->direction_vector_m[i][j], MASA_FREQUENCY_BANDS ); + } +#endif + IF( ( hMcMasa->direction_vector_m_fx[i] = (Word32 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + FOR ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + IF ( ( hMcMasa->direction_vector_m_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero_fx( hMcMasa->direction_vector_m_fx[i][j], MASA_FREQUENCY_BANDS ); + } + IF( ( hMcMasa->direction_vector_e[i] = (Word16 **) malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( Word16 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + IF( ( hMcMasa->direction_vector_e[i][j] = (Word16 *) malloc( MASA_FREQUENCY_BANDS * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set16_fx( hMcMasa->direction_vector_e[i][j],0, MASA_FREQUENCY_BANDS ); + } + } + FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { +#if 1/*TODO: To be removed later*/ + if ( ( hMcMasa->buffer_intensity_real[i][j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->buffer_intensity_real[i][j], MASA_FREQUENCY_BANDS ); +#endif + IF ( ( hMcMasa->buffer_intensity_real_fx[i][j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof(Word32) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero_fx( hMcMasa->buffer_intensity_real_fx[i][j], MASA_FREQUENCY_BANDS ); + } + } + set16_fx( hMcMasa->buffer_intensity_real_q, 31, DIRAC_NO_COL_AVG_DIFF); + + FOR ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { +#if 1/*TODO: To be removed later*/ + if ( ( hMcMasa->buffer_intensity_real_vert[j] = (float *) malloc( MASA_FREQUENCY_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero( hMcMasa->buffer_intensity_real_vert[j], MASA_FREQUENCY_BANDS ); +#endif + IF ( ( hMcMasa->buffer_intensity_real_vert_fx[j] = (Word32 *) malloc( MASA_FREQUENCY_BANDS * sizeof(Word32) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for McMasa\n" ) ); + } + set_zero_fx( hMcMasa->buffer_intensity_real_vert_fx[j], MASA_FREQUENCY_BANDS ); + } + + set16_fx(hMcMasa->buffer_intensity_real_vert_q, 31, DIRAC_NO_COL_AVG_DIFF ); +#if 1/*TODO: To be removed later*/ + set_zero( hMcMasa->buffer_energy, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); +#endif + set_zero_fx( hMcMasa->buffer_energy_fx, DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS ); + set16_fx(hMcMasa->buffer_energy_q, 31, DIRAC_NO_COL_AVG_DIFF ); + + computeEvenLayout_fx( ls_azimuth_fx, ls_azimuth_even_fx, hMcMasa->numHorizontalChannels ); + + IF ( !hMcMasa->isHorizontalSetup ) + { + computeEvenLayout_fx( &ls_azimuth_fx[hMcMasa->numHorizontalChannels], &ls_azimuth_even_fx[hMcMasa->numHorizontalChannels], sub(numAnalysisChannels , hMcMasa->numHorizontalChannels) ); + } + + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + hMcMasa->chnlToFoaMtx_fx[0][i] = ONE_IN_Q31; + hMcMasa->chnlToFoaMtx_fx[1][i] = L_mult( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 /*32767/360*/ ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); + hMcMasa->chnlToFoaMtx_fx[2][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ), 16 ); + hMcMasa->chnlToFoaMtx_fx[3][i] = L_mult( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_fx[i], 91 ), 7 ) ) ), getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_elevation_fx[i], 91 ), 7 ) ) ) ); + + hMcMasa->chnlToFoaEvenMtx_fx[0][i] = ONE_IN_Q31; + hMcMasa->chnlToFoaEvenMtx_fx[1][i] = L_shl( getSineWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); + hMcMasa->chnlToFoaEvenMtx_fx[2][i] = 0; + hMcMasa->chnlToFoaEvenMtx_fx[3][i] = L_shl( getCosWord16R2( extract_l( L_shr( Mult_32_16( ls_azimuth_even_fx[i], 91 ), 7 ) ) ), 16 ); + } + + Copy32( ls_azimuth_fx, hMcMasa->ls_azimuth_fx, numAnalysisChannels ); + + FOR ( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) + { + left_min_fx = L_shl(360,22); + right_min_fx = L_shl(-360,22); + + FOR ( j = 0; j < hMcMasa->numHorizontalChannels; j++ ) + { + azi_diff_fx = L_sub(ls_azimuth_fx[j] , ls_azimuth_fx[i]); + + IF ( GT_32(azi_diff_fx , (180<<22)) ) + { + azi_diff_fx = L_sub(azi_diff_fx,360<<22); + } + ELSE IF ( LT_32(azi_diff_fx , -(180<<22)) ) + { + azi_diff_fx = L_add(azi_diff_fx,360<<22); + } + + IF( LT_32( azi_diff_fx, left_min_fx ) && GT_32( azi_diff_fx, 0 ) ) + { + hMcMasa->leftNearest[i] = j; + left_min_fx = azi_diff_fx; + } + + IF( GT_32( azi_diff_fx, right_min_fx ) && LT_32( azi_diff_fx , 0 ) ) + { + hMcMasa->rightNearest[i] = j; + right_min_fx = azi_diff_fx; + } + } + } + +#if 1/*TODO: To be removed later(floating point initialization)*/ + hMcMasa->prevMultiChEne = 0.0f; + hMcMasa->prevDownmixEne = 0.0f; + hMcMasa->prevEQ = 1.0f; +#endif + hMcMasa->prevMultiChEne_fx = 0; + hMcMasa->prevDownmixEne_fx = 0; + hMcMasa->prevEQ_fx = 32767; + input_frame = (int16_t) ( input_Fs / FRAMES_PER_SEC ); + FOR ( i = 0; i < input_frame; i++ ) + { + hMcMasa->interpolator_fx[i] = div_s( i, input_frame ); + } + + hMcMasa->index_buffer_intensity = 0; + + IF ( ( hMcMasa->hMasaOut = (MASA_DECODER_EXT_OUT_META_HANDLE) malloc( sizeof( MASA_DECODER_EXT_OUT_META ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + + IF ( ( hMcMasa->sph_grid16 = (SPHERICAL_GRID_DATA *) malloc( sizeof( SPHERICAL_GRID_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA decoder\n" ) ); + } + generate_gridEq_fx( hMcMasa->sph_grid16 ); + + ( *hMcMasaPtr ) = hMcMasa; + + return error; +} + +#else ivas_error ivas_mcmasa_ana_open( MCMASA_ANA_HANDLE *hMcMasaPtr, /* i/o: McMASA data handle pointer */ const AUDIO_CONFIG inConfig, /* i : Input config */ @@ -297,7 +626,7 @@ ivas_error ivas_mcmasa_ana_open( return error; } - +#endif // IVAS_FLOAT_FIXED /*--------------------------------------------------------------------------* * ivas_mcmasa_ana_close() @@ -305,106 +634,777 @@ ivas_error ivas_mcmasa_ana_open( * *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_mcmasa_ana_close( + MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */ +) +{ + Word16 i, j; + + IF ( hMcMasa == NULL || *hMcMasa == NULL ) + { + return; + } + + FOR ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ ) + { + deleteCldfb_ivas( &( ( *hMcMasa )->cldfbAnaEnc[i] ) ); + } + + /* intensity 3-dim */ + FOR( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hMcMasa )->direction_vector_m_fx[i][j] ); + ( *hMcMasa )->direction_vector_m_fx[i][j] = NULL; + } + + FOR ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real_fx[i][j] ); + ( *hMcMasa )->buffer_intensity_real_fx[i][j] = NULL; + } + + free( ( *hMcMasa )->direction_vector_m_fx[i] ); + ( *hMcMasa )->direction_vector_m_fx[i] = NULL; + } + + FOR ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real_vert_fx[j] ); + ( *hMcMasa )->buffer_intensity_real_vert_fx[j] = NULL; + } +#if 1/*TODO: To be removed later( freeing float buffer)*/ + FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + FOR ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hMcMasa )->direction_vector_m[i][j] ); + ( *hMcMasa )->direction_vector_m[i][j] = NULL; + } + + FOR ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real[i][j] ); + ( *hMcMasa )->buffer_intensity_real[i][j] = NULL; + } + + free( ( *hMcMasa )->direction_vector_m[i] ); + ( *hMcMasa )->direction_vector_m[i] = NULL; + } + + FOR ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real_vert[j] ); + ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL; + } +#endif + + free( ( *hMcMasa )->hMasaOut ); + ( *hMcMasa )->hMasaOut = NULL; + free( ( *hMcMasa )->sph_grid16 ); + ( *hMcMasa )->sph_grid16 = NULL; + + free( ( *hMcMasa ) ); + ( *hMcMasa ) = NULL; + + return; +} +#else void ivas_mcmasa_ana_close( MCMASA_ANA_HANDLE *hMcMasa /* i/o: analysis McMASA handle */ ) { int16_t i, j; - if ( hMcMasa == NULL || *hMcMasa == NULL ) - { - return; - } + if ( hMcMasa == NULL || *hMcMasa == NULL ) + { + return; + } + + for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ ) + { + deleteCldfb_ivas( &( ( *hMcMasa )->cldfbAnaEnc[i] ) ); + } + + /* intensity 3-dim */ + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + free( ( *hMcMasa )->direction_vector_m[i][j] ); + ( *hMcMasa )->direction_vector_m[i][j] = NULL; + } + + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real[i][j] ); + ( *hMcMasa )->buffer_intensity_real[i][j] = NULL; + } + + free( ( *hMcMasa )->direction_vector_m[i] ); + ( *hMcMasa )->direction_vector_m[i] = NULL; + } + + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + free( ( *hMcMasa )->buffer_intensity_real_vert[j] ); + ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL; + } + + free( ( *hMcMasa )->hMasaOut ); + ( *hMcMasa )->hMasaOut = NULL; + free( ( *hMcMasa )->sph_grid16 ); + ( *hMcMasa )->sph_grid16 = NULL; + + free( ( *hMcMasa ) ); + ( *hMcMasa ) = NULL; + + return; +} +#endif // IVAS_FLOAT_FIXED + + +/*--------------------------------------------------------------------------* + * ivas_mcmasa_ana() + * + * Multichannel MASA analysis + *--------------------------------------------------------------------------*/ + +#ifdef IVAS_FLOAT_FIXED +void ivas_mcmasa_ana_fx( + MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */ + Word32 data[][L_FRAME48k], /* i/o: Input / transport audio signals */ + Word16 q_data, + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_transport, /* i : Number of transport channels */ + const Word16 nchan_inp /* i : Number of input channels */ +) +{ + Word16 i; + + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + /* Sum center and LFE, move surround channels */ + v_add_32( data[2], data[3], data[2], input_frame ); + FOR ( i = 4; i < nchan_inp; i++ ) + { + Copy32( data[i], data[i - 1], input_frame ); + } + + /* Analysis */ + ivas_mcmasa_param_est_ana_fx( hMcMasa, data, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, q_data, input_frame, nchan_inp ); + + /* Create MASA metadata buffer from the estimated values */ + ivas_create_masa_out_meta_fx( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values_fx, azimuth_m_values_fx, energyRatio_fx, spreadCoherence_fx, surroundingCoherence_fx, Q31, Q31, Q31 ); + + /* Downmix */ + + ivas_mcmasa_dmx_fx( hMcMasa, data, 31 - q_data, input_frame, nchan_transport, nchan_inp ); + + + return; +} +#endif +void ivas_mcmasa_ana( + MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */ + float data_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ + const int16_t input_frame, /* i : Input frame size */ + const int16_t nchan_transport, /* i : Number of transport channels */ + const int16_t nchan_inp /* i : Number of input channels */ +) +{ + int16_t i; + float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + + + /* Sum center and LFE, move surround channels */ + v_add( data_f[2], data_f[3], data_f[2], input_frame ); + for ( i = 4; i < nchan_inp; i++ ) + { + mvr2r( data_f[i], data_f[i - 1], input_frame ); + } + + /* Analysis */ + ivas_mcmasa_param_est_ana( hMcMasa, data_f, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame, nchan_inp ); + + /* Create MASA metadata buffer from the estimated values */ + ivas_create_masa_out_meta( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence ); + + /* Downmix */ + ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp ); + + return; +} + + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +/* Estimate metadata parameters for McMASA */ +#ifdef IVAS_FLOAT_FIXED +void ivas_mcmasa_param_est_ana_fx( + MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ + Word32 data_fx[][L_FRAME48k], /* i : Audio frame in MC-format */ + Word32 elevation_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated elevation */ + Word32 azimuth_m_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated azimuth */ + Word32 energyRatio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated direct-to-total ratio */ + Word32 spreadCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated spread coherence */ + Word32 surroundingCoherence_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* o : Estimated surround coherence */ + Word16 q_data, + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_inp /* i : Number of input channels */ +) +{ + Word16 cohPanCoh_e; + Word16 tempLsEnergyRelation_e; + Word16 q_vdv[MASA_FREQUENCY_BANDS]; + Word16 out_exp[MASA_FREQUENCY_BANDS]; + Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 dir_v_fx[DIRAC_NUM_DIMS]; + Word32 Chnl_RealBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX]; + Word32 Chnl_ImagBuffer_fx[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX]; + Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 FoaEven_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 FoaEven_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 intensity_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word32 intensity_even_real_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word32 direction_vector_fx[DIRAC_NUM_DIMS][MASA_FREQUENCY_BANDS]; + Word32 diffuseness_vector_fx[MASA_FREQUENCY_BANDS]; + Word32 vertical_diffuseness_vector_fx[MASA_FREQUENCY_BANDS]; + Word32 diffuseness_m_fx[MASA_FREQUENCY_BANDS]; + Word16 diffuseness_e[MASA_FREQUENCY_BANDS]; + Word32 coherentEnergyRatio_fx[MASA_FREQUENCY_BANDS]; + Word32 renormalization_factor_diff_fx[MASA_FREQUENCY_BANDS]; + Word16 renormalization_factor_diff_e[MASA_FREQUENCY_BANDS]; + Word32 norm_tmp_fx; + Word32 absCOVls_fx[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word16 absCOVls_e[MCMASA_MAX_ANA_CHANS][MCMASA_MAX_ANA_CHANS]; + Word32 lsEnergy_fx[MCMASA_MAX_ANA_CHANS]; + Word16 lsEnergy_e[MCMASA_MAX_ANA_CHANS]; + Word32 lsEnergySum_fx, maxEne_fx; + Word16 lsEnergySum_e = 0; + Word16 maxEne_e; + Word32 angleDist_fx, minAngleDist_fx; + Word32 currentAzi_fx; + Word32 lsEnergyRelation_fx; + Word16 lsEnergyRelation_e; + Word32 tempLsEnergyRelation_fx; + Word32 stereoness_fx, cohwideness_fx, spreadCoh_fx; + Word32 stereoRatio_fx, cohPanRatio_fx; + Word16 stereoness_e; + Word32 stereoCoh_fx, cohPanCoh_fx, cohRatio_fx; + Word32 surrCoh_fx, tempCoh_fx, tempCoh2_fx; + Word16 surrCoh_e; + Word16 stereoCoh_e; + Word16 tempCoh_e; + Word16 tempCoh2_e; + Word16 ts, i, j, d; + Word16 num_freq_bins, num_freq_bands, index; + Word16 l_ts; + Word16 band_m_idx, block_m_idx; + Word16 mrange[2], brange[2]; + CovarianceMatrix COVls[MASA_FREQUENCY_BANDS]; + Word16 loudestCh; + Word16 i1, i2, i3; + Word16 numAnalysisChannels; + Word16 spreadCoh_e; + num_freq_bins = hMcMasa->cldfbAnaEnc[0]->no_channels; + num_freq_bands = hMcMasa->nbands; + l_ts = input_frame / CLDFB_NO_COL_MAX; + numAnalysisChannels = sub(nchan_inp , 1); + + set16_fx( q_vdv, 31, MASA_FREQUENCY_BANDS ); + set16_fx( out_exp, 30, MASA_FREQUENCY_BANDS ); + /* do processing over all CLDFB time slots */ + FOR ( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ ) + { + mrange[0] = hMcMasa->block_grouping[block_m_idx]; + mrange[1] = hMcMasa->block_grouping[block_m_idx + 1]; + + FOR ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + { + hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = 0; + hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = 0; + hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = 0; + hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] = 0; + hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] = 0; + hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] = 0; + } + + /* Need to initialize renormalization_factors, and variables to be normalized */ + set_zero_fx( renormalization_factor_diff_fx, hMcMasa->nbands ); + set16_fx( renormalization_factor_diff_e,0, hMcMasa->nbands ); + set_zero_fx( diffuseness_m_fx, hMcMasa->nbands ); + set16_fx( diffuseness_e, 0,hMcMasa->nbands ); + set_zero_fx( hMcMasa->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS ); + set16_fx( hMcMasa->energy_e[block_m_idx], 0,MASA_FREQUENCY_BANDS ); + /* Reset variable */ + FOR ( i = 0; i < hMcMasa->nbands; i++ ) + { + FOR ( j = 0; j < numAnalysisChannels; j++ ) + { + set_zero_fx( COVls[i].xr_fx[j], numAnalysisChannels ); + set_zero_fx( COVls[i].xi_fx[j], numAnalysisChannels ); + set16_fx( COVls[i].xr_e[j],0, numAnalysisChannels ); + set16_fx( COVls[i].xi_e[j],0, numAnalysisChannels ); + } + } + + FOR ( ts = mrange[0]; ts < mrange[1]; ts++ ) + { + Word16 cr_q=MAX_16, ci_q= MAX_16,sf,c_e; + Word16 inp_q= q_data; + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + inp_q = q_data; + cldfbAnalysis_ts_fx_fixed_q( &( data_fx[i][l_ts * ts] ), Chnl_RealBuffer_fx[i], Chnl_ImagBuffer_fx[i], l_ts, hMcMasa->cldfbAnaEnc[i], &inp_q); + cr_q = s_min(cr_q,getScaleFactor32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX )); + ci_q = s_min( ci_q, getScaleFactor32(Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX ) ); + } + sf = sub(s_min( cr_q, ci_q ) , 4); + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + scale_sig32( Chnl_RealBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf); + scale_sig32( Chnl_ImagBuffer_fx[i], CLDFB_NO_CHANNELS_MAX, sf); + } + inp_q = add(inp_q, sf ); + c_e = sub(31 , inp_q); + hMcMasa->chnlToFoaMtx_e = c_e; + /* Compute channel-based energy for metadata processing */ + FOR ( band_m_idx = 0; band_m_idx < num_freq_bands; band_m_idx++ ) + { + brange[0] = hMcMasa->band_grouping[band_m_idx]; + brange[1] = hMcMasa->band_grouping[band_m_idx + 1]; + FOR ( j = brange[0]; j < brange[1]; j++ ) + { + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + Word32 temp = L_add( Mult_32_32( Chnl_RealBuffer_fx[i][j], Chnl_RealBuffer_fx[i][j] ), Mult_32_32( Chnl_ImagBuffer_fx[i][j], Chnl_ImagBuffer_fx[i][j] ) ); + hMcMasa->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp(hMcMasa->energy_fx[block_m_idx][band_m_idx], hMcMasa->energy_e[block_m_idx][band_m_idx], temp, (c_e) * 2, &hMcMasa->energy_e[block_m_idx][band_m_idx]); + } + } + } + + /* Compute covariance matrix */ + FOR ( i = 0; i < num_freq_bands; i++ ) + { + brange[0] = hMcMasa->band_grouping[i]; + brange[1] = hMcMasa->band_grouping[i + 1]; + FOR ( j = brange[0]; j < brange[1]; j++ ) + { + compute_cov_mtx_fx( Chnl_RealBuffer_fx, Chnl_ImagBuffer_fx, j, numAnalysisChannels, &( COVls[i] ), c_e); + } + } + + /* Compute standard FOA */ + /* W */ + v_add_32( Chnl_RealBuffer_fx[0], Chnl_RealBuffer_fx[1], Foa_RealBuffer_fx[0], num_freq_bins );/*q*/ + v_add_32( Chnl_ImagBuffer_fx[0], Chnl_ImagBuffer_fx[1], Foa_ImagBuffer_fx[0], num_freq_bins );/*q*/ + FOR ( i = 2; i < numAnalysisChannels; i++ ) + { + v_add_32( Chnl_RealBuffer_fx[i], Foa_RealBuffer_fx[0], Foa_RealBuffer_fx[0], num_freq_bins );/*q*/ + v_add_32( Chnl_ImagBuffer_fx[i], Foa_ImagBuffer_fx[0], Foa_ImagBuffer_fx[0], num_freq_bins );/*q*/ + } + + /* Y */ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_RealBuffer_fx[1], num_freq_bins );/*q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[1][0], Foa_ImagBuffer_fx[1], num_freq_bins );/*q*/ + FOR ( i = 1; i < numAnalysisChannels; i++ ) + { + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_RealBuffer_fx[1], num_freq_bins );/*q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[1][i], Foa_ImagBuffer_fx[1], num_freq_bins );/*q*/ + } + /* Z */ + IF ( hMcMasa->isHorizontalSetup ) + { + /* Set zero for horizontal setups */ + set_zero_fx( Foa_RealBuffer_fx[2], num_freq_bins ); + set_zero_fx( Foa_ImagBuffer_fx[2], num_freq_bins ); + } + ELSE + { + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_RealBuffer_fx[2], num_freq_bins );/*q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[2][0], Foa_ImagBuffer_fx[2], num_freq_bins );/*q*/ + FOR ( i = 1; i < numAnalysisChannels; i++ ) + { + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_RealBuffer_fx[2], num_freq_bins );/*q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[2][i], Foa_ImagBuffer_fx[2], num_freq_bins );/*q*/ + } + } + /* X */ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_RealBuffer_fx[3], num_freq_bins );/*q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaMtx_fx[3][0], Foa_ImagBuffer_fx[3], num_freq_bins );/*q*/ + FOR ( i = 1; i < numAnalysisChannels; i++ ) + { + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_RealBuffer_fx[3], num_freq_bins );/*q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaMtx_fx[3][i], Foa_ImagBuffer_fx[3], num_freq_bins );/*q*/ + } + + /* Compute even FOA */ + /* W */ + Copy32( Foa_RealBuffer_fx[0], FoaEven_RealBuffer_fx[0], num_freq_bins ); + Copy32( Foa_ImagBuffer_fx[0], FoaEven_ImagBuffer_fx[0], num_freq_bins ); + + /* Y */ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_RealBuffer_fx[1], num_freq_bins );/*q*/ + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[1][0], FoaEven_ImagBuffer_fx[1], num_freq_bins );/*q*/ + FOR ( i = 1; i < numAnalysisChannels; i++ ) + { + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_RealBuffer_fx[1], num_freq_bins );/*q*/ + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[1][i], FoaEven_ImagBuffer_fx[1], num_freq_bins );/*q*/ + } + + /* Z (even setups are handled as horizontal) */ + set_zero_fx( FoaEven_RealBuffer_fx[2], num_freq_bins ); + set_zero_fx( FoaEven_ImagBuffer_fx[2], num_freq_bins ); + + /* X */ + v_multc_fixed( Chnl_RealBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_RealBuffer_fx[3], num_freq_bins ); + v_multc_fixed( Chnl_ImagBuffer_fx[0], hMcMasa->chnlToFoaEvenMtx_fx[3][0], FoaEven_ImagBuffer_fx[3], num_freq_bins ); + FOR ( i = 1; i < numAnalysisChannels; i++ ) + { + v_multc_acc_32_32( Chnl_RealBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_RealBuffer_fx[3], num_freq_bins ); + v_multc_acc_32_32( Chnl_ImagBuffer_fx[i], hMcMasa->chnlToFoaEvenMtx_fx[3][i], FoaEven_ImagBuffer_fx[3], num_freq_bins ); + } + + /* Direction estimation */ + computeIntensityVector_ana_fx( hMcMasa->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, num_freq_bands, intensity_real_fx ); /*2+q-31*/ + + computeDirectionVectors_fixed( intensity_real_fx[0], intensity_real_fx[1], intensity_real_fx[2], 0, num_freq_bands, direction_vector_fx[0], direction_vector_fx[1], direction_vector_fx[2],2*c_e );/*Q30*/ + + /* Power and intensity estimation for diffuseness */ + computeIntensityVector_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, num_freq_bands, intensity_even_real_fx );/*2*(q)-31*/ + computeReferencePower_ana_fx( hMcMasa->band_grouping, FoaEven_RealBuffer_fx, FoaEven_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands );/*2*q-30*/ + + /* Fill buffers of length "averaging_length" time slots for intensity and energy */ + hMcMasa->index_buffer_intensity = ( hMcMasa->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ) + 1; /* averaging_length = 32 */ + index = hMcMasa->index_buffer_intensity; + FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + /* only real part needed */ + Copy32( intensity_even_real_fx[i], &( hMcMasa->buffer_intensity_real_fx[i][index - 1][0] ), num_freq_bands ); + } + hMcMasa->buffer_intensity_real_q[index - 1] = 2 * inp_q - 31; + Copy32( reference_power_fx[ts], &( hMcMasa->buffer_energy_fx[( index - 1 ) * num_freq_bands] ), num_freq_bands ); + hMcMasa->buffer_energy_q[index - 1] = 2 * inp_q - 30; + computeDiffuseness_fixed( hMcMasa->buffer_intensity_real_fx, hMcMasa->buffer_energy_fx, num_freq_bands, diffuseness_vector_fx ,hMcMasa->buffer_intensity_real_q, hMcMasa->buffer_energy_q,out_exp); + /* Compute vertical diffuseness, and tune original diffuseness if needed */ + IF ( !hMcMasa->isHorizontalSetup ) + { + Copy32( intensity_real_fx[2], &( hMcMasa->buffer_intensity_real_vert_fx[index - 1][0] ), num_freq_bands ); + hMcMasa->buffer_intensity_real_vert_q[index - 1] = 2 * inp_q - 31; + computeVerticalDiffuseness_fx( hMcMasa->buffer_intensity_real_vert_fx, hMcMasa->buffer_energy_fx, num_freq_bands, vertical_diffuseness_vector_fx , hMcMasa->buffer_intensity_real_vert_q, hMcMasa->buffer_energy_q); + v_min_fx( diffuseness_vector_fx,out_exp, vertical_diffuseness_vector_fx,q_vdv, diffuseness_vector_fx,out_exp, num_freq_bands ); + } + FOR ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + { + norm_tmp_fx = L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], L_sub( ONE_IN_Q30, diffuseness_vector_fx[band_m_idx] ) ), 1 ); /*2q-30*/ + hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[0][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[0][band_m_idx] ), 2 * c_e, &hMcMasa->direction_vector_e[0][block_m_idx][band_m_idx] ); + hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[1][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[1][band_m_idx] ), 2 * c_e, &hMcMasa->direction_vector_e[1][block_m_idx][band_m_idx] ); + hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( hMcMasa->direction_vector_m_fx[2][block_m_idx][band_m_idx], hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx], Mult_32_32( norm_tmp_fx, direction_vector_fx[2][band_m_idx] ), 2 * c_e, &hMcMasa->direction_vector_e[2][block_m_idx][band_m_idx] ); + diffuseness_m_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( diffuseness_m_fx[band_m_idx], diffuseness_e[band_m_idx], L_shl( Mult_32_32( reference_power_fx[ts][band_m_idx], diffuseness_vector_fx[band_m_idx] ), 1 ), 2 * c_e - 1, &diffuseness_e[band_m_idx]); + renormalization_factor_diff_fx[band_m_idx] = BASOP_Util_Add_Mant32Exp( renormalization_factor_diff_fx[band_m_idx], renormalization_factor_diff_e[band_m_idx], reference_power_fx[ts][band_m_idx], 2 * c_e - 1, &renormalization_factor_diff_e[band_m_idx]); + } + } + FOR ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + { + Word16 max_e=MIN_16; + FOR ( d = 0; d < DIRAC_NUM_DIMS; d++ ) + { + max_e = s_max( max_e, hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx]); + } + max_e =add(max_e,1);/*1 as guard bit to prevent overflow*/ + FOR ( d = 0; d < DIRAC_NUM_DIMS; d++ ) + { + dir_v_fx[d] = L_shr(hMcMasa->direction_vector_m_fx[d][block_m_idx][band_m_idx], max_e-hMcMasa->direction_vector_e[d][block_m_idx][band_m_idx]); + } + Word16 div_q = sub(31, max_e); + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( dir_v_fx,div_q, &azimuth_m_values_fx[block_m_idx][band_m_idx], &elevation_m_values_fx[block_m_idx][band_m_idx] ); + elevation_m_values_fx[block_m_idx][band_m_idx] = L_add( elevation_m_values_fx[block_m_idx][band_m_idx], L_shr( elevation_m_values_fx[block_m_idx][band_m_idx], 5 ) ); + } + + /* Coherence processing */ + FOR ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) + { + /* Compute absolute values */ + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + FOR ( j = i; j < numAnalysisChannels; j++ ) + { + Word32 temp=BASOP_Util_Add_Mant32Exp(Mult_32_32(COVls[band_m_idx].xr_fx[i][j] , COVls[band_m_idx].xr_fx[i][j]), 2*COVls[band_m_idx].xr_e[i][j],Mult_32_32(COVls[band_m_idx].xi_fx[i][j] , COVls[band_m_idx].xi_fx[i][j]),2* COVls[band_m_idx].xi_e[i][j],&absCOVls_e[i][j]); + absCOVls_fx[i][j] = Sqrt32(temp, &absCOVls_e[i][j]); + } + lsEnergy_fx[i] = absCOVls_fx[i][i]; + lsEnergy_e[i] = absCOVls_e[i][i]; + } + + /* Find loudest channel */ + maxEne_fx = lsEnergy_fx[0]; + maxEne_e = lsEnergy_e[0]; + loudestCh = 0; + FOR ( i = 1; i < numAnalysisChannels; i++ ) + { + IF (EQ_16(BASOP_Util_Cmp_Mant32Exp( lsEnergy_fx[i] , lsEnergy_e[i] , maxEne_fx, maxEne_e),1) ) + { + maxEne_fx = lsEnergy_fx[i]; + maxEne_e = lsEnergy_e[i]; + loudestCh = i; + } + } + + /* Compute surrounding coherence */ + surrCoh_fx = ONE_IN_Q31; + surrCoh_e = 0; + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + IF ( NE_16(i , loudestCh) ) + { + IF ( LT_16(i , loudestCh) ) + { + i1 = i; + i2 = loudestCh; + } + ELSE + { + i1 = loudestCh; + i2 = i; + } + Word16 temp_exp= lsEnergy_e[i1]+ lsEnergy_e[i2]; + Word32 temp = Sqrt32(L_add(Mult_32_32(lsEnergy_fx[i1] , lsEnergy_fx[i2]), EPSILON_FX),&temp_exp); + tempCoh_e = 0; + tempCoh_fx = L_shl(BASOP_Util_Divide3232_Scale(absCOVls_fx[i1][i2] , temp,&tempCoh_e),16); + tempCoh_e = absCOVls_e[i1][i2] - temp_exp + tempCoh_e; + IF ( NE_16(BASOP_Util_Cmp_Mant32Exp( surrCoh_fx, surrCoh_e, tempCoh_fx, tempCoh_e ) , -1) ) + { + surrCoh_fx = tempCoh_fx; + surrCoh_e = tempCoh_e; + } + } + } + surrCoh_fx = L_shl( surrCoh_fx, surrCoh_e ); + surrCoh_e = 0; + surrCoh_fx = Mult_32_32(surrCoh_fx , surrCoh_fx); + surrCoh_fx = ( LT_32(surrCoh_fx , ONE_IN_Q31)) ? surrCoh_fx : ONE_IN_Q31; + surrCoh_fx = ( GT_32(surrCoh_fx , 0) ) ? surrCoh_fx : 0; + /* Compute spread coherence */ + IF ( LT_32(elevation_m_values_fx[block_m_idx][band_m_idx] , NEAR_HORIZONTAL_PLANE_ELEVATION_FX) ) /* Computed only near horizontal plane */ + { + minAngleDist_fx = 754974720;/*Q22*/ + i1 = 0; + currentAzi_fx = azimuth_m_values_fx[block_m_idx][band_m_idx]; + FOR ( i = 0; i < hMcMasa->numHorizontalChannels; i++ ) + { + angleDist_fx = L_abs( L_sub(currentAzi_fx , hMcMasa->ls_azimuth_fx[i]) ); + IF ( GT_32(angleDist_fx , 754974720/*180.0f Q.22*/)) + { + angleDist_fx = L_abs( L_sub(angleDist_fx , 1509949440) ); + } + IF ( LT_32(angleDist_fx , minAngleDist_fx) ) + { + minAngleDist_fx = angleDist_fx; + i1 = i; + } + } + i2 = hMcMasa->leftNearest[i1]; + i3 = hMcMasa->rightNearest[i1]; + Word16 temp_e= add(lsEnergy_e[i2], lsEnergy_e[i3]); + Word32 temp = Sqrt32( Mult_32_32(lsEnergy_fx[i2] , lsEnergy_fx[i3]) + EPSILON_FX ,&temp_e); + IF ( LT_16(i2 , i3 )) + { + stereoCoh_fx = BASOP_Util_Divide3232_Scale(absCOVls_fx[i2][i3] , temp,&stereoCoh_e); + stereoCoh_e = add(sub(absCOVls_e[i2][i3] , temp_e) , stereoCoh_e); + } + ELSE + { + stereoCoh_fx = BASOP_Util_Divide3232_Scale(absCOVls_fx[i3][i2], temp, &stereoCoh_e ); + stereoCoh_e = add(sub(absCOVls_e[i3][i2] , temp_e) , stereoCoh_e); + } + stereoCoh_fx = L_shl( stereoCoh_fx, 16 ); + Word32 temp1, temp2; + Word16 temp1_e, temp2_e; + temp1 = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i2], lsEnergy_e[i2], lsEnergy_fx[i3], lsEnergy_e[i3], &temp1_e ); + temp2 = BASOP_Util_Add_Mant32Exp( temp1, temp1_e, lsEnergy_fx[i1], lsEnergy_e[i1], &temp2_e ); + temp2 = L_add( temp2, EPSILON_FX ); + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp1, temp2, &lsEnergyRelation_e ); + lsEnergyRelation_e = add(lsEnergyRelation_e,sub(temp1_e , temp2_e)); + lsEnergyRelation_fx = L_shl(lsEnergyRelation_fx, 16+lsEnergyRelation_e ); + stereoness_fx = Mult_32_32(stereoCoh_fx , lsEnergyRelation_fx); + stereoness_e = stereoCoh_e; + IF ( LT_16(i1 , i2) ) + { + temp_e = add(lsEnergy_e[i1] , lsEnergy_e[i2]); + tempCoh_fx = BASOP_Util_Divide3232_Scale(absCOVls_fx[i1][i2] , ( Sqrt32( L_add(Mult_32_32(lsEnergy_fx[i1] , lsEnergy_fx[i2]) , EPSILON_FX ),&temp_e) ), &tempCoh_e); + tempCoh_e = add(tempCoh_e,sub(absCOVls_e[i1][i2] , temp_e)); + } + ELSE + { + temp_e = add(lsEnergy_e[i1] , lsEnergy_e[i2]); + tempCoh_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i2][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i2] ), EPSILON_FX ), &temp_e ) ), &tempCoh_e ); + tempCoh_e = add(tempCoh_e,sub(absCOVls_e[i2][i1] , temp_e)); + } + tempCoh_fx = L_shl( tempCoh_fx, 16 ); + IF ( LT_16(i1 , i3) ) + { + temp_e = lsEnergy_e[i1] + lsEnergy_e[i3]; + tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i1][i3], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e ); + tempCoh2_e = add(tempCoh2_e,sub(absCOVls_e[i1][i3] , temp_e)); + } + ELSE + { + temp_e = lsEnergy_e[i1] + lsEnergy_e[i3]; + tempCoh2_fx = BASOP_Util_Divide3232_Scale( absCOVls_fx[i3][i1], ( Sqrt32( L_add( Mult_32_32( lsEnergy_fx[i1], lsEnergy_fx[i3] ), EPSILON_FX ), &temp_e ) ), &tempCoh2_e ); + tempCoh2_e = add(tempCoh2_e,sub(absCOVls_e[i3][i1] , temp_e)); + } + tempCoh2_fx = L_shl( tempCoh2_fx, 16 ); + IF ( EQ_16(BASOP_Util_Cmp_Mant32Exp( tempCoh_fx, tempCoh_e, tempCoh2_fx, tempCoh2_e ) , -1) ) + { + cohPanCoh_fx = tempCoh_fx; + cohPanCoh_e = tempCoh_e; + } + ELSE + { + cohPanCoh_fx = tempCoh2_fx; + cohPanCoh_e = tempCoh2_e; + } + cohPanCoh_fx = L_shl( cohPanCoh_fx, cohPanCoh_e );/*Q31*/ + cohPanCoh_e = 0; + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale(lsEnergy_fx[i2] , L_add( lsEnergy_fx[i1] , EPSILON_FX ), &lsEnergyRelation_e); + lsEnergyRelation_e += lsEnergy_e[i2] - lsEnergy_e[i1]; + tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale(lsEnergy_fx[i1] , L_add( lsEnergy_fx[i2] , EPSILON_FX ), &tempLsEnergyRelation_e); + tempLsEnergyRelation_e += lsEnergy_e[i1] - lsEnergy_e[i2]; + IF ( NE_16(BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ),-1) ) + { + lsEnergyRelation_fx = tempLsEnergyRelation_fx; + lsEnergyRelation_e = tempLsEnergyRelation_e; + } + tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( lsEnergy_fx[i3], L_add( lsEnergy_fx[i1], EPSILON_FX ), &tempLsEnergyRelation_e ); + tempLsEnergyRelation_e = add(tempLsEnergyRelation_e,sub(lsEnergy_e[i3] , lsEnergy_e[i1])); + IF ( NE_16(BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ) , -1) ) + { + lsEnergyRelation_fx = tempLsEnergyRelation_fx; + lsEnergyRelation_e = tempLsEnergyRelation_e; + } + tempLsEnergyRelation_fx = BASOP_Util_Divide3232_Scale(lsEnergy_fx[i1] , ( lsEnergy_fx[i3] + EPSILON_FX ), &tempLsEnergyRelation_e); + tempLsEnergyRelation_e = add(tempLsEnergyRelation_e,sub(lsEnergy_e[i1] , lsEnergy_e[i3])); + IF ( NE_16(BASOP_Util_Cmp_Mant32Exp( lsEnergyRelation_fx, lsEnergyRelation_e, tempLsEnergyRelation_fx, tempLsEnergyRelation_e ) , -1) ) + { + lsEnergyRelation_fx = tempLsEnergyRelation_fx; + lsEnergyRelation_e = tempLsEnergyRelation_e; + } + lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx,16+ lsEnergyRelation_e );/*Q31*/ + cohwideness_fx = Mult_32_32(cohPanCoh_fx , lsEnergyRelation_fx);/*cohPanCoh_e*/ + + IF (EQ_16(BASOP_Util_Cmp_Mant32Exp( cohwideness_fx , cohPanCoh_e, stereoness_fx, stereoness_e),1) ) + { + spreadCoh_fx = cohwideness_fx; + spreadCoh_e = cohPanCoh_e; + } + ELSE + { + spreadCoh_fx = stereoness_fx; + spreadCoh_e = stereoness_e; + } + IF ( LT_16(spreadCoh_e , 0) ) + { + spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); + spreadCoh_e = 0; + } + IF ( GT_32( spreadCoh_fx, L_shl_sat( 1, 31 - spreadCoh_e - 1 /*0.5f with exp=spreadCoh_e*/) ) ) + { + IF (EQ_16(BASOP_Util_Cmp_Mant32Exp(cohwideness_fx , cohPanCoh_e, stereoness_fx, stereoness_e),1) ) + { - for ( i = 0; i < ( *hMcMasa )->num_Cldfb_instances; i++ ) - { - deleteCldfb_ivas( &( ( *hMcMasa )->cldfbAnaEnc[i] ) ); - } + tempCoh_fx = BASOP_Util_Add_Mant32Exp(stereoness_fx , stereoness_e, -L_sub( cohwideness_fx , L_shl(1, 31-cohPanCoh_e-1) ), cohPanCoh_e,&tempCoh_e); + IF ( LT_16(tempCoh_e , 0) ) + { + tempCoh_fx = L_shl( tempCoh_fx, tempCoh_e ); + tempCoh_e = 0; + } + spreadCoh_fx = GT_32( tempCoh_fx , L_shl_sat(1,31- tempCoh_e-1) ) ? tempCoh_fx : L_shl_sat(1, 31 - tempCoh_e - 1); + spreadCoh_e = tempCoh_e; + } + } + IF ( LT_16(spreadCoh_e , 0) ) + { + spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e ); + spreadCoh_e = 0; + } + spreadCoh_fx = ( LT_32(spreadCoh_fx , L_shl_sat(1,31- spreadCoh_e))) ? spreadCoh_fx : L_shl_sat(1,31- spreadCoh_e); + spreadCoh_fx = ( spreadCoh_fx > 0 ) ? spreadCoh_fx : 0; + spreadCoh_fx = L_shl( spreadCoh_fx, spreadCoh_e );/*Q31*/ + /* Compute energy ratio tuning parameter */ + lsEnergySum_fx = 0; + lsEnergySum_e = 0; + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + lsEnergySum_fx = BASOP_Util_Add_Mant32Exp(lsEnergy_fx[i],lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e,&lsEnergySum_e); + } + lsEnergySum_fx = L_add_sat(lsEnergySum_fx,EPSILON_FX); + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale(temp1, lsEnergySum_fx, &lsEnergyRelation_e ); + lsEnergyRelation_e = add(lsEnergyRelation_e,sub(temp1_e , lsEnergySum_e)); + lsEnergyRelation_fx = L_shl(lsEnergyRelation_fx,16+lsEnergyRelation_e ); + stereoRatio_fx = L_sub(Mult_32_32(L_shl_sat(stereoCoh_fx, stereoCoh_e), lsEnergyRelation_fx) ,surrCoh_fx); + + lsEnergyRelation_fx = BASOP_Util_Divide3232_Scale( temp2, lsEnergySum_fx, &lsEnergyRelation_e ); + lsEnergyRelation_e = add(lsEnergyRelation_e,sub(temp2_e , lsEnergySum_e)); + lsEnergyRelation_fx = L_shl( lsEnergyRelation_fx, 16 + lsEnergyRelation_e ); + cohPanRatio_fx = L_sub( Mult_32_32( cohPanCoh_fx, lsEnergyRelation_fx ), surrCoh_fx ); + + cohRatio_fx = GT_32( stereoRatio_fx , cohPanRatio_fx ) ? stereoRatio_fx : cohPanRatio_fx;/*Q31*/ + cohRatio_fx = ( LT_32(cohRatio_fx , ONE_IN_Q31) ) ? cohRatio_fx : ONE_IN_Q31; + cohRatio_fx = ( GT_32(cohRatio_fx , 0) ) ? cohRatio_fx : 0; + } + ELSE /* Otherwise, set spread coherence to zero */ + { + spreadCoh_fx = 0; + cohRatio_fx = 0; + lsEnergySum_fx = 0; + FOR ( i = 0; i < numAnalysisChannels; i++ ) + { + lsEnergySum_fx = BASOP_Util_Add_Mant32Exp( lsEnergy_fx[i], lsEnergy_e[i], lsEnergySum_fx, lsEnergySum_e, &lsEnergySum_e ); + } + lsEnergySum_fx =L_add_sat(lsEnergySum_fx, EPSILON_FX); + } - /* intensity 3-dim */ - for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) - { - for ( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) - { - free( ( *hMcMasa )->direction_vector_m[i][j] ); - ( *hMcMasa )->direction_vector_m[i][j] = NULL; + /* Store values */ + spreadCoherence_fx[block_m_idx][band_m_idx] = spreadCoh_fx;/*Q31*/ + surroundingCoherence_fx[block_m_idx][band_m_idx] = surrCoh_fx;/*Q31*/ + coherentEnergyRatio_fx[band_m_idx] = cohRatio_fx;/*Q31*/ } - for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + /* Determine energy ratios */ + FOR ( band_m_idx = 0; band_m_idx < hMcMasa->nbands; band_m_idx++ ) { - free( ( *hMcMasa )->buffer_intensity_real[i][j] ); - ( *hMcMasa )->buffer_intensity_real[i][j] = NULL; - } - - free( ( *hMcMasa )->direction_vector_m[i] ); - ( *hMcMasa )->direction_vector_m[i] = NULL; - } - - for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) - { - free( ( *hMcMasa )->buffer_intensity_real_vert[j] ); - ( *hMcMasa )->buffer_intensity_real_vert[j] = NULL; - } - - free( ( *hMcMasa )->hMasaOut ); - ( *hMcMasa )->hMasaOut = NULL; - free( ( *hMcMasa )->sph_grid16 ); - ( *hMcMasa )->sph_grid16 = NULL; - - free( ( *hMcMasa ) ); - ( *hMcMasa ) = NULL; - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_mcmasa_ana() - * - * Multichannel MASA analysis - *--------------------------------------------------------------------------*/ - -void ivas_mcmasa_ana( - MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */ - float data_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ - const int16_t input_frame, /* i : Input frame size */ - const int16_t nchan_transport, /* i : Number of transport channels */ - const int16_t nchan_inp /* i : Number of input channels */ -) -{ - int16_t i; - float elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - float azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - float energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - float spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - float surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - + Word16 diffuseness_m_e; + IF ( GT_32(renormalization_factor_diff_fx[band_m_idx] , EPSILON_FX) ) + { + diffuseness_m_fx[band_m_idx] =BASOP_Util_Divide3232_Scale(diffuseness_m_fx[band_m_idx], renormalization_factor_diff_fx[band_m_idx], &diffuseness_m_e); + diffuseness_m_e = add(diffuseness_m_e,sub(diffuseness_e[band_m_idx] , renormalization_factor_diff_e[band_m_idx])); + diffuseness_m_fx[band_m_idx] = L_shl_sat( diffuseness_m_fx[band_m_idx], 16+diffuseness_m_e ); + } + ELSE + { + diffuseness_m_fx[band_m_idx] = 0; + } - /* Sum center and LFE, move surround channels */ - v_add( data_f[2], data_f[3], data_f[2], input_frame ); - for ( i = 4; i < nchan_inp; i++ ) - { - mvr2r( data_f[i], data_f[i - 1], input_frame ); + energyRatio_fx[block_m_idx][band_m_idx] = L_sub(ONE_IN_Q31 , diffuseness_m_fx[band_m_idx]); + energyRatio_fx[block_m_idx][band_m_idx] = GT_32( energyRatio_fx[block_m_idx][band_m_idx] , coherentEnergyRatio_fx[band_m_idx] ) ? energyRatio_fx[block_m_idx][band_m_idx] : coherentEnergyRatio_fx[band_m_idx]; + } } - - /* Analysis */ - ivas_mcmasa_param_est_ana( hMcMasa, data_f, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence, input_frame, nchan_inp ); - - /* Create MASA metadata buffer from the estimated values */ - ivas_create_masa_out_meta( hMcMasa->hMasaOut, hMcMasa->sph_grid16, nchan_transport, elevation_m_values, azimuth_m_values, energyRatio, spreadCoherence, surroundingCoherence ); - - /* Downmix */ - ivas_mcmasa_dmx( hMcMasa, data_f, input_frame, nchan_transport, nchan_inp ); - return; } - - -/*--------------------------------------------------------------------------* - * Local functions - *--------------------------------------------------------------------------*/ - -/* Estimate metadata parameters for McMASA */ +#endif // IVAS_FLOAT_FIXED void ivas_mcmasa_param_est_ana( MCMASA_ANA_HANDLE hMcMasa, /* i : McMASA analyzer structure */ float data_f[][L_FRAME48k], /* i : Audio frame in MC-format */ @@ -901,6 +1901,174 @@ static void ivas_mcmasa_dmx( } +#ifdef IVAS_FLOAT_FIXED +static void ivas_mcmasa_dmx_fx( + MCMASA_ANA_HANDLE hMcMasa, + Word32 data_f_fx[][L_FRAME48k], + Word16 data_e, + const Word16 input_frame, + const Word16 nchan_transport, + const Word16 nchan_inp ) +{ + int16_t i, j; + int16_t numAnalysisChannels; + + Word32 dmx_c_fx; + Word32 multiChEne_fx, downmixEne_fx; + Word32 prevEQ_fx, currEQ_fx, instEQ_fx; + Word32 alpha_fx, L_tmp, L_tmp1; + Word16 multiChEne_e, scale, downmixEne_e = 0, prevEQ_e, tmp, currEQ_e, instEQ_e; + + numAnalysisChannels = nchan_inp - 1; + + multiChEne_fx = 0; + multiChEne_e = 0; + + FOR ( j = 0; j < numAnalysisChannels; j++ ) + { + FOR ( i = 0; i < input_frame; i++ ) + { + L_tmp1 = BASOP_Util_Add_Mant32Exp(data_f_fx[j][i], data_e, 0, 0, &scale); + L_tmp = Mpy_32_32(L_tmp1, L_tmp1); // data_e + data_e + multiChEne_fx = BASOP_Util_Add_Mant32Exp(L_tmp, scale + scale, multiChEne_fx, multiChEne_e, &scale); + multiChEne_e = scale; + } + } + + IF ( nchan_transport == 2 ) + { + Word16 numSideChannels; /* Channels other than left, right, center */ + Word16 leftIndex, rightIndex; + + numSideChannels = numAnalysisChannels / 2 - 1; + FOR ( j = 0; j < numSideChannels; j++ ) + { + leftIndex = j * 2 + 3; + rightIndex = j * 2 + 4; + + FOR ( i = 0; i < input_frame; i++ ) + { + data_f_fx[0][i] = L_add(data_f_fx[0][i], data_f_fx[leftIndex][i] ); + data_f_fx[1][i] = L_add(data_f_fx[1][i] , data_f_fx[rightIndex][i] ); + + } + } + + FOR ( i = 0; i < input_frame; i++ ) + { + dmx_c_fx = (Word32) W_shr(W_mult_32_32(INV_SQRT2_FX, data_f_fx[2][i]), 32 ); + + data_f_fx[0][i] = L_add( dmx_c_fx, data_f_fx[0][i] ); + data_f_fx[1][i] = L_add( dmx_c_fx, data_f_fx[1][i] ); + + } + } + ELSE IF ( nchan_transport == 1 ) + { + FOR ( i = 0; i < input_frame; i++ ) + { + FOR ( j = 1; j < numAnalysisChannels; j++ ) + { + data_f_fx[0][i] = L_add( data_f_fx[0][i], data_f_fx[j][i] ); + } + } + } + + downmixEne_fx = 0; + + FOR ( j = 0; j < nchan_transport; j++ ) + { + FOR ( i = 0; i < input_frame; i++ ) + { + L_tmp1 = BASOP_Util_Add_Mant32Exp(data_f_fx[j][i], data_e, 0, 0, &scale); + L_tmp = Mpy_32_32(L_tmp1, L_tmp1); // data_e + data_e + downmixEne_fx = BASOP_Util_Add_Mant32Exp(L_tmp, scale + scale, downmixEne_fx, downmixEne_e, &downmixEne_e); + } + } + + alpha_fx = 214748364; // Q31 + + L_tmp = Mpy_32_32(alpha_fx, multiChEne_fx); + L_tmp1 = Mpy_32_32( 1932735284, hMcMasa->prevMultiChEne_fx ); + hMcMasa->prevMultiChEne_fx = BASOP_Util_Add_Mant32Exp(L_tmp, multiChEne_e, L_tmp1, hMcMasa->prevMultiChEne_e, &hMcMasa->prevMultiChEne_e ); + + + L_tmp = Mpy_32_32(alpha_fx, downmixEne_fx); + L_tmp1 = Mpy_32_32(1932735284, hMcMasa->prevDownmixEne_fx); + hMcMasa->prevDownmixEne_fx = BASOP_Util_Add_Mant32Exp(L_tmp, downmixEne_e, L_tmp1, hMcMasa->prevDownmixEne_e, &hMcMasa->prevDownmixEne_e); + + prevEQ_fx = hMcMasa->prevEQ_fx; + prevEQ_e = hMcMasa->prevEQ_e; + + tmp = BASOP_Util_Divide3232_Scale(hMcMasa->prevMultiChEne_fx, L_add(hMcMasa->prevDownmixEne_fx, EPSILON_FX), &scale); + currEQ_e = scale + ( hMcMasa->prevMultiChEne_e - hMcMasa->prevDownmixEne_e); + currEQ_fx = Sqrt32(L_deposit_h(tmp), &currEQ_e); + + hMcMasa->prevEQ_fx = currEQ_fx; + hMcMasa->prevEQ_e = currEQ_e; + + FOR ( i = 0; i < input_frame; i++ ) + { + L_tmp = Mpy_32_32(L_deposit_h(hMcMasa->interpolator_fx[i]), currEQ_fx); + L_tmp1 = L_sub(1073741824, L_lshr( L_deposit_h(hMcMasa->interpolator_fx[i]), 1 ) ); + L_tmp1 = Mpy_32_32( L_tmp1, prevEQ_fx ); + instEQ_fx = BASOP_Util_Add_Mant32Exp(L_tmp, currEQ_e, L_tmp1, prevEQ_e + 1, &instEQ_e); + + FOR ( j = 0; j < nchan_transport; j++ ) + { + data_f_fx[j][i] = Mpy_32_32( instEQ_fx, data_f_fx[j][i] ); + + data_f_fx[j][i] = L_shl(data_f_fx[j][i], instEQ_e); + } + } + + return; +} + +#endif + +#ifdef IVAS_FLOAT_FIXED +/* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */ +static void compute_cov_mtx_fx( + Word32 sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */ + Word32 si[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, imag, s[ch][freq] */ + const Word16 freq, /* i : Freq to process */ + const Word16 N, /* i : Number of channels */ + CovarianceMatrix *COVls, /* o : Output matrix, contains upper part of cov mtx */ + Word16 inp_exp/*Stores exponent for temp*/ +) +{ + Word16 i, j; + Word32 a, b, c, d; + Word32 temp; + Word16 norm_a,norm_b,norm_c, norm_d; + Word16 shift; + FOR ( i = 0; i < N; i++ ) + { + a = sr[i][freq]; + b = si[i][freq]; + norm_a = norm_l( a ); + norm_b = norm_l( b ); + a = L_shl( a, norm_a);/*inp_exp-norm_a*/ + b = L_shl( b, norm_b);/*inp_exp-norm_b*/ + FOR ( j = i; j < N; j++ ) + { + c = sr[j][freq]; + d = si[j][freq]; + norm_c= norm_l( c ); + norm_d = norm_l( d ); + c = L_shl( c, norm_c );/*inp_exp-norm_c*/ + d = L_shl( d, norm_d );/*inp_exp-norm_d*/ + temp = BASOP_Util_Add_Mant32Exp( Mult_32_32( a, c ), 2*inp_exp - norm_a-norm_c, Mult_32_32( b, d ), 2 * inp_exp - norm_b - norm_d,&shift);/*exp=inp_exp-norm_ab+inp_exp-norm_cd*/ + COVls->xr_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xr_fx[i][j], COVls->xr_e[i][j], temp,shift,&COVls->xr_e[i][j]); + temp = BASOP_Util_Add_Mant32Exp(Mult_32_32( b, c ), 2 * inp_exp - norm_b - norm_c,-Mult_32_32( a, d ), 2 * inp_exp - norm_a - norm_d, &shift); + COVls->xi_fx[i][j] = BASOP_Util_Add_Mant32Exp( COVls->xi_fx[i][j], COVls->xi_e[i][j], temp, shift,&COVls->xi_e[i][j]); + } + } + + return; +} +#endif /* Compute covariance matrix, i.e., xT * conj(x), and accumulate to the output */ static void compute_cov_mtx( float sr[MCMASA_MAX_ANA_CHANS][CLDFB_NO_CHANNELS_MAX], /* i : Input matrix, real, s[ch][freq] */ @@ -934,6 +2102,80 @@ static void compute_cov_mtx( * * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void computeVerticalDiffuseness_fx( + Word32 **buffer_intensity, /* i : Intensity vectors */ + const Word32 *buffer_energy, /* i : Energy */ + const Word16 num_freq_bands, /* i : Number of frequency bands */ + Word32 *diffuseness , /* o : Estimated diffuseness */ + Word16 *buffer_intensity_q, + Word16 *buffer_energy_q +) +{ + Word32 intensity_slow[MASA_FREQUENCY_BANDS]; + Word32 intensity_slow_abs[MASA_FREQUENCY_BANDS]; + Word32 energy_slow[MASA_FREQUENCY_BANDS]; + Word16 i, k; + Word32 tmp = 0; + const Word32 *p_tmp_c; + Word16 intensity_slow_e[MASA_FREQUENCY_BANDS], energy_slow_e[MASA_FREQUENCY_BANDS]; + + /* Set variables to zero */ + set32_fx( intensity_slow, 0, MASA_FREQUENCY_BANDS ); + set32_fx( energy_slow, 0, MASA_FREQUENCY_BANDS ); + set16_fx(intensity_slow_e, 0, MASA_FREQUENCY_BANDS ); + set16_fx(energy_slow_e, 0, MASA_FREQUENCY_BANDS ); + + FOR ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; ++i ) + { + /* Energy slow */ + p_tmp_c = buffer_energy + i * num_freq_bands; + FOR ( k = 0; k < num_freq_bands; k++ ) + { + energy_slow[k] = BASOP_Util_Add_Mant32Exp( energy_slow[k], energy_slow_e[k],*( p_tmp_c ), 31-buffer_energy_q[i],&energy_slow_e[k]);/*q=min_q*/ + p_tmp_c++; + } + + /* Intensity slow */ + FOR ( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow[k] = BASOP_Util_Add_Mant32Exp(intensity_slow[k], intensity_slow_e[k], buffer_intensity[i][k],31- buffer_intensity_q[i],&intensity_slow_e[k]);/*q=min_q*/ + } + } + + /* Compute absolute value */ + FOR ( k = 0; k < num_freq_bands; k++ ) + { + intensity_slow_abs[k] = L_abs( intensity_slow[k] );/*min_q*/ + } + + /* Compute Diffuseness */ + FOR( i = 0; i < num_freq_bands; ++i ) + { + Word16 tmp_e1, tmp_e2; + tmp = BASOP_Util_Divide3232_Scale( intensity_slow_abs[i], ( energy_slow[i] + EPSILON_FX_SMALL), &tmp_e1 ); + tmp_e1 += intensity_slow_e[i] - energy_slow_e[i]; + tmp = BASOP_Util_Divide3232_Scale( tmp - L_shr( VERTICAL_ENERGY_RATIO_OFFSET_FX, tmp_e1 ), ONE_IN_Q15 - VERTICAL_ENERGY_RATIO_OFFSET_FX, &tmp_e2 ); /* Tuned to avoid effect due to ambience of vertically un-even setups */ + tmp_e2 += tmp_e1; + tmp = L_sub( L_shl( 1, 15 - tmp_e2 ), tmp ); + IF( tmp < 0 ) + { + tmp = 0; + } + ELSE IF( tmp >= L_shl( 1, 15 - tmp_e2 ) ) + { + tmp = ONE_IN_Q31; + } + ELSE + { + tmp = L_shl( tmp, 16 + tmp_e2 ); + } + diffuseness[i] = tmp; + } + + return; +} +#endif // IVAS_FLOAT_FIXED static void computeVerticalDiffuseness( float **buffer_intensity, /* i : Intensity vectors */ @@ -987,6 +2229,68 @@ static void computeVerticalDiffuseness( return; } +#ifdef IVAS_FLOAT_FIXED +static void computeEvenLayout_fx( + const Word32 *ls_azimuth, + Word32 *ls_azimuth_even, + const Word16 numChannels ) +{ + Word16 i; + Word16 j; + Word32 ls_azimuth_temp[MCMASA_MAX_ANA_CHANS]; + Word32 ls_azimuth_even_ordered[MCMASA_MAX_ANA_CHANS]; + Word16 ls_azimuth_order[MCMASA_MAX_ANA_CHANS]; + Word32 smallestAzimuth; + Word16 smallestAzimuthIndex; + Word32 lsSpacing; + UWord8 oddLayout; + Word32 startAzimuth; + Word16 numChannelsHalf; + + lsSpacing = L_shl(L_mult0(360 , div_s(1,numChannels)),6);/*Q.21*/ + oddLayout = numChannels % 2; + numChannelsHalf = shr(numChannels , 1); + + Copy32( ls_azimuth, ls_azimuth_temp, numChannels ); + Scale_sig32( ls_azimuth_temp, numChannels, -1 );/*Q.21*/ + FOR ( i = 0; i < numChannels; i++ ) + { + smallestAzimuth = L_shl(1000,21);/*Q21*/ + smallestAzimuthIndex = 0; + FOR ( j = 0; j < numChannels; j++ ) + { + IF ( LT_32(ls_azimuth_temp[j] , smallestAzimuth) ) + { + smallestAzimuth = ls_azimuth_temp[j]; + smallestAzimuthIndex = j; + } + } + ls_azimuth_order[i] = smallestAzimuthIndex; + ls_azimuth_temp[smallestAzimuthIndex] = L_shl(1000, 21); + } + + IF ( oddLayout ) + { + startAzimuth = W_extract_l(W_mult0_32_32(-lsSpacing , shl( numChannelsHalf ,1)));/*Q.22*/ + } + ELSE + { + startAzimuth = W_extract_l(W_mult0_32_32(-lsSpacing , sub(shl(numChannelsHalf,1) , 1 )));/*Q.22*/ + } + + FOR ( i = 0; i < numChannels; i++ ) + { + ls_azimuth_even_ordered[i] = W_extract_l(W_add(W_mult_32_16(lsSpacing,i) , startAzimuth));/*Q.22*/ + } + + FOR ( i = 0; i < numChannels; i++ ) + { + ls_azimuth_even[ls_azimuth_order[i]] = L_shl(L_shr(L_add(ls_azimuth_even_ordered[i],ONE_IN_Q21),22),22);/*((a+2^21)/2^22)*2^22*/ + } + + return; +} +#endif // IVAS_FLOAT_FIXED static void computeEvenLayout( const float *ls_azimuth, diff --git a/lib_rend/ivas_objectRenderer_mix.c b/lib_rend/ivas_objectRenderer_mix.c index cfb3ec5dd..5696571f9 100644 --- a/lib_rend/ivas_objectRenderer_mix.c +++ b/lib_rend/ivas_objectRenderer_mix.c @@ -396,9 +396,10 @@ ivas_error TDREND_MIX_Init( { ivas_error error; - hBinRendererTd->Gain = 1.0f; #ifdef IVAS_FLOAT_FIXED hBinRendererTd->Gain_fx = ONE_IN_Q14; +#else + hBinRendererTd->Gain = 1.0f; #endif /* Init source list */ diff --git a/lib_rend/ivas_objectRenderer_sources.c b/lib_rend/ivas_objectRenderer_sources.c index 39347f1bf..1b566cb9f 100644 --- a/lib_rend/ivas_objectRenderer_sources.c +++ b/lib_rend/ivas_objectRenderer_sources.c @@ -1360,15 +1360,16 @@ void TDREND_SRC_Init( Src_p->itd = 0; Src_p->previtd = 0; Src_p->filterlength = 1; /* Init to unit impulse of length 1 */ +#ifndef IVAS_FLOAT_FIXED set_f( Src_p->mem_itd, 0.0f, ITD_MEM_LEN ); set_f( Src_p->mem_hrf_left, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); set_f( Src_p->mem_hrf_right, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); +#endif #ifdef IVAS_FLOAT_FIXED set32_fx( Src_p->mem_itd_fx, 0, ITD_MEM_LEN ); set32_fx( Src_p->mem_hrf_left_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); set32_fx( Src_p->mem_hrf_right_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 ); -#endif - +#else set_f( Src_p->hrf_left_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); set_f( Src_p->hrf_right_prev, 0.0f, SFX_SPAT_BIN_MAX_FILTER_LENGTH ); Src_p->hrf_left_prev[0] = 1; @@ -1377,6 +1378,7 @@ void TDREND_SRC_Init( Src_p->elev_prev = 0.0f; Src_p->Gain = 1; Src_p->prevGain = 1.0f; +#endif #ifdef IVAS_FLOAT_FIXED set32_fx(Src_p->hrf_left_prev_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH); set32_fx(Src_p->hrf_right_prev_fx, 0, SFX_SPAT_BIN_MAX_FILTER_LENGTH); diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index bc6836520..7e20e2671 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -2578,6 +2578,16 @@ ivas_error ivas_mcmasa_ana_open( const AUDIO_CONFIG inConfig, /* i : Input config */ int32_t input_Fs /* i : Sampling frequency */ ); +#ifdef IVAS_FLOAT_FIXED +void ivas_mcmasa_ana_fx( + MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */ + Word32 data[][L_FRAME48k], /* i/o: Input / transport audio signals */ + Word16 q_data, + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_transport, /* i : Number of transport channels */ + const Word16 nchan_inp /* i : Number of input channels */ +); +#endif // IVAS_FLOAT_FIXED void ivas_mcmasa_ana( MCMASA_ANA_HANDLE hMcMasa, /* i/o: McMASA encoder handle */ diff --git a/lib_rend/ivas_reflections.c b/lib_rend/ivas_reflections.c index dcb41e6aa..2805751e3 100644 --- a/lib_rend/ivas_reflections.c +++ b/lib_rend/ivas_reflections.c @@ -138,7 +138,7 @@ ivas_error ivas_er_init( const AUDIO_CONFIG inConfig ) { ivas_error error; - uint8_t i; + UWord8 i; /* Set to defaults for shoebox */ reflections->is_ready = 0; @@ -152,15 +152,6 @@ ivas_error ivas_er_init( move16(); move32(); - -#if 0 -// Commenting this code as the values are initialized in below loop. -// This initialization is redundant. - reflections->user_origin[0] = 0.0f; - reflections->user_origin[1] = 0.0f; - reflections->user_origin[2] = ER_LIST_HEIGHT; -#endif - /* Store scene origin if present */ FOR( i = 0; i < 3; i++ ) @@ -173,13 +164,13 @@ ivas_error ivas_er_init( ivas_shoebox_init( &reflections->shoebox_lib, &reflections->shoebox_lib.cal ); /* Set mode */ - IF( ( error = ivas_er_set_reflections_mode( reflections, inConfig ) ) != IVAS_ERR_OK ) + IF( NE_32 ( ( error = ivas_er_set_reflections_mode( reflections, inConfig ) ), IVAS_ERR_OK ) ) { return error; } /* Compute the static reflections (first frame) */ - IF( ( error = ivas_er_compute_reflections( reflections ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_er_compute_reflections( reflections ) ), IVAS_ERR_OK ) ) { return error; } @@ -190,7 +181,7 @@ ivas_error ivas_er_init( } set_s( (int16_t *) reflections->closest_ch_idx, 0, reflections->n_total_reflections ); - IF( ( error = getAudioConfigNumChannels( reflections->audio_config, &( reflections->nchan_out ) ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = getAudioConfigNumChannels( reflections->audio_config, &( reflections->nchan_out ) ) ), IVAS_ERR_OK ) ) { return error; } @@ -203,6 +194,7 @@ ivas_error ivas_er_init( /* Update flag to indicate that reflection module is ready to process */ reflections->is_ready = 1; + move16(); return error; } @@ -215,6 +207,165 @@ ivas_error ivas_er_init( Function sets the ER source positions based on the audio config *-----------------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_er_set_reflections_mode( + er_struct_t *reflections, + const AUDIO_CONFIG inConfig ) +{ + ivas_error error; + UWord16 ch; + error = IVAS_ERR_OK; + + IF ( EQ_32( reflections->audio_config, inConfig ) ) + { + return error; + } + + reflections->is_ready = 0; + move16(); + reflections->audio_config = inConfig; + + SWITCH ( reflections->audio_config ) + { + case IVAS_AUDIO_CONFIG_MONO: + reflections->shoebox_data.n_sources = 1; + reflections->n_LC_sources = 1; + reflections->LC_mixing = LC_mixing_5_1; + move16(); + move16(); + move16(); + + reflections->source_positions_fx[0] = 0; + reflections->source_positions_fx[1] = 0; + reflections->source_positions_fx[2] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + BREAK; + case IVAS_AUDIO_CONFIG_STEREO: + reflections->shoebox_data.n_sources = 2; + reflections->n_LC_sources = 2; + reflections->LC_mixing = LC_mixing_5_1; + move16(); + move16(); + move16(); + + FOR ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP2_idx[ch]; + reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP2_idx[ch]; + reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + } + BREAK; + case IVAS_AUDIO_CONFIG_5_1: + reflections->shoebox_data.n_sources = 5; + reflections->n_LC_sources = 3; + reflections->LC_mixing = LC_mixing_5_1; + move16(); + move16(); + move16(); + + FOR ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP6_idx[ch]; + reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP6_idx[ch]; + reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + } + BREAK; + case IVAS_AUDIO_CONFIG_7_1: + reflections->shoebox_data.n_sources = 7; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_7_1; + move16(); + move16(); + move16(); + FOR ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP12_idx[ch]; + reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP12_idx[ch]; + reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + } + BREAK; + case IVAS_AUDIO_CONFIG_5_1_2: + reflections->shoebox_data.n_sources = 7; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_5_1_2; + move16(); + move16(); + move16(); + FOR ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP14_idx[ch]; + reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP14_idx[ch]; + reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + } + BREAK; + case IVAS_AUDIO_CONFIG_5_1_4: + reflections->shoebox_data.n_sources = 9; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_5_1_4; + move16(); + move16(); + move16(); + FOR ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP16_idx[ch]; + reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP16_idx[ch]; + reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + } + BREAK; + case IVAS_AUDIO_CONFIG_7_1_4: + reflections->shoebox_data.n_sources = 11; + reflections->n_LC_sources = 5; + reflections->LC_mixing = LC_mixing_7_1_4; + move16(); + move16(); + move16(); + FOR ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) + { + reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP19_idx[ch]; + reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP19_idx[ch]; + reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; + move32(); + move32(); + move32(); + } + BREAK; + case IVAS_AUDIO_CONFIG_HOA3: + reflections->use_er = 0; + move16(); + BREAK; + case IVAS_AUDIO_CONFIG_HOA2: + reflections->use_er = 0; + move16(); + BREAK; + case IVAS_AUDIO_CONFIG_FOA: + reflections->use_er = 0; + move16(); + BREAK; + default: + reflections->audio_config = IVAS_AUDIO_CONFIG_INVALID; + return IVAS_ERROR( IVAS_ERR_INVALID_ER_PARAM, "Unsupported reflections mode" ); + } + + return error; +} +#else ivas_error ivas_er_set_reflections_mode( er_struct_t *reflections, const AUDIO_CONFIG inConfig ) @@ -237,15 +388,11 @@ ivas_error ivas_er_set_reflections_mode( reflections->shoebox_data.n_sources = 1; reflections->n_LC_sources = 1; reflections->LC_mixing = LC_mixing_5_1; -#ifndef IVAS_FLOAT_FIXED + reflections->source_positions[0] = 0; reflections->source_positions[1] = 0; reflections->source_positions[2] = ER_RADIUS; -#else - reflections->source_positions_fx[0] = 0; - reflections->source_positions_fx[1] = 0; - reflections->source_positions_fx[2] = ER_RADIUS_FX; -#endif + break; case IVAS_AUDIO_CONFIG_STEREO: reflections->shoebox_data.n_sources = 2; @@ -253,17 +400,9 @@ ivas_error ivas_er_set_reflections_mode( reflections->LC_mixing = LC_mixing_5_1; for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { -#ifndef IVAS_FLOAT_FIXED reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP2[ch] ); reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP2[ch] ); reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; - -#else - reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP2_idx[ch]; - reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP2_idx[ch]; - reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; - -#endif } break; case IVAS_AUDIO_CONFIG_5_1: @@ -272,15 +411,9 @@ ivas_error ivas_er_set_reflections_mode( reflections->LC_mixing = LC_mixing_5_1; for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { -#ifndef IVAS_FLOAT_FIXED reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP6[ch] ); reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP6[ch] ); reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; -#else - reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP6_idx[ch]; - reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP6_idx[ch]; - reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; -#endif } break; case IVAS_AUDIO_CONFIG_7_1: @@ -289,15 +422,9 @@ ivas_error ivas_er_set_reflections_mode( reflections->LC_mixing = LC_mixing_7_1; for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { -#ifndef IVAS_FLOAT_FIXED reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP12[ch] ); reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP12[ch] ); reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; -#else - reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP12_idx[ch]; - reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP12_idx[ch]; - reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; -#endif } break; case IVAS_AUDIO_CONFIG_5_1_2: @@ -306,15 +433,9 @@ ivas_error ivas_er_set_reflections_mode( reflections->LC_mixing = LC_mixing_5_1_2; for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { -#ifndef IVAS_FLOAT_FIXED reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP14[ch] ); reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP14[ch] ); reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; -#else - reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP14_idx[ch]; - reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP14_idx[ch]; - reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; -#endif } break; case IVAS_AUDIO_CONFIG_5_1_4: @@ -323,15 +444,9 @@ ivas_error ivas_er_set_reflections_mode( reflections->LC_mixing = LC_mixing_5_1_4; for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { -#ifndef IVAS_FLOAT_FIXED reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP16[ch] ); reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP16[ch] ); reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; -#else - reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP16_idx[ch]; - reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP16_idx[ch]; - reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; -#endif } break; case IVAS_AUDIO_CONFIG_7_1_4: @@ -340,15 +455,9 @@ ivas_error ivas_er_set_reflections_mode( reflections->LC_mixing = LC_mixing_7_1_4; for ( ch = 0; ch < reflections->shoebox_data.n_sources; ch++ ) { -#ifndef IVAS_FLOAT_FIXED reflections->source_positions[3 * ch] = deg2rad( ls_azimuth_CICP19[ch] ); reflections->source_positions[1 + ( 3 * ch )] = deg2rad( ls_elevation_CICP19[ch] ); reflections->source_positions[2 + ( 3 * ch )] = ER_RADIUS; -#else - reflections->source_positions_fx[3 * ch] = ls_azimuth_CICP19_idx[ch]; - reflections->source_positions_fx[1 + ( 3 * ch )] = ls_elevation_CICP19_idx[ch]; - reflections->source_positions_fx[2 + ( 3 * ch )] = ER_RADIUS_FX; -#endif } break; case IVAS_AUDIO_CONFIG_HOA3: @@ -368,6 +477,8 @@ ivas_error ivas_er_set_reflections_mode( return error; } +#endif + /*-----------------------------------------------------------------------------------------* Function ivas_er_encoder_init() @@ -449,12 +560,16 @@ ivas_error ivas_er_encoder_init( ivas_error error = IVAS_ERR_OK; Word16 i, j, src_idx; Word16 min_index_fx = 0; + move16(); Word32 rad_el_angle, rad_az_angle, tmp_data_fx, p_x_src_fx, p_y_src_fx, p_z_src_fx; Word16 el_angle_cos, az_angle_cos, el_angle_sin, az_angle_sin; Word32 p_x_fx, p_y_fx, p_z_fx, tmp_fx, tmp_data, dist_fx, min_dist_fx = 0; + move32(); Word32 *src_pos_ptr_fx; Word16 q_format, tmp16, min_qformat = 0; + move16(); + IF( reflections == NULL ) @@ -535,12 +650,12 @@ ivas_error ivas_er_encoder_init( tmp_fx = L_mac( tmp_fx, tmp16, tmp16 ); // Q.27 q_format = Q31 - Q27; dist_fx = Sqrt32( tmp_fx, &q_format ); - if ( EQ_32( dist_fx, 0 ) ) + IF ( EQ_32( dist_fx, 0 ) ) { q_format = 0; move16(); } - if ( LE_16( q_format, 0 ) ) + IF ( LE_16( q_format, 0 ) ) { dist_fx = L_shl( dist_fx, q_format ); // Q31 q_format = 0; @@ -556,13 +671,13 @@ ivas_error ivas_er_encoder_init( move16(); move16(); } - else + ELSE { - if ( LE_16( q_format, min_qformat ) ) + IF ( LE_16( q_format, min_qformat ) ) { - if ( EQ_16( q_format, min_qformat ) ) + IF ( EQ_16( q_format, min_qformat ) ) { - if ( LT_32( dist_fx, min_dist_fx ) ) + IF ( LT_32( dist_fx, min_dist_fx ) ) { min_dist_fx = dist_fx; min_index_fx = j; @@ -570,7 +685,7 @@ ivas_error ivas_er_encoder_init( move16(); } } - else + ELSE { min_dist_fx = dist_fx; min_index_fx = j; @@ -584,7 +699,7 @@ ivas_error ivas_er_encoder_init( } } - reflections->closest_ch_idx[i] = (uint16_t) min_index_fx; + reflections->closest_ch_idx[i] = (UWord16) min_index_fx; move16(); } } @@ -605,46 +720,25 @@ ivas_error ivas_er_compute_reflections( er_struct_t *reflections ) { ivas_error error = IVAS_ERR_OK; - uint16_t circ_len, i, j; -#ifndef IVAS_FLOAT_FIXED - float tmp; -#else + UWord16 circ_len, i, j; UWord32 tmp_fx, tmp_fx1; UWord16 tmp_fx_hi, tmp_fx_lo; -#endif reflections->is_ready = 0; + move16(); /* Disabled case */ - if ( reflections->audio_config == IVAS_AUDIO_CONFIG_INVALID ) + IF ( EQ_32( reflections->audio_config, IVAS_AUDIO_CONFIG_INVALID ) ) { return error; } /* Run shoebox with current reflection parameters */ -#ifndef IVAS_FLOAT_FIXED - ivas_shoebox_set_scene( &( reflections->shoebox_lib ), &( reflections->shoebox_data ), reflections->shoebox_lib.cal.list_orig, - reflections->source_positions, reflections->is_cartesian, reflections->is_relative ); -#else ivas_shoebox_set_scene( &( reflections->shoebox_lib ), &( reflections->shoebox_data ), reflections->shoebox_lib.cal.list_orig_fx, reflections->source_positions_fx, reflections->is_cartesian, reflections->is_relative ); -#endif - /* Convert reflection times in seconds to samples and keep track of max */ circ_len = 0; -#ifndef IVAS_FLOAT_FIXED - - for ( i = 0; i < reflections->shoebox_data.n_sources; i++ ) - { - for ( j = 0; j < reflections->shoebox_data.n_ref; j++ ) - { - tmp = reflections->shoebox_data.times.data[j + ( i * reflections->shoebox_data.n_ref )]; - tmp = roundf( tmp * reflections->output_Fs ); - reflections->shoebox_data.times.data[j + ( i * reflections->shoebox_data.n_ref )] = tmp; - circ_len = ( (uint16_t) tmp > circ_len ) ? (uint16_t) tmp : circ_len; - } - } -#else + move16(); FOR( i = 0; i < reflections->shoebox_data.n_sources; i++ ) { @@ -657,94 +751,63 @@ ivas_error ivas_er_compute_reflections( tmp_fx1 = (UWord32) L_add( tmp_fx1, 0x20 ); tmp_fx1 = L_shr( tmp_fx1, 6 ); reflections->shoebox_data.times.data_fx[j + ( i * reflections->shoebox_data.n_ref )] = tmp_fx1; - circ_len = ( (uint16_t) tmp_fx1 > circ_len ) ? (uint16_t) tmp_fx1 : circ_len; + circ_len = ( (UWord16) tmp_fx1 > circ_len ) ? (UWord16) tmp_fx1 : circ_len; } } -#endif - /* If max delay is less than max frame size, use max frame size to compute circ buffer length */ - circ_len = ( circ_len > (uint16_t) reflections->max_frame_size ) ? circ_len : (uint16_t) reflections->max_frame_size; - circ_len += (uint16_t) reflections->max_frame_size; + circ_len = ( circ_len > (UWord16) reflections->max_frame_size ) ? circ_len : (UWord16) reflections->max_frame_size; + circ_len += (UWord16) reflections->max_frame_size; /* If circ buffers exist and size is the same, reset memory to all zeros */ /* If size is different, reallocate circ buffers */ /* Otherwise allocate new circ buffers */ -#ifdef IVAS_FLOAT_FIXED - for ( i = 0; i < 150; i++ ) + + FOR ( i = 0; i < 150; i++ ) { reflections->shoebox_data.gains.data_fx[i] = L_shl( reflections->shoebox_data.gains.data_fx[i], 9 ); } - if ( reflections->circ_buffers ) + IF ( reflections->circ_buffers ) { - if ( reflections->circ_len == circ_len ) + IF ( reflections->circ_len == circ_len ) { /* circ buffers exist and size is the same */ set32_fx( reflections->circ_buffers, 0, reflections->shoebox_data.n_sources * reflections->circ_len ); } - else + ELSE { /* circ buffers exist but size is different */ reflections->circ_len = circ_len; + move16(); free( reflections->circ_buffers ); - if ( ( reflections->circ_buffers = (Word32 *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( Word32 ) ) ) == NULL ) + IF ( ( reflections->circ_buffers = (Word32 *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( Word32 ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" ); } set32_fx( reflections->circ_buffers, 0, reflections->shoebox_data.n_sources * reflections->circ_len ); } } - else + ELSE { /* circ buffers do not exist */ reflections->circ_len = circ_len; - if ( ( reflections->circ_buffers = (Word32 *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( Word32 ) ) ) == NULL ) + move16(); + IF ( ( reflections->circ_buffers = (Word32 *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( Word32 ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" ); } set32_fx( reflections->circ_buffers, 0, reflections->shoebox_data.n_sources * reflections->circ_len ); } -#else - if ( reflections->circ_buffers ) - { - if ( reflections->circ_len == circ_len ) - { - /* circ buffers exist and size is the same */ - set_f( reflections->circ_buffers, 0.0f, reflections->shoebox_data.n_sources * reflections->circ_len ); - } - else - { - /* circ buffers exist but size is different */ - reflections->circ_len = circ_len; - free( reflections->circ_buffers ); - if ( ( reflections->circ_buffers = (float *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" ); - } - set_f( reflections->circ_buffers, 0.0f, reflections->shoebox_data.n_sources * reflections->circ_len ); - } - } - else - { - /* circ buffers do not exist */ - reflections->circ_len = circ_len; - if ( ( reflections->circ_buffers = (float *) malloc( reflections->shoebox_data.n_sources * reflections->circ_len * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections buffers" ); - } - set_f( reflections->circ_buffers, 0.0f, reflections->shoebox_data.n_sources * reflections->circ_len ); - } -#endif /* Initialize circular buffer insertion point */ - reflections->circ_insert = reflections->circ_len - (uint16_t) reflections->max_frame_size; + reflections->circ_insert = reflections->circ_len - (UWord16) reflections->max_frame_size; /* Get total reflections number */ reflections->n_total_reflections = reflections->shoebox_data.n_sources * reflections->shoebox_data.n_ref; /* Check that reflection buffers were allocated */ - if ( error != IVAS_ERR_OK ) + IF ( NE_32( error, IVAS_ERR_OK ) ) { return error; } @@ -866,40 +929,44 @@ ivas_error ivas_er_process( Word32 *buffer_ch; Word32 temp; - if ( !reflections ) + IF ( !reflections ) { return IVAS_ERR_INIT_ERROR; } /* should not arrive here if reflections are disabled but in case it does just do nothing */ - if ( reflections->use_er != 1 ) + IF ( reflections->use_er != 1 ) { return error; } /* Ensure all reflection memory is allocated */ - if ( !reflections->circ_buffers || !reflections->is_ready ) + IF ( !reflections->circ_buffers || !reflections->is_ready ) { return IVAS_ERR_INIT_ERROR; } subframe_offset = subframe_idx * subframe_size; + move16(); n_ref = reflections->shoebox_data.n_ref; + move16(); /* If low complexity ER are requested only compute ER for n_LC_sources */ - if ( reflections->lowComplexity ) + IF ( reflections->lowComplexity ) { n_ref_sources = reflections->n_LC_sources; + move16(); } - else + ELSE { n_ref_sources = reflections->shoebox_data.n_sources; + move16(); } /* Channel case, copy input into buffers panning for LC mode and skipping LFE */ - if ( getAudioConfigType( inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) + IF ( EQ_32( getAudioConfigType( inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ) { /* Loop through all input sources filling circular buffers */ - for ( i = 0; i < reflections->shoebox_data.n_sources; i++ ) + FOR ( i = 0; i < reflections->shoebox_data.n_sources; i++ ) { /* Pull correct circular buffer depending on complexity mode */ buf_ch_idx = ( reflections->lowComplexity == 1 ) ? reflections->LC_mixing[i] : i; @@ -910,18 +977,18 @@ ivas_error ivas_er_process( samp_idx = reflections->circ_insert; /* If less than number of reflection sources, overwrite buffer */ - if ( i == buf_ch_idx ) + IF ( i == buf_ch_idx ) { - for ( j = 0; j < subframe_size; j++ ) + FOR ( j = 0; j < subframe_size; j++ ) { buffer_ch[samp_idx++] = io[in_ch_idx][j + subframe_offset]; samp_idx = samp_idx % reflections->circ_len; } } /* Accumulate with buffer for low complexity mixed sources */ - else + ELSE { - for ( j = 0; j < subframe_size; j++ ) + FOR ( j = 0; j < subframe_size; j++ ) { buffer_ch[samp_idx] = L_add( io[in_ch_idx][j + subframe_offset], buffer_ch[samp_idx] ); samp_idx++; @@ -930,19 +997,19 @@ ivas_error ivas_er_process( } } } - else + ELSE { return IVAS_ERR_INVALID_INPUT_FORMAT; } /* Loop through sources retrieve reflections from circ buffers */ - for ( i = 0; i < n_ref_sources; i++ ) + FOR ( i = 0; i < n_ref_sources; i++ ) { /* Access correct row of input circ buffer */ buffer_ch = &( reflections->circ_buffers[i * reflections->circ_len] ); /* Loop through reflections */ - for ( j = 0; j < n_ref; j++ ) + FOR ( j = 0; j < n_ref; j++ ) { ref_no = j + ( i * n_ref ); ref_gain = (Word32) reflections->shoebox_data.gains.data_fx[ref_no]; @@ -952,13 +1019,13 @@ ivas_error ivas_er_process( /* Determine start idx of reflection in circ buffer based on current insert idx and reflection delay */ samp_idx = (Word16) reflections->circ_insert - ref_delay; - if ( samp_idx < 0 ) + IF ( LT_16( samp_idx, 0 ) ) { - samp_idx = (Word16) reflections->circ_len + samp_idx; + samp_idx = add( (Word16) reflections->circ_len, samp_idx ); } /* Pull reflection from circ buffer and apply gain */ - for ( k = 0; k < subframe_size; k++ ) + FOR ( k = 0; k < subframe_size; k++ ) { temp = Mpy_32_32( buffer_ch[samp_idx], ref_gain ); io[ref_out_idx][k + subframe_offset] = L_add( temp, io[ref_out_idx][k + subframe_offset] ); diff --git a/lib_rend/ivas_rom_binauralRenderer.c b/lib_rend/ivas_rom_binauralRenderer.c index 310968d99..5330ecbcb 100644 --- a/lib_rend/ivas_rom_binauralRenderer.c +++ b/lib_rend/ivas_rom_binauralRenderer.c @@ -10895,7 +10895,7 @@ const float hrtfShCoeffsRe[BINAURAL_CHANNELS][HRTF_SH_CHANNELS][HRTF_NUM_BINS]= } }; #ifdef IVAS_FLOAT_FIXED -const int hrtfShCoeffsIm_fx[2][16][60]/*Q-14*/ = +const Word16 hrtfShCoeffsIm_fx[2][16][60]/*Q-14*/ = { { { diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index eaba2d206..4b00e46d0 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -269,21 +269,42 @@ const float surCohEne[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = 3.0903f, 2.0053f, 1.0860f, 0.8072f, 0.7079f }; +const Word16 surCohEne_fx[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = +{ + 25315, 16427, 8896, 6612, 5799 +}; + const float spreadCohEne05[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = { 2.3988f, 1.7783f, 1.1220f, 1.1220f, 1.1220f }; +const Word16 spreadCohEne05_fx[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = /* Q13 */ +{ + 19650, 14567, 9191, 9191, 9191 +}; + const float spreadCohEne1[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = { 1.5975f, 1.1220f, 1.1220f, 1.1220f, 1.1220f }; +const Word16 spreadCohEne1_fx[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS] = /* Q14 */ +{ + 26173, 18382, 18382, 18382, 18382 +}; + const float lowBitRateBinauralEQ[LOW_BIT_RATE_BINAURAL_EQ_BINS] = { 0.979f, 0.893f, 0.762f, 0.615f, 0.52f, 0.48f, 0.477f, 0.477f, 0.48f, 0.501f, 0.546f, 0.602f, 0.652f, 0.664f, 0.652f, 0.639f, 0.635f }; +const Word32 lowBitRateBinauralEQ_fx[LOW_BIT_RATE_BINAURAL_EQ_BINS] = +{ + 2102386432, 1917702912, 1636382592, 1320702464, 1116691456, 1030792128, 1024349696, 1024349696, 1030792128, + 1075889280, 1172526080, 1292785152, 1400159360, 1425929088, 1400159360, 1372242048, 1363652096 +}; + const float diffuseFieldCoherenceDifferenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS] = { 0.047421f, 0.19773f, 0.22582f, 0.10637f, 0.0087111f, 0.012028f, 0.031972f, 0.019668f, 0.0079928f diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h index 7ffcb441e..04730ad97 100644 --- a/lib_rend/ivas_rom_rend.h +++ b/lib_rend/ivas_rom_rend.h @@ -85,11 +85,15 @@ extern const int16_t channelIndex_CICP19[11]; /* These are equalization values for spread and surround coherent sounds, approximating the spectrum * for such sounds at anechoic multichannel listening. */ extern const float surCohEne[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; +extern const Word16 surCohEne_fx[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; extern const float spreadCohEne05[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; +extern const Word16 spreadCohEne05_fx[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; extern const float spreadCohEne1[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; +extern const Word16 spreadCohEne1_fx[MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS]; /* Values for low-bit-rate equalization */ extern const float lowBitRateBinauralEQ[LOW_BIT_RATE_BINAURAL_EQ_BINS]; +extern const Word32 lowBitRateBinauralEQ_fx[LOW_BIT_RATE_BINAURAL_EQ_BINS]; /* Diffuse field binaural coherence directional adjustment values */ extern const float diffuseFieldCoherenceDifferenceX[BINAURAL_COHERENCE_DIFFERENCE_BINS]; diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 2684fe020..3ad19a9a9 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -848,6 +848,8 @@ typedef struct ivas_dirac_dec_binaural_data_structure float processMtxDecRePrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; float processMtxDecImPrev[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; #ifdef IVAS_FLOAT_FIXED + Word32 earlyPartEneCorrection_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 q_earlyPartEneCorrection; Word16 processMtxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; Word16 processMtxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; Word16 processMtxDecRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; @@ -856,6 +858,38 @@ typedef struct ivas_dirac_dec_binaural_data_structure Word16 processMtxImPrev_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS + MAX_NUM_OBJECTS][CLDFB_NO_CHANNELS_MAX]; Word16 processMtxDecRePrev_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; Word16 processMtxDecImPrev_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + + Word32 ChEnePrev_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossRePrev_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossImPrev_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChEne_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossRe_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossIm_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossReOut_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossImOut_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChEneOut_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 ChEneOutPrev_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word32 frameMeanDiffuseness_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossReOutPrev_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 ChCrossImOutPrev_fx[CLDFB_NO_CHANNELS_MAX]; + + Word16 ChEnePrev_e[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossRePrev_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossImPrev_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChEne_e[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossRe_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossIm_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossReOut_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossImOut_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChEneOut_e[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word16 ChEneOutPrev_e[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossReOutPrev_e[CLDFB_NO_CHANNELS_MAX]; + Word16 ChCrossImOutPrev_e[CLDFB_NO_CHANNELS_MAX]; + + Word32 diffuseFieldCoherence_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 diffuseFieldCoherenceX_fx[BINAURAL_COHERENCE_DIFFERENCE_BINS]; + Word32 diffuseFieldCoherenceY_fx[BINAURAL_COHERENCE_DIFFERENCE_BINS]; + Word32 diffuseFieldCoherenceZ_fx[BINAURAL_COHERENCE_DIFFERENCE_BINS]; #endif uint16_t useTdDecorr; ivas_td_decorr_state_t *hTdDecorr; @@ -1785,16 +1819,17 @@ typedef struct Word32 elev_prev_fx; Word16 Gain_fx; // Q14 Word16 prevGain_fx; // Q14 -#endif // IVAS_FLOAT_FIXED +#else float mem_itd[ITD_MEM_LEN]; + float azim_prev; float hrf_left_prev[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; float hrf_right_prev[SFX_SPAT_BIN_MAX_FILTER_LENGTH]; - float azim_prev; float elev_prev; float mem_hrf_left[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1]; float mem_hrf_right[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1]; float Gain; float prevGain; +#endif // IVAS_FLOAT_FIXED } TDREND_SRC_t; @@ -1809,9 +1844,10 @@ typedef struct ivas_binaural_td_rendering_struct TDREND_SRC_t *Sources[MAX_NUM_TDREND_CHANNELS]; #ifdef IVAS_FLOAT_FIXED Word16 Gain_fx; /* Q14 */ +#else + float Gain; /* Mixer gain */ #endif // IVAS_FLOAT_FIXED - float Gain; /* Mixer gain */ TDREND_MIX_Listener_t *Listener_p; /* The virtual listener */ TDREND_HRFILT_FiltSet_t *HrFiltSet_p; /* HR filter set */ @@ -2197,7 +2233,33 @@ typedef struct ivas_mcmasa_ana_data_structure HANDLE_CLDFB_FILTER_BANK cldfbAnaEnc[MCMASA_MAX_ANA_CHANS]; /* DirAC parameter estimation */ +#ifdef IVAS_FLOAT_FIXED + Word32 **direction_vector_m_fx[DIRAC_NUM_DIMS]; /* Average direction vector */ + Word16 **direction_vector_e[MAX_PARAM_SPATIAL_SUBFRAMES]; /* Average direction vector */ +#endif // IVAS_FLOAT_FIXED float **direction_vector_m[DIRAC_NUM_DIMS]; /* Average direction vector */ +#ifdef IVAS_FLOAT_FIXED + Word32 *buffer_intensity_real_fx[DIRAC_NUM_DIMS][DIRAC_NO_COL_AVG_DIFF]; + Word16 buffer_intensity_real_q[DIRAC_NO_COL_AVG_DIFF]; + Word32 *buffer_intensity_real_vert_fx[DIRAC_NO_COL_AVG_DIFF]; + Word16 buffer_intensity_real_vert_q[DIRAC_NO_COL_AVG_DIFF]; + Word32 buffer_energy_fx[DIRAC_NO_COL_AVG_DIFF * MASA_FREQUENCY_BANDS]; + Word16 buffer_energy_q[DIRAC_NO_COL_AVG_DIFF]; + Word32 chnlToFoaMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; + Word32 chnlToFoaEvenMtx_fx[FOA_CHANNELS][MCMASA_MAX_ANA_CHANS]; + Word32 ls_azimuth_fx[MCMASA_MAX_ANA_CHANS]; + Word32 prevMultiChEne_fx; + Word32 prevDownmixEne_fx; + Word32 prevEQ_fx; + Word16 interpolator_fx[L_FRAME48k]; + Word32 energy_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 energy_e[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; + Word16 chnlToFoaMtx_e; + Word16 prevMultiChEne_e; + Word16 prevDownmixEne_e; + Word16 prevEQ_e; + Word16 interpolator_e; +#endif // IVAS_FLOAT_FIXED int16_t band_grouping[MASA_FREQUENCY_BANDS + 1]; int16_t block_grouping[5]; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 83fd23f69..d4bd50556 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3858,6 +3858,24 @@ static ivas_error initMcMasaRendering( { return error; } +#ifdef IVAS_FLOAT_FIXED +#if 1 /*Fixed to float conversion for ivas_mcmasa_ana_open (to be removed later)*/ + MCMASA_ANA_HANDLE hMcMasa = inputMc->hMcMasa; + Word16 i, j; + fixedToFloat_arrL( hMcMasa->ls_azimuth_fx, hMcMasa->ls_azimuth, Q22, MCMASA_MAX_ANA_CHANS); + FOR ( i = 0; i < MCMASA_MAX_ANA_CHANS; i++ ) + { + FOR ( j = 0; j < FOA_CHANNELS; j++ ) + { + hMcMasa->chnlToFoaMtx[j][i] = fixedToFloat( hMcMasa->chnlToFoaMtx_fx[j][i], Q31 ); + } + } + FOR( i = 0; i < (inSampleRate/FRAMES_PER_SEC); i++ ) + { + hMcMasa->interpolator[i] = fixedToFloat( hMcMasa->interpolator_fx[i], Q15 ); + } +#endif +#endif // IVAS_FLOAT_FIXED return IVAS_ERR_OK; } @@ -9751,7 +9769,71 @@ static void renderMcToMasa( push_wmops( "renderMcToMasa" ); copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); +#ifdef IVAS_FLOAT_FIXED + Word32 tmpRendBuffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer_fx ); +#if 1 /*TODO: To be removed later: Float to fixed */ + /*From here: Cleanup changes for ivas_mcmasa_param_est_ana_fx*/ + MCMASA_ANA_HANDLE hMcMasa = mcInput->hMcMasa; + Word16 i, nchan_inp = mcInput->base.inputBuffer.config.numChannels; + Word16 q_data = *( outAudio.pq_fact ); + FOR ( i = 0; i < nchan_inp - 1; i++ ) + { + floatToFixed_arrL( hMcMasa->cldfbAnaEnc[i]->cldfb_state, hMcMasa->cldfbAnaEnc[i]->cldfb_state_fx, q_data, hMcMasa->cldfbAnaEnc[i]->p_filter_length - hMcMasa->cldfbAnaEnc[i]->no_channels ); + } + /*From here: Cleanup changes for ivas_mcmasa_dmx_fx*/ + f2me( hMcMasa->prevMultiChEne, &hMcMasa->prevMultiChEne_fx, &hMcMasa->prevMultiChEne_e ); + f2me( hMcMasa->prevDownmixEne, &hMcMasa->prevDownmixEne_fx, &hMcMasa->prevDownmixEne_e ); + f2me( hMcMasa->prevEQ, &hMcMasa->prevEQ_fx, &hMcMasa->prevEQ_e ); + floatToFixed_arr( hMcMasa->interpolator, hMcMasa->interpolator_fx, 15, L_FRAME48k ); +#endif + ivas_mcmasa_ana_fx( mcInput->hMcMasa, tmpRendBuffer_fx, *( outAudio.pq_fact ), mcInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels, mcInput->base.inputBuffer.config.numChannels ); +#if 1 /*TODO: To be removed later(fixed to float)*/ + /*From here : Cleanup changes for ivas_mcmasa_param_est_ana_fx*/ + FOR ( i = 0; i < nchan_inp - 1; i++ ) + { + fixedToFloat_arrL( hMcMasa->cldfbAnaEnc[i]->cldfb_state_fx, hMcMasa->cldfbAnaEnc[i]->cldfb_state, q_data, hMcMasa->cldfbAnaEnc[i]->p_filter_length - hMcMasa->cldfbAnaEnc[i]->no_channels ); + } + FOR ( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + FOR ( int k = 0; k < MASA_FREQUENCY_BANDS; k++ ) + { + FOR ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + hMcMasa->direction_vector_m[i][j][k] = me2f( hMcMasa->direction_vector_m_fx[i][j][k], hMcMasa->direction_vector_e[i][j][k] ); + } + hMcMasa->energy[j][k] = me2f( hMcMasa->energy_fx[j][k], hMcMasa->energy_e[j][k] ); + } + } + FOR ( i = 0; i < DIRAC_NO_COL_AVG_DIFF; i++ ) + { + FOR ( int j = 0; j < DIRAC_NUM_DIMS; j++ ) + { + FOR ( int k = 0; k < MASA_FREQUENCY_BANDS; k++ ) + hMcMasa->buffer_intensity_real[j][i][k] = fixedToFloat( hMcMasa->buffer_intensity_real_fx[j][i][k], hMcMasa->buffer_intensity_real_q[i] ); + } + FOR ( int j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + { + hMcMasa->buffer_intensity_real_vert[i][j] = fixedToFloat( hMcMasa->buffer_intensity_real_vert_fx[i][j], hMcMasa->buffer_intensity_real_vert_q[i] ); + } + FOR ( int j = 0; j < MASA_FREQUENCY_BANDS; j++ ) + { + hMcMasa->buffer_energy[i * j + j] = fixedToFloat( hMcMasa->buffer_energy_fx[i * j + j], hMcMasa->buffer_energy_q[i] ); + } + } + /*From here : cleanup changes for ivas_mcmasa_dmx_fx*/ + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + fixedToFloat_arrL( tmpRendBuffer_fx[i], tmpRendBuffer[i], q_data, L_FRAME48k ); + } + + hMcMasa->prevMultiChEne = me2f( hMcMasa->prevMultiChEne_fx, hMcMasa->prevMultiChEne_e ); + hMcMasa->prevDownmixEne = me2f( hMcMasa->prevDownmixEne_fx, hMcMasa->prevDownmixEne_e ); + hMcMasa->prevEQ = me2f( hMcMasa->prevEQ_fx, hMcMasa->prevEQ_e ); +#endif +#else ivas_mcmasa_ana( mcInput->hMcMasa, tmpRendBuffer, mcInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels, mcInput->base.inputBuffer.config.numChannels ); +#endif // IVAS_FLOAT_FIXED accumulate2dArrayToBuffer( tmpRendBuffer, &outAudio ); -- GitLab