diff --git a/apps/renderer.c b/apps/renderer.c index 8d2877ae9111da0ca30f7eee384ca31052b7e6ad..1c6cd62dcc6cbdb491016dd462547afd633e02cd 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1815,6 +1815,26 @@ int main( exit( -1 ); } +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( isCurrentFrameMultipleOf20ms ) + { + if ( masaReaders[i] != NULL ) + { + /* This will update data in hMasaMetadata[i] */ + if ( ( error = MasaFileReader_readNextFrame( masaReaders[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in MASA Metadata File Reading: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + if ( ( error = IVAS_REND_FeedInputMasaMetadata( hIvasRend, masaIds[i], hMasaMetadata[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + } +#else if ( masaReaders[i] != NULL ) { /* This will update data in hMasaMetadata[i] */ @@ -1826,6 +1846,7 @@ int main( exit( -1 ); } } +#endif } @@ -2530,9 +2551,13 @@ static IVAS_AUDIO_CONFIG parseAudioConfig( switch ( charBuf[4] ) { case '1': +#ifdef NONBE_FIX_225_MASA_EXT_REND + return IVAS_AUDIO_CONFIG_MASA1; +#else fprintf( stderr, "1TC MASA support is not functional and is pending on DirAC renderer refactoring.\n" ); exit( EXIT_FAILURE ); /*return IVAS_AUDIO_CONFIG_MASA1;*/ // ToDo: temporarily disabled to avoid compilation warnings +#endif case '2': return IVAS_AUDIO_CONFIG_MASA2; default: diff --git a/lib_com/options.h b/lib_com/options.h index c6aa559ff158b5055f687463e272f7a67cac6b3b..71bdcdb793b0f5e14baad4af4bf7d08e33aedded 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -168,6 +168,7 @@ #define NONBE_FIX_856_TCX_LTP_SYNTH_FILTER /* FhG: issue 856: correct filtering length for tcx-ltp synth filtering*/ #define NONBE_UNIFIED_DECODING_PATHS /* FhG: unify decoding paths */ #define NONBE_FIX_874_OMASA_BRSW_2TD /* Nokia: issue 874: Fixes the crashes with the long test vectors that prompted switching to TD*/ +#define NONBE_FIX_225_MASA_EXT_REND /* Nokia: Resolve #225: Complete MASA external renderer implementation */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 4de8d38aaa6bd135b8e9b36f92913612b56f1783..b5b8282c1207886ce9458cad2dac520d7dfab17a 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -41,6 +41,9 @@ #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_dec.h" +#ifdef NONBE_FIX_225_MASA_EXT_REND +#include "ivas_rom_rend.h" +#endif #ifdef DEBUGGING #include "debug.h" #endif @@ -840,8 +843,14 @@ ivas_error ivas_dirac_dec_config( if ( !sparfoa_flag ) { common_rend_config_flag = st_ivas->hSpatParamRendCom == NULL ? DIRAC_OPEN : flag_config_inp; +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( ( error = ivas_spat_hSpatParamRendCom_config( &st_ivas->hSpatParamRendCom, common_rend_config_flag, dec_param_estim_new, + st_ivas->ivas_format, st_ivas->mc_mode, output_Fs, hodirac_flag, 0 ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_spat_hSpatParamRendCom_config( &st_ivas->hSpatParamRendCom, common_rend_config_flag, dec_param_estim_new, st_ivas->ivas_format, st_ivas->mc_mode, output_Fs, hodirac_flag ) ) != IVAS_ERR_OK ) + +#endif { return error; } @@ -1960,7 +1969,11 @@ void ivas_dirac_dec_render_sf( ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, hDirACRend, st_ivas->hVBAPdata, +#ifdef NONBE_FIX_225_MASA_EXT_REND + st_ivas->hMasa == NULL ? NULL : st_ivas->hMasa->data.band_mapping, +#else st_ivas->hMasa, +#endif st_ivas->hMasaIsmData, azimuth, elevation, @@ -1975,7 +1988,11 @@ void ivas_dirac_dec_render_sf( ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, hDirACRend, st_ivas->hVBAPdata, +#ifdef NONBE_FIX_225_MASA_EXT_REND + st_ivas->hMasa == NULL ? NULL : st_ivas->hMasa->data.band_mapping, +#else st_ivas->hMasa, +#endif st_ivas->hMasaIsmData, azimuth, elevation, diff --git a/lib_dec/ivas_rom_dec.c b/lib_dec/ivas_rom_dec.c index 1c04fb93efc7fedaaa2ad598419f720eb2507035..26846d6254bbcf90fcb29720cda571a9a30c8b84 100644 --- a/lib_dec/ivas_rom_dec.c +++ b/lib_dec/ivas_rom_dec.c @@ -379,6 +379,7 @@ const uint16_t * const sym_freq_ECSQ_tab_abs_lsbs[1 + 4] = * DirAC ROM tables *----------------------------------------------------------------------------------*/ +#ifndef NONBE_FIX_225_MASA_EXT_REND const float ls_azimuth_4d4[8] = { 45.0f, -45.0f, 135.0f, -135.0f, 45.0f, -45.0f, 135.0f, -135.0f }; const float ls_elevation_4d4[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 35.0f, 35.0f, 35.0f, 35.0f }; @@ -389,6 +390,7 @@ const float diffuse_response_CICP14[7] = { 0.3817f, 0.3817f, 0.2819f, 0.5399f, 0 const float diffuse_response_CICP16[9] = { 0.3456f, 0.3456f, 0.3035f, 0.4124f, 0.4124f, 0.2702f, 0.2702f, 0.3023f, 0.3023f }; +#endif const float dirac_dithering_azi_scale[DIRAC_DIFFUSE_LEVELS] = { @@ -400,6 +402,7 @@ const float dirac_dithering_ele_scale[DIRAC_DIFFUSE_LEVELS] = 6.716062e-01f, 1.011804e+00f, 1.796875e+00f, 2.804382e+00f, 4.623130e+00f, 7.802667e+00f, 1.045446e+01f, 1.379538e+01f }; +#ifndef NONBE_FIX_225_MASA_EXT_REND const int16_t ap_pre_delay[DIRAC_DECORR_NUM_SPLIT_BANDS] = { 7, 2, 1 }; const int16_t ap_filter_length[DIRAC_DECORR_NUM_SPLIT_BANDS] = { 15, 6, 3 }; @@ -530,6 +533,7 @@ const int16_t sba_map_tc_512[11] = }; +#endif /*----------------------------------------------------------------------------------* * FASTCONV and PARAMETRIC binaural renderer ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_dec/ivas_rom_dec.h b/lib_dec/ivas_rom_dec.h index 2ab0e12690aae5ce99930d435c91c7712ba85315..5c22186afdbdd13ecac296201a5ed686e26b61ea 100644 --- a/lib_dec/ivas_rom_dec.h +++ b/lib_dec/ivas_rom_dec.h @@ -92,16 +92,19 @@ extern const uint16_t *const sym_freq_ECSQ_tab_abs_lsbs[1 + 4]; * DirAC ROM tables *----------------------------------------------------------------------------------*/ +#ifndef NONBE_FIX_225_MASA_EXT_REND extern const float ls_azimuth_4d4[8]; extern const float ls_elevation_4d4[8]; extern const float diffuse_response_CICP6[5]; extern const float diffuse_response_CICP14[7]; extern const float diffuse_response_CICP16[9]; +#endif extern const float dirac_dithering_azi_scale[DIRAC_DIFFUSE_LEVELS]; extern const float dirac_dithering_ele_scale[DIRAC_DIFFUSE_LEVELS]; +#ifndef NONBE_FIX_225_MASA_EXT_REND extern const int16_t ap_pre_delay[DIRAC_DECORR_NUM_SPLIT_BANDS]; extern const int16_t ap_filter_length[DIRAC_DECORR_NUM_SPLIT_BANDS]; extern const float ap_lattice_delta_phi[DIRAC_MAX_NUM_DECORR_FILTERS * DIRAC_MAX_DECORR_FILTER_LEN]; @@ -113,6 +116,7 @@ extern const float ap_split_frequencies[DIRAC_DECORR_NUM_SPLIT_BANDS + 1]; extern const int16_t sba_map_tc[11]; extern const int16_t sba_map_tc_512[11]; +#endif /*----------------------------------------------------------------------------------* * FASTCONV and PARAMETRIC binaural renderer ROM tables @@ -120,7 +124,6 @@ extern const int16_t sba_map_tc_512[11]; extern const float dmxmtx_table[BINAURAL_CHANNELS][11]; - #ifdef SPLIT_REND_WITH_HEAD_ROT /*----------------------------------------------------------------------* * Binuaral split rendering ROM tables diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 0edeee6e38993c5febd09c598028854c630dfcd6..6636f08060e01db8de1d22ed7f60622de7747c94 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -127,6 +127,13 @@ static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Ai static void matrixTransp2Mul( 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] ); +#ifdef NONBE_FIX_225_MASA_EXT_REND +#ifdef SPLIT_REND_WITH_HEAD_ROT +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 SPLIT_REND_WRAPPER *hSplitRendWrapper, float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ); +#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 ); +#endif +#endif /*------------------------------------------------------------------------- * ivas_dirac_dec_init_binaural_data() @@ -3470,3 +3477,319 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects( return; } + +#ifdef NONBE_FIX_225_MASA_EXT_REND +static void ivas_masa_ext_rend_parambin_internal( + MASA_EXT_REND_HANDLE hMasaExtRend, + COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, + float *output_f[], +#ifdef SPLIT_REND_WITH_HEAD_ROT + const int16_t subframe, + const SPLIT_REND_WRAPPER *hSplitRendWrapper, + float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ) +#else + const int16_t subframe ) +#endif +{ + 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 SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + float tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + + /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */ + 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 decorrRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float decorrIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX]; + float IIReneLimiter[CLDFB_NO_CHANNELS_MAX]; + + hDiracDecBin = hMasaExtRend->hDiracDecBin[0]; +#else + hDiracDecBin = hMasaExtRend->hDiracDecBin; +#endif + 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; + + 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( + &( 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 */ + { + /* 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 ); + } + } + } + + if ( hCombinedOrientationData ) + { + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < 3; j++ ) + { +#ifdef NONBE_UNIFIED_DECODING_PATHS + Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j]; +#else + Rmat[i][j] = hCombinedOrientationData->Rmat[subframe][i][j]; +#endif + } + } + + if ( nchan_transport == 2 ) + { +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */ +#endif + 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 ); + } + } + + +#ifndef SPLIT_REND_WITH_HEAD_ROT +#ifdef NONBE_UNIFIED_DECODING_PATHS + 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 ); +#else + 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[subframe] > 0, NULL ); +#endif +#endif + + /* Always using CLDFB decorrelation in MASA EXT renderer */ + max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr; + + +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe, + subFrameTotalEne, IIReneLimiter ); + ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + subFrameTotalEne, IIReneLimiter, NULL ); +#endif + +#ifdef NONBE_UNIFIED_DECODING_PATHS + 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 ); +#else + ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + 0, NULL ); +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT + pMultiBinPoseData = NULL; + if ( hSplitRendWrapper != NULL ) + { + pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData ); + + 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, tmp_Cldfb_out_re, tmp_Cldfb_out_im, + reverbRe, reverbIm, decorrRe, decorrIm, 1 ); + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ ) + { + mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + } + } + } + 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, NULL, NULL, + reverbRe, reverbIm, decorrRe, decorrIm, 1 ); + } +#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; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 ) + { + /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */ + IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref; + float Rmat_local[3][3]; + + if ( hCombinedOrientationData ) + { + Quaternions_ref = &hCombinedOrientationData->Quaternions[0]; + Quaternions_rot.w = -3.0f; /* signal to use Euler */ + Quaternions_abs.w = -3.0f; /* signal to use Euler */ + Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/ + + for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0]; + Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1]; + Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2]; + + QuatToRotMat( Quaternions_rot, Rmat_local ); + + hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx]; + assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" ); + + /* re-use input covariance for the side renderings */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + mvr2r( hMasaExtRend->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands ); + } + mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands ); + mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands ); + + ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + subFrameTotalEne, IIReneLimiter, NULL ); + + ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + 0, NULL ); + + + /* re-use reverb and decorr from main direction for the sides */ + 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, tmp_Cldfb_out_re, tmp_Cldfb_out_im, + reverbRe, reverbIm, decorrRe, decorrIm, 0 ); + + /* copy from temporary buffer to the main split rendering buffer */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ ) + { + mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + } + } + + hDiracDecBin->hDiffuseDist = NULL; + } + } + } + + /* update this counter only after the last rendering of split directions */ +#endif + hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe]; + hSpatParamRendCom->subframes_rendered++; + + return; +} + + +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 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const int16_t num_subframes, /* i : number of subframes to render */ + const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */ + float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */ + float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ) /* o : rendered orientations for split rend. imag part of cldfb */ +#else + const int16_t num_subframes ) /* i : number of subframes to render */ +#endif +{ + int16_t subframe; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + float *p_output[BINAURAL_CHANNELS]; + int16_t ch; + + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_output[ch] = output_f[ch]; + } + + hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx; + + for ( subframe = 0; subframe < num_subframes; subframe++ ) + { + int16_t n_samples_sf = hSpatParamRendCom->slot_size * CLDFB_SLOTS_PER_SUBFRAME; + hSpatParamRendCom->slots_rendered = 0; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_masa_ext_rend_parambin_internal( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag ); +#else + ivas_masa_ext_rend_parambin_internal( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx ); +#endif + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + p_output[ch] += n_samples_sf; + } + +#ifdef NONBE_UNIFIED_DECODING_PATHS + ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_sf ); +#endif + + hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + } + + return; +} +#endif diff --git a/lib_rend/ivas_dirac_decorr_dec.c b/lib_rend/ivas_dirac_decorr_dec.c index e8311888819097d56c1a30837fe588d2cd501046..36ac883e8729cbe5104705ddd514776c14d7f501 100644 --- a/lib_rend/ivas_dirac_decorr_dec.c +++ b/lib_rend/ivas_dirac_decorr_dec.c @@ -38,9 +38,15 @@ #include "prot.h" #include "ivas_prot.h" #include "ivas_prot_rend.h" +#ifndef NONBE_FIX_225_MASA_EXT_REND #include "ivas_stat_dec.h" +#endif #include "ivas_cnst.h" +#ifdef NONBE_FIX_225_MASA_EXT_REND +#include "ivas_rom_rend.h" +#else #include "ivas_rom_dec.h" +#endif #ifdef DEBUGGING #include "debug.h" #endif diff --git a/lib_rend/ivas_dirac_output_synthesis_dec.c b/lib_rend/ivas_dirac_output_synthesis_dec.c index f10b7b2c225c57450d098ab0e094321ceaa6694b..30d102440b0362632ed27fc31ef1746f7760c53a 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec.c @@ -1741,11 +1741,19 @@ static void ivas_dirac_dec_get_response_split_order( *------------------------------------------------------------------------*/ void ivas_dirac_dec_compute_directional_responses( +#ifdef NONBE_FIX_225_MASA_EXT_REND + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ + DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const int16_t *masa_band_mapping, /* i : Band mapping for MASA, NULL assumes not using MASA in any form */ + MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ +#else SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ const MASA_DECODER_HANDLE hMasa, /* i : MASA decoder structure */ MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ +#endif const int16_t *azimuth, const int16_t *elevation, const int16_t md_idx, @@ -1793,14 +1801,24 @@ void ivas_dirac_dec_compute_directional_responses( for ( k = 0; k < hSpatParamRendCom->num_freq_bands; ++k ) { +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( masa_band_mapping != NULL && k == MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] ) +#else if ( hMasa != NULL && k == MASA_band_grouping_24[hMasa->data.band_mapping[codingBand + 1]] ) +#endif { codingBand++; } +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( masa_band_mapping != NULL && k > MASA_band_grouping_24[masa_band_mapping[codingBand]] && + k < MASA_band_grouping_24[masa_band_mapping[codingBand + 1]] && + k != hDirACRend->h_output_synthesis_psd_params.max_band_decorr ) +#else if ( hMasa != NULL && k > MASA_band_grouping_24[hMasa->data.band_mapping[codingBand]] && k < MASA_band_grouping_24[hMasa->data.band_mapping[codingBand + 1]] && k != hDirACRend->h_output_synthesis_psd_params.max_band_decorr ) +#endif { /* Panning gains have to be computed only for the first bin of the coding band in MASA, for other bins the previous values can be used */ if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) @@ -1841,7 +1859,11 @@ void ivas_dirac_dec_compute_directional_responses( } } +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( masa_band_mapping == NULL && hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) +#else if ( hMasa == NULL && hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) +#endif { mvr2r_inc( direct_response_hoa, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k], hSpatParamRendCom->num_freq_bands, num_channels_dir ); @@ -1850,8 +1872,13 @@ void ivas_dirac_dec_compute_directional_responses( mvr2r_inc( direct_response_dir2, 1, &hDirACRend->h_output_synthesis_psd_state.direct_responses[k + hSpatParamRendCom->num_freq_bands * num_channels_dir], hSpatParamRendCom->num_freq_bands, num_channels_dir ); } } +#ifdef NONBE_FIX_225_MASA_EXT_REND + else if ( ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) && ( masa_band_mapping != NULL ) ) || + hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) +#else else if ( ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) && ( hMasa != NULL ) ) || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) +#endif { /* Synthesize the first direction */ spreadCoherencePanningHoa( azimuth[k], elevation[k], hSpatParamRendCom->spreadCoherence[md_idx][k], direct_response_hoa, num_channels_dir, hDirACRend->hOutSetup.ambisonics_order ); diff --git a/lib_rend/ivas_dirac_rend.c b/lib_rend/ivas_dirac_rend.c index 148f11e82c8230d526861e25fb54949a174ee0ce..98cd33401e0a896dbfcc1eecd425d7d2b154d6dd 100644 --- a/lib_rend/ivas_dirac_rend.c +++ b/lib_rend/ivas_dirac_rend.c @@ -39,7 +39,11 @@ #include "ivas_prot.h" #include "ivas_prot_rend.h" #include "ivas_cnst.h" +#ifdef NONBE_FIX_225_MASA_EXT_REND +#include "ivas_rom_rend.h" +#else #include "ivas_rom_dec.h" +#endif #ifdef DEBUGGING #include "debug.h" #endif @@ -197,7 +201,12 @@ ivas_error ivas_spat_hSpatParamRendCom_config( const IVAS_FORMAT ivas_format, const MC_MODE mc_mode, const int32_t output_Fs, +#ifdef NONBE_FIX_225_MASA_EXT_REND + const int16_t hodirac_flag, + const int16_t masa_ext_rend_flag ) +#else const int16_t hodirac_flag ) +#endif { ivas_error error; int16_t map_idx; @@ -266,7 +275,11 @@ ivas_error ivas_spat_hSpatParamRendCom_config( hSpatParamRendCom->dirac_md_buffer_length = 0; hSpatParamRendCom->dirac_bs_md_write_idx = 0; hSpatParamRendCom->dirac_read_idx = 0; +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( mc_mode == MC_MODE_MCMASA || masa_ext_rend_flag == 1 ) +#else if ( mc_mode == MC_MODE_MCMASA ) +#endif { hSpatParamRendCom->dirac_md_buffer_length = MAX_PARAM_SPATIAL_SUBFRAMES; @@ -2084,3 +2097,424 @@ void rotateAziEle_DirAC( return; } + +#ifdef NONBE_FIX_225_MASA_EXT_REND +/* A reduced rewrite of the corresponding decoder side function */ +static void ivas_masa_ext_dirac_render_sf( + MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: IVAS decoder structure */ + float *output_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ +) +{ + int16_t i, ch, idx_in, idx_lfe; + DIRAC_REND_HANDLE hDirACRend; + float dirEne; + float surCohEner; + float surCohRatio[CLDFB_NO_CHANNELS_MAX]; + int16_t subframe_idx; + int16_t slot_idx, index_slot; + int16_t slot_idx_start, slot_idx_start_cldfb_synth, md_idx; + int16_t nchan_transport; + int16_t masa_band_mapping[MASA_FREQUENCY_BANDS + 1]; + + /* CLDFB: last output channels reserved to LFT for CICPx */ + float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + + /* local copies of azi, ele, diffuseness */ + int16_t azimuth[CLDFB_NO_CHANNELS_MAX]; + int16_t elevation[CLDFB_NO_CHANNELS_MAX]; + float diffuseness_vector[CLDFB_NO_CHANNELS_MAX]; + + DIRAC_DEC_STACK_MEM DirAC_mem; + float *reference_power, *reference_power_smooth; + float *onset_filter, *onset_filter_subframe, *p_onset_filter = NULL; + uint16_t coherence_flag; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + + push_wmops( "ivas_masa_ext_dirac_render_sf" ); + + /* Initialize aux buffers */ + hDirACRend = hMasaExtRend->hDirACRend; + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; + nchan_transport = hMasaExtRend->nchan_input; + + DirAC_mem = hDirACRend->stack_mem; + + reference_power = DirAC_mem.reference_power; + reference_power_smooth = DirAC_mem.reference_power + hSpatParamRendCom->num_freq_bands; + onset_filter = DirAC_mem.onset_filter; + onset_filter_subframe = ( DirAC_mem.onset_filter == NULL ) ? NULL : DirAC_mem.onset_filter + hSpatParamRendCom->num_freq_bands; + + coherence_flag = 1; /* There is always coherence assumed for ext rend of MASA */ + + /* Construct default MASA band mapping */ + for ( i = 0; i < MASA_FREQUENCY_BANDS + 1; i++ ) + { + masa_band_mapping[i] = i; + } + + /* Subframe loop */ + slot_idx_start = hSpatParamRendCom->slots_rendered; + slot_idx_start_cldfb_synth = 0; + + subframe_idx = hSpatParamRendCom->subframes_rendered; + md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx]; + + /* copy parameters into local buffers*/ + mvs2s( hSpatParamRendCom->azimuth[hSpatParamRendCom->render_to_md_map[subframe_idx]], azimuth, hSpatParamRendCom->num_freq_bands ); + mvs2s( hSpatParamRendCom->elevation[hSpatParamRendCom->render_to_md_map[subframe_idx]], elevation, hSpatParamRendCom->num_freq_bands ); + mvr2r( hSpatParamRendCom->diffuseness_vector[hSpatParamRendCom->render_to_md_map[subframe_idx]], diffuseness_vector, hSpatParamRendCom->num_freq_bands ); + + if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + set_zero( reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + } + else + { + set_zero( onset_filter_subframe, hSpatParamRendCom->num_freq_bands ); + } + + /* compute response */ + if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_compute_power_factors( hSpatParamRendCom->num_freq_bands, + diffuseness_vector, + hDirACRend->h_output_synthesis_psd_params.max_band_decorr, + hDirACRend->h_output_synthesis_psd_state.direct_power_factor, + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor ); + + if ( coherence_flag ) + { + for ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + dirEne = hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i]; + surCohEner = hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] * hSpatParamRendCom->surroundingCoherence[md_idx][i]; + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor[i] -= surCohEner; + hDirACRend->h_output_synthesis_psd_state.direct_power_factor[i] += surCohEner; + + surCohRatio[i] = surCohEner / ( 1e-12f + dirEne + surCohEner ); + } + } + else + { + set_zero( surCohRatio, hSpatParamRendCom->num_freq_bands ); + } + } + else + { + ivas_dirac_dec_compute_gain_factors( hSpatParamRendCom->num_freq_bands, + hSpatParamRendCom->diffuseness_vector[md_idx], + hDirACRend->h_output_synthesis_psd_params.max_band_decorr, + hDirACRend->h_output_synthesis_psd_state.direct_power_factor, + hDirACRend->h_output_synthesis_psd_state.diffuse_power_factor ); + + if ( coherence_flag ) + { + for ( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + surCohRatio[i] = hSpatParamRendCom->surroundingCoherence[md_idx][i]; + } + } + else + { + set_zero( surCohRatio, hSpatParamRendCom->num_freq_bands ); + } + } + + ivas_dirac_dec_compute_directional_responses( hSpatParamRendCom, + hDirACRend, + hMasaExtRend->hVBAPdata, + masa_band_mapping, + NULL, + azimuth, + elevation, + md_idx, + surCohRatio, + 0, + NULL, + 0 ); + + + for ( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + index_slot = slot_idx_start + slot_idx; + md_idx = hSpatParamRendCom->render_to_md_map[subframe_idx]; + + /* CLDFB Analysis*/ + for ( ch = 0; ch < nchan_transport; ch++ ) + { + cldfbAnalysis_ts( &( output_f[ch][hSpatParamRendCom->num_freq_bands * index_slot] ), + Cldfb_RealBuffer[ch][0], + Cldfb_ImagBuffer[ch][0], + hSpatParamRendCom->num_freq_bands, + hMasaExtRend->cldfbAnaRend[ch] ); + } + + + if ( nchan_transport == 1 ) + { + /* Need to set second CLDFB channel to zero as further processing assumes CNA content in it */ + set_zero( Cldfb_RealBuffer[1][0], hSpatParamRendCom->num_freq_bands ); + set_zero( Cldfb_ImagBuffer[1][0], hSpatParamRendCom->num_freq_bands ); + } + + /*-----------------------------------------------------------------* + * prototype signal computation + *-----------------------------------------------------------------*/ + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + protoSignalComputation_shd( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f, + reference_power, slot_idx, nchan_transport, + hDirACRend->num_outputs_diff, + hSpatParamRendCom->num_freq_bands, + 0 ); + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, hDirACRend->proto_frame_f, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, + 0, slot_idx, hSpatParamRendCom->num_freq_bands, hDirACRend->masa_stereo_type_detect ); + } + else + { + switch ( nchan_transport ) + { + case 2: + protoSignalComputation2( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirACRend->proto_frame_f, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, + hDirACRend->hOutSetup.is_loudspeaker_setup, + slot_idx, + hSpatParamRendCom->num_freq_bands, + hDirACRend->masa_stereo_type_detect ); + break; + case 1: + protoSignalComputation1( Cldfb_RealBuffer, Cldfb_ImagBuffer, + hDirACRend->proto_frame_f, + hDirACRend->h_output_synthesis_psd_state.proto_direct_buffer_f, + reference_power, + hDirACRend->h_output_synthesis_psd_state.proto_power_smooth, + slot_idx, + hDirACRend->num_protos_diff, + hSpatParamRendCom->num_freq_bands ); + break; + default: + return; + } + } + + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ + + if ( hDirACRend->proto_signal_decorr_on == 1 ) + { + /* decorrelate prototype frame */ + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_decorr_process( hSpatParamRendCom->num_freq_bands, + hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->synthesisConf, + nchan_transport, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->proto_index_diff, + hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f + slot_idx * 2 * hSpatParamRendCom->num_freq_bands * hDirACRend->num_outputs_diff + 2 * hSpatParamRendCom->num_freq_bands * min( 4, nchan_transport ), + onset_filter, + hDirACRend->h_freq_domain_decorr_ap_params, + hDirACRend->h_freq_domain_decorr_ap_state ); + + v_multc( onset_filter, 0.25f, onset_filter, hSpatParamRendCom->num_freq_bands ); + v_add( onset_filter, onset_filter_subframe, onset_filter_subframe, hSpatParamRendCom->num_freq_bands ); + p_onset_filter = onset_filter_subframe; + } + else + { + ivas_dirac_dec_decorr_process( hSpatParamRendCom->num_freq_bands, + hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->synthesisConf, + nchan_transport, + hDirACRend->proto_frame_f, + hDirACRend->num_protos_diff, + hDirACRend->proto_index_diff, + DirAC_mem.frame_dec_f, + onset_filter, + hDirACRend->h_freq_domain_decorr_ap_params, + hDirACRend->h_freq_domain_decorr_ap_state ); + + hDirACRend->proto_frame_dec_f = DirAC_mem.frame_dec_f; + p_onset_filter = onset_filter; + } + } + else + { + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + set_f( onset_filter_subframe, 1.f, hSpatParamRendCom->num_freq_bands ); + p_onset_filter = onset_filter_subframe; + } + else + { + /* no frequency domain decorrelation: use prototype frame */ + hDirACRend->proto_frame_dec_f = hDirACRend->proto_frame_f; + p_onset_filter = NULL; + } + } + + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + /* Compute diffuse prototypes */ + ivas_dirac_dec_compute_diffuse_proto( hDirACRend, hSpatParamRendCom->num_freq_bands, slot_idx ); + } + + ivas_dirac_dec_output_synthesis_process_slot( reference_power, + p_onset_filter, + azimuth, + elevation, + hSpatParamRendCom->diffuseness_vector[md_idx], + hSpatParamRendCom, + hDirACRend, + 0, + 0, + hMasaExtRend->hVBAPdata, + hDirACRend->hOutSetup, + nchan_transport, + md_idx, + 0, + 0 ); + + if ( hDirACRend->synthesisConf != DIRAC_SYNTHESIS_GAIN_SHD ) + { + v_add( reference_power, reference_power_smooth, reference_power_smooth, hSpatParamRendCom->num_freq_bands ); + } + } + + ivas_dirac_dec_output_synthesis_get_interpolator( &hDirACRend->h_output_synthesis_psd_params, hSpatParamRendCom->subframe_nbslots[subframe_idx] ); + + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + ivas_dirac_dec_output_synthesis_process_subframe_gain_shd( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hSpatParamRendCom, + hDirACRend, + nchan_transport, + hSpatParamRendCom->subframe_nbslots[subframe_idx], + p_onset_filter, + diffuseness_vector, + 0, + 0 ); + } + else + { + ivas_dirac_dec_output_synthesis_process_subframe_psd_ls( Cldfb_RealBuffer, + Cldfb_ImagBuffer, + hSpatParamRendCom, + hDirACRend, + hSpatParamRendCom->subframe_nbslots[subframe_idx], + diffuseness_vector, + reference_power_smooth, + 1.0f, + 0 ); + } + + /*-----------------------------------------------------------------* + * CLDFB synthesis (and binaural rendering) + *-----------------------------------------------------------------*/ + + index_slot = slot_idx_start_cldfb_synth; + + { + float *RealBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + float *ImagBuffer[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t outchannels; + + idx_in = 0; + idx_lfe = 0; + + outchannels = hDirACRend->hOutSetup.nchan_out_woLFE + hDirACRend->hOutSetup.num_lfe; + + /* Note here that compared to decoder path, there is no separate channel ever for MASA ext rend path */ + + for ( ch = 0; ch < outchannels; ch++ ) + { + if ( ( hDirACRend->hOutSetup.num_lfe > 0 ) && ( hDirACRend->hOutSetup.index_lfe[idx_lfe] == ch ) ) + { + /* No LFE for MASA rendering */ + set_zero( &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->subframe_nbslots[subframe_idx] * hSpatParamRendCom->num_freq_bands ); + + if ( idx_lfe < ( hDirACRend->hOutSetup.num_lfe - 1 ) ) + { + idx_lfe++; + } + } + else + { + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) + { + RealBuffer[i] = Cldfb_RealBuffer[idx_in][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[idx_in][i]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][index_slot * hSpatParamRendCom->num_freq_bands] ), hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->subframe_nbslots[subframe_idx], hMasaExtRend->cldfbSynRend[idx_in] ); + idx_in++; + } + } + } + hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe_idx]; + hSpatParamRendCom->subframes_rendered++; + + pop_wmops(); + + return; +} + +void ivas_masa_ext_dirac_render( + MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure */ + float *output_f[], /* i/o: input/output signals in time domain */ + const int16_t num_subframes /* i : number of subframes to render */ +) +{ + int16_t subframe_idx; + float *output_f_local[MAX_OUTPUT_CHANNELS]; + int16_t n, n_samples_sf; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + + hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; + + n_samples_sf = JBM_CLDFB_SLOTS_IN_SUBFRAME * hSpatParamRendCom->slot_size; + + for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + output_f_local[n] = output_f[n]; + } + + hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx; + + for ( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ ) + { + hSpatParamRendCom->slots_rendered = 0; + ivas_masa_ext_dirac_render_sf( hMasaExtRend, output_f_local ); + for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) + { + output_f_local[n] += n_samples_sf; + } + + hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length; + } + + return; +} +#endif diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 81612f51068d2407b9bc364da5a072f93433d7d3..0a63d12e4cf7ec91cd9ef178f849020a78c59424 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -240,6 +240,21 @@ void ivas_dirac_dec_binaural_render( float *output_f[] /* o : rendered time signal */ ); +#ifdef NONBE_FIX_225_MASA_EXT_REND +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 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const int16_t num_subframes, /* i : number of subframes to render */ + const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */ + float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */ + float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* o : rendered orientations for split rend. imag part of cldfb */ +#else + const int16_t num_subframes /* i : number of subframes to render */ +#endif +); +#endif ivas_error ivas_dirac_dec_init_binaural_data( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ @@ -521,6 +536,22 @@ void ivas_dirac_dec_compute_power_factors( float *diffuse_power_factor ); +#ifdef NONBE_FIX_225_MASA_EXT_REND +void ivas_dirac_dec_compute_directional_responses( + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ + DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ + const VBAP_HANDLE hVBAPdata, /* i : VBAP structure */ + const int16_t *masa_band_mapping, /* i : Band mapping for MASA, NULL assumes not using MASA in any form */ + MASA_ISM_DATA_HANDLE hMasaIsm, /* i : MASA_ISM data structure */ + const int16_t *azimuth, + const int16_t *elevation, + const int16_t md_idx, + const float *surCohRatio, + const int16_t shd_rot_max_order, /* i : split-order rotation method */ + const float *p_Rmat, /* i : rotation matrix */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); +#else void ivas_dirac_dec_compute_directional_responses( SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial renderer data handle */ DIRAC_REND_HANDLE hDirACRend, /* i/o: DirAC renderer handle */ @@ -535,6 +566,7 @@ void ivas_dirac_dec_compute_directional_responses( const float *p_Rmat, /* i : rotation matrix */ const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ ); +#endif void ivas_dirac_dec_get_frequency_axis( float *frequency_axis, /* o : array of center frequencies of a real filter bank */ @@ -549,7 +581,12 @@ ivas_error ivas_spat_hSpatParamRendCom_config( const IVAS_FORMAT ivas_format, const MC_MODE mc_mode, const int32_t output_Fs, +#ifdef NONBE_FIX_225_MASA_EXT_REND + const int16_t hodirac_flag, + const int16_t masa_ext_rend_flag +#else const int16_t hodirac_flag +#endif ); void ivas_spat_hSpatParamRendCom_close( @@ -570,6 +607,13 @@ void ivas_dirac_deallocate_parameters( const int16_t params_flag /* i : set of parameters flag */ ); +#ifdef NONBE_FIX_225_MASA_EXT_REND +void ivas_masa_ext_dirac_render( + MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure */ + float *output_f[], /* i/o: input/output signals in time domain */ + const int16_t num_subframes /* i : number of subframes to render */ +); +#endif /*----------------------------------------------------------------------------------* * HRTF diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index 93483575617e54207ebe4bd294593580b8ff397d..4aef137a33b365afe3760b3c6d39d799f0754944 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -39,6 +39,151 @@ /* clang-format off */ +#ifdef NONBE_FIX_225_MASA_EXT_REND +/*----------------------------------------------------------------------------------* + * DirAC renderer ROM tables + *----------------------------------------------------------------------------------*/ + +const float ls_azimuth_4d4[8] = { 45.0f, -45.0f, 135.0f, -135.0f, 45.0f, -45.0f, 135.0f, -135.0f }; + +const float ls_elevation_4d4[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 35.0f, 35.0f, 35.0f, 35.0f }; + +const float diffuse_response_CICP6[5] = { 0.4219f, 0.4219f, 0.3704f, 0.5034f, 0.5034f }; + +const float diffuse_response_CICP14[7] = { 0.3817f, 0.3817f, 0.2819f, 0.5399f, 0.5399f, 0.1519f, 0.1519f }; + +const float diffuse_response_CICP16[9] = { 0.3456f, 0.3456f, 0.3035f, 0.4124f, 0.4124f, 0.2702f, 0.2702f, 0.3023f, 0.3023f }; + +const int16_t ap_pre_delay[DIRAC_DECORR_NUM_SPLIT_BANDS] = { 7, 2, 1 }; + +const int16_t ap_filter_length[DIRAC_DECORR_NUM_SPLIT_BANDS] = { 15, 6, 3 }; + +const float ap_lattice_delta_phi[DIRAC_MAX_NUM_DECORR_FILTERS*DIRAC_MAX_DECORR_FILTER_LEN] = +{ + 1.802519f, 0.922986f, 1.813685f, 1.272828f, 0.856928f, 0.366571f, 1.531249f, 1.318158f, 0.123812f, 0.897173f, 0.958696f, 1.256384f, 0.179677f, 0.668918f, 1.440292f, 1.573058f, 1.396481f, 1.191463f, 0.444143f, 1.666942f, + 1.273955f, 1.747171f, 1.408330f, 1.002782f, 1.559302f, 1.782992f, 1.474896f, 0.813181f, 1.457724f, 0.588531f, 1.384302f, 0.156493f, 0.600048f, 1.661632f, 0.538958f, 0.645429f, 0.565237f, 0.024684f, 0.264229f, 0.062140f, + 1.235343f, 0.851725f, 1.820211f, 0.116148f, 0.972111f, 0.488703f, 1.777672f, 1.452170f, 0.814134f, 1.272649f, 1.281416f, 0.101871f, 0.897888f, 0.199760f, 0.085732f, 1.686579f, 0.964558f, 0.057281f, 0.910252f, 1.662302f, + 0.955234f, 0.834348f, 1.672478f, 1.324896f, 0.444544f, 1.721172f, 0.153356f, 1.602240f, 0.171880f, 1.169774f, 0.543628f, 1.409581f, 1.763724f, 1.686754f, 1.210390f, 0.402691f, 0.983618f, 0.862997f, 1.220409f, 0.890061f, + 0.031641f, 0.461590f, 1.719550f, 1.357698f, 1.112262f, 1.166531f, 0.246097f, 1.387325f, 0.177485f, 1.446268f, 0.799476f, 1.667227f, 1.723465f, 1.505920f, 0.245874f, 1.155854f, 0.831394f, 0.677194f, 0.568871f, 1.652070f, + 0.019803f, 1.197794f, 0.635553f, 0.531682f, 0.878194f, 0.048050f, 0.080480f, 1.566743f, 0.724210f, 0.853668f, 1.741191f, 0.698465f, 1.553550f, 0.130290f, 0.688346f, 1.331091f, 0.599759f, 1.125466f, 1.764818f, 1.042879f, + 1.486589f, 1.627971f, 1.871181f, 0.102359f, 0.035021f, 1.403176f, 1.468675f, 0.190347f, 0.553282f, 1.031227f, 1.232390f, 1.255724f, 1.504443f, 0.683526f, 0.600958f, 1.746936f, 1.529243f, 1.448196f, 0.646850f, 0.116053f, + 1.283295f, 0.355220f, 1.380620f, 1.858453f, 0.818804f, 0.219006f, 0.476292f, 0.420029f, 1.291187f, 0.568738f, 1.174088f, 0.628805f, 1.753154f, 1.459582f, 1.354449f, 1.755790f, 0.441757f, 0.856240f, 1.647962f, 0.686353f, + 1.395289f, 0.699934f, 0.239310f, 0.239535f, 0.958190f, 0.748780f, 0.513784f, 1.666344f, 1.461995f, 1.599060f, 0.893107f, 0.341873f, 1.387703f, 1.808363f, 0.676542f, 1.424958f, 0.310574f, 0.836247f, 1.011101f, 1.686200f, + 1.823432f, 0.994827f, 1.635555f, 0.684380f, 1.017029f, 1.440371f, 1.694641f, 0.607132f, 1.197331f, 0.862161f, 0.666449f, 1.047956f, 0.159627f, 0.043131f, 1.251515f, 1.618724f, 0.216906f, 0.152250f, 0.471610f, 0.744260f, + 0.576810f, 1.632177f, 1.556912f, 1.866317f, 0.568088f, 1.541817f, 1.726725f, 0.275154f, 0.814958f, 0.863399f, 1.333040f, 0.148277f, 0.197893f, 1.048665f, 1.158090f, 1.692225f, 0.884294f, 0.289619f, 0.380633f, 1.728234f, + 1.433213f, 1.749505f, 1.533837f, 0.669701f, 0.372580f, 1.052390f, 1.116645f, 0.181320f, 1.139126f, 0.222671f, 0.604393f, 1.811797f, 1.743315f, 1.368792f, 1.861434f, 0.751908f, 0.159811f, 1.566503f, 0.443273f, 1.667530f, + 1.083060f, 1.243136f, 0.717777f, 0.675019f, 0.690490f, 0.672228f, 1.060789f, 0.423566f, 1.198457f, 0.485768f, 0.993953f, 0.443540f, 0.361702f, 1.552042f, 0.863562f, 1.517677f, 1.061899f, 0.691413f, 1.642818f, 1.756590f, + 0.278323f, 0.790363f, 0.172303f, 0.417138f, 0.009343f, 0.783325f, 1.369303f, 1.041067f, 0.467102f, 0.992773f, 1.525170f, 0.871213f, 0.243906f, 1.542036f, 0.449148f, 0.843633f, 0.191800f, 1.614246f, 1.038188f, 1.415620f, + 0.551081f, 0.382599f, 1.410121f, 0.102084f, 0.137286f, 0.671081f, 0.254860f, 1.758068f, 1.079013f, 0.129143f, 1.410873f, 0.150485f, 0.601119f, 0.760737f, 0.975905f, 0.223261f, 0.710162f, 1.677048f, 0.996836f, 1.849865f, + 1.536222f, 0.089016f, 0.960881f, 0.388690f, 0.379955f, 1.002223f, 1.271420f, 1.410632f, 0.254397f, 1.535559f, 1.133703f, 1.305280f, 1.466565f, 0.274167f, 0.399688f, 1.359638f, 1.766289f, 1.401348f, 1.310883f, 0.261030f, + 1.314825f, 1.538635f, 1.317986f, 1.243167f, 1.749461f, 1.689706f, 0.024853f, 0.634754f, 1.036317f, 1.828101f, 1.676951f, 0.023606f, 0.857000f, 0.076471f, 1.622198f, 0.254469f, 1.451625f, 1.720881f, 0.763812f, 0.186982f, + 0.056994f, 0.590507f, 0.375291f, 1.609261f, 0.607721f, 0.026355f, 0.483366f, 0.823931f, 0.792878f, 0.163577f, 0.753588f, 0.730789f, 0.135991f, 1.031660f, 1.554135f, 1.192863f, 0.016693f, 0.125796f, 1.017920f, 1.591773f, + 0.575956f, 0.112943f, 0.249506f, 1.399570f, 0.053241f, 1.410759f, 0.251638f, 1.059086f, 0.025315f, 1.422914f, 1.030412f, 0.848758f, 0.317396f, 1.375456f, 1.116858f, 1.682310f, 0.279550f, 0.325974f, 0.937704f, 1.744329f, + 0.447773f, 1.024286f, 1.001528f, 1.863684f, 1.278323f, 0.860699f, 1.346331f, 1.692596f, 0.022627f, 1.033613f, 0.546354f, 0.395804f, 1.486546f, 1.381045f, 1.312260f, 0.245976f, 1.607429f, 1.818793f, 0.964359f, 1.496598f, + 0.669967f, 1.535929f, 1.841878f, 0.979127f, 0.614002f, 1.879218f, 0.512531f, 1.167061f, 0.081697f, 1.773427f, 1.535668f, 0.757729f, 0.220395f, 1.538243f, 1.281162f, 0.302159f, 0.889871f, 0.798522f, 1.476288f, 1.665941f, + 0.915365f, 1.394094f, 0.757041f, 0.350064f, 1.199679f, 1.319499f, 1.128405f, 0.632337f, 0.790673f, 0.461582f, 1.693343f, 1.537442f, 0.346527f, 0.433782f, 1.754552f, 0.550903f, 0.686724f, 0.764433f, 1.792750f, 1.489998f +}; + +const float ap_lattice_coeffs_1[DIRAC_DECORR_FILTER_LEN_1*DIRAC_MAX_NUM_DECORR_FILTERS] = +{ + 0.795329f, 0.502700f, 0.204456f, 0.416566f, 0.459648f, 0.270454f, -0.201944f, 0.027997f, 0.067811f, -0.052627f, -0.038779f, -0.057387f, 0.020480f, 0.367697f, -0.593705f, + 0.533667f, 0.202500f, -0.001953f, 0.195081f, -0.184458f, -0.233867f, 0.228100f, -0.329293f, -0.338714f, -0.079700f, 0.052389f, -0.009468f, 0.178807f, 0.190843f, -0.478877f, + 0.044022f, 0.788498f, 0.133529f, -0.173657f, 0.545391f, 0.681431f, 0.332868f, 0.294685f, 0.325261f, 0.047617f, 0.157401f, 0.116272f, 0.218980f, -0.189248f, -0.317401f, + -0.753681f, 0.772385f, -0.507384f, 0.276980f, -0.692775f, 0.232302f, -0.354759f, -0.015620f, -0.223059f, 0.310506f, -0.035034f, 0.085783f, -0.499998f, 0.215260f, 0.201415f, + -0.495551f, -0.301660f, 0.196510f, 0.326147f, -0.594364f, 0.314921f, 0.668671f, 0.076643f, 0.045711f, -0.124790f, -0.203272f, -0.297190f, 0.125806f, -0.179483f, -0.201757f, + 0.161128f, 0.396050f, 0.266897f, 0.356586f, 0.488145f, -0.056254f, 0.139280f, -0.296405f, -0.112844f, 0.037405f, -0.367425f, -0.216292f, -0.277360f, 0.389420f, 0.115115f, + -0.240449f, -0.271015f, 0.426720f, -0.011059f, 0.151813f, 0.253490f, 0.225764f, 0.498716f, -0.136377f, 0.443004f, -0.305017f, -0.031310f, -0.010765f, 0.170349f, 0.496478f, + -0.139875f, -0.241998f, -0.104850f, 0.294343f, -0.067728f, -0.492202f, -0.487610f, 0.036395f, 0.109393f, 0.396155f, -0.352845f, -0.205913f, -0.082999f, -0.463033f, -0.309296f, + 0.025886f, -0.092456f, -0.125139f, -0.156117f, -0.004887f, 0.178440f, 0.089586f, 0.044827f, 0.238219f, -0.312120f, -0.390688f, -0.178543f, 0.454418f, 0.387012f, -0.388874f, + -0.197797f, 0.035540f, 0.455388f, -0.054410f, 0.380035f, 0.290964f, 0.048804f, 0.078637f, 0.221740f, -0.217548f, 0.121289f, -0.396681f, -0.218482f, -0.127265f, -0.269507f, + -0.344218f, -0.465038f, -0.421415f, -0.026031f, 0.221547f, 0.361993f, -0.348243f, 0.294983f, 0.366175f, 0.070663f, -0.086050f, 0.252129f, 0.156066f, -0.062800f, 0.408972f, + 0.242461f, -0.301764f, -0.066160f, 0.388651f, -0.462227f, -0.158880f, 0.230796f, -0.093179f, 0.047076f, 0.073402f, -0.335018f, 0.022940f, 0.354611f, 0.072391f, 0.019473f, + 0.336900f, -0.480534f, 0.170267f, 0.259663f, -0.393576f, -0.348588f, -0.108962f, 0.278842f, 0.385490f, 0.362249f, -0.318739f, 0.362305f, 0.288936f, 0.291204f, -0.278019f, + -0.449302f, -0.288513f, -0.413973f, -0.405279f, -0.295152f, -0.245110f, 0.002530f, 0.287890f, 0.348229f, -0.178354f, -0.206517f, 0.351081f, -0.482205f, 0.021360f, -0.492207f, + 0.048642f, 0.453282f, 0.109160f, 0.232599f, -0.473781f, 0.140502f, 0.352527f, -0.098606f, 0.147172f, -0.055797f, 0.107739f, -0.231026f, 0.357310f, 0.348031f, 0.232404f, + -0.324788f, 0.162480f, 0.057647f, -0.060734f, -0.009742f, -0.224185f, -0.282355f, -0.065443f, 0.064697f, 0.280370f, -0.284906f, -0.470501f, 0.019484f, -0.442308f, 0.377214f, + 0.447384f, -0.290498f, 0.345528f, 0.370207f, -0.313120f, 0.119592f, 0.300014f, 0.406995f, -0.277922f, 0.447039f, 0.194824f, 0.157703f, -0.223402f, -0.147167f, 0.379073f, + -0.216342f, 0.137967f, -0.397180f, 0.073905f, -0.273110f, -0.443037f, -0.168327f, 0.346264f, 0.037543f, 0.065387f, 0.163901f, -0.122523f, 0.365477f, -0.316321f, 0.117273f, + -0.301282f, 0.169625f, -0.336466f, 0.269914f, -0.420160f, -0.331296f, 0.498523f, -0.393009f, -0.462184f, -0.323097f, 0.470977f, -0.359463f, 0.264315f, 0.216797f, 0.493400f, + 0.151489f, -0.321653f, 0.464413f, -0.355673f, 0.420401f, 0.184297f, -0.302128f, 0.136536f, -0.252849f, 0.193906f, 0.298775f, 0.238808f, -0.386298f, -0.181999f, -0.077326f, + 0.124840f, -0.263394f, 0.389606f, 0.004502f, 0.339804f, 0.415204f, 0.377751f, 0.400221f, 0.352426f, -0.003808f, -0.184530f, 0.433348f, -0.237554f, 0.147684f, 0.407210f, + 0.067616f, -0.249313f, -0.354010f, 0.320937f, 0.426000f, 0.309576f, -0.189689f, -0.209447f, 0.158967f, -0.081929f, 0.386828f, 0.178582f, -0.407143f, 0.222189f, -0.149097f +}; + +const float ap_lattice_coeffs_2[DIRAC_DECORR_FILTER_LEN_2*DIRAC_MAX_NUM_DECORR_FILTERS] = +{ + 0.633692f, 0.681207f, -0.049418f, 0.286715f, 0.146022f, 0.135402f, + -0.410145f, -0.206766f, -0.656968f, -0.101746f, 0.436299f, 0.339818f, + -0.131383f, -0.773746f, -0.301627f, 0.327561f, 0.332227f, 0.205858f, + 0.717602f, -0.552370f, -0.150136f, 0.054556f, 0.239519f, -0.648477f, + -0.721848f, 0.189377f, 0.068185f, 0.006216f, 0.077025f, 0.038678f, + 0.423415f, -0.108658f, 0.432050f, -0.414641f, 0.277840f, 0.418486f, + 0.077811f, -0.283063f, -0.357008f, 0.004634f, -0.442640f, -0.372315f, + 0.403336f, 0.243023f, 0.314367f, 0.444513f, 0.347517f, 0.496043f, + 0.108408f, 0.469382f, -0.170286f, 0.326310f, 0.172157f, 0.440334f, + 0.058417f, 0.339673f, -0.194965f, 0.491219f, -0.281296f, -0.043120f, + -0.482487f, -0.335005f, -0.336159f, 0.196469f, -0.164623f, 0.442491f, + -0.135190f, -0.354385f, 0.452133f, -0.311221f, -0.347640f, 0.498342f, + -0.288999f, 0.376431f, -0.177924f, 0.195542f, 0.333872f, -0.152697f, + 0.053230f, 0.457767f, 0.442476f, 0.235254f, -0.345159f, -0.286098f, + 0.155438f, 0.405393f, 0.217073f, -0.107960f, 0.010698f, 0.368987f, + -0.498358f, -0.495816f, -0.215479f, -0.093869f, 0.320276f, -0.013842f, + 0.489406f, 0.470814f, -0.065834f, 0.346871f, 0.027279f, 0.150086f, + 0.484013f, -0.497391f, 0.168796f, -0.493841f, -0.173528f, 0.334676f, + 0.264235f, -0.424651f, -0.314926f, 0.253086f, 0.397381f, -0.491565f, + -0.453727f, -0.463358f, -0.019128f, 0.000344f, 0.315432f, 0.472345f, + 0.095139f, 0.283375f, -0.225088f, -0.119762f, -0.476871f, 0.037525f, + 0.336951f, 0.494511f, -0.062603f, 0.177652f, 0.463892f, 0.489286f +}; + +const float ap_lattice_coeffs_3[DIRAC_DECORR_FILTER_LEN_3*DIRAC_MAX_NUM_DECORR_FILTERS] = +{ + 0.018977f, -0.212205f, 0.422719f, + -0.400657f, -0.106890f, -0.024589f, + 0.140005f, 0.279582f, 0.032357f, + 0.632535f, 0.578535f, -0.734606f, + 0.017182f, 0.013244f, -0.027715f, + -0.353356f, -0.482160f, -0.491265f, + 0.457024f, 0.165122f, 0.469723f, + -0.195705f, 0.440105f, -0.477366f, + 0.360186f, -0.490565f, 0.484623f, + -0.173791f, 0.007543f, 0.278186f, + 0.434416f, 0.060363f, -0.193717f, + -0.033709f, 0.496222f, 0.002939f, + -0.480848f, -0.109552f, -0.023198f, + 0.324679f, -0.292075f, -0.356148f, + -0.366595f, 0.380917f, -0.301741f, + 0.110318f, 0.383789f, 0.303984f, + -0.499685f, -0.349584f, 0.334749f, + -0.020224f, -0.430078f, -0.154705f, + -0.371129f, 0.334080f, 0.346913f, + -0.166781f, -0.229089f, 0.117956f, + 0.341292f, 0.490463f, 0.493655f, + -0.367726f, 0.426528f, -0.045774f +}; + +const float * const ap_lattice_coeffs[DIRAC_DECORR_NUM_SPLIT_BANDS] = +{ + &ap_lattice_coeffs_1[0], + &ap_lattice_coeffs_2[0], + &ap_lattice_coeffs_3[0], +}; + +const float ap_split_frequencies[DIRAC_DECORR_NUM_SPLIT_BANDS + 1] = +{ + 0.0f, 0.125f, 0.375f, 1.0f +}; + +const int16_t sba_map_tc[11] = +{ + 0, 1, 2, 3, 4, 8, 9, 15, 5, 6, 7 +}; +const int16_t sba_map_tc_512[11] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15 +}; +#endif + /*----------------------------------------------------------------------------------* * FASTCONV and PARAMETRIC binaural renderer ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h index 0e42c33286b69ef62a64f3c5f29b92cf060dac0f..db0c7d1c33401f1eca73133fb457cbd8bc50abd5 100644 --- a/lib_rend/ivas_rom_rend.h +++ b/lib_rend/ivas_rom_rend.h @@ -41,6 +41,30 @@ #include "ivas_cnst.h" #include "ivas_stat_rend.h" +#ifdef NONBE_FIX_225_MASA_EXT_REND +/*----------------------------------------------------------------------------------* + * DirAC renderer ROM tables + *----------------------------------------------------------------------------------*/ + +extern const float ls_azimuth_4d4[8]; +extern const float ls_elevation_4d4[8]; +extern const float diffuse_response_CICP6[5]; +extern const float diffuse_response_CICP14[7]; +extern const float diffuse_response_CICP16[9]; + +extern const int16_t ap_pre_delay[DIRAC_DECORR_NUM_SPLIT_BANDS]; +extern const int16_t ap_filter_length[DIRAC_DECORR_NUM_SPLIT_BANDS]; +extern const float ap_lattice_delta_phi[DIRAC_MAX_NUM_DECORR_FILTERS * DIRAC_MAX_DECORR_FILTER_LEN]; +extern const float ap_lattice_coeffs_1[DIRAC_DECORR_FILTER_LEN_1 * DIRAC_MAX_NUM_DECORR_FILTERS]; +extern const float ap_lattice_coeffs_2[DIRAC_DECORR_FILTER_LEN_2 * DIRAC_MAX_NUM_DECORR_FILTERS]; +extern const float ap_lattice_coeffs_3[DIRAC_DECORR_FILTER_LEN_3 * DIRAC_MAX_NUM_DECORR_FILTERS]; +extern const float *const ap_lattice_coeffs[DIRAC_DECORR_NUM_SPLIT_BANDS]; +extern const float ap_split_frequencies[DIRAC_DECORR_NUM_SPLIT_BANDS + 1]; + +extern const int16_t sba_map_tc[11]; +extern const int16_t sba_map_tc_512[11]; +#endif + /*----------------------------------------------------------------------------------* * FASTCONV and PARAMETRIC binaural renderer ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index e461f17311a4b62fa3cfa0351d25bde9ef67d554..ee9ee3f9065f1a0a6bda202d74667856b5c06e33 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1614,6 +1614,34 @@ typedef enum } ChannelType; +#ifdef NONBE_FIX_225_MASA_EXT_REND +/*----------------------------------------------------------------------------------* + * MASA external renderer structure + *----------------------------------------------------------------------------------*/ + +typedef struct ivas_masa_external_rendering_struct +{ + int16_t nchan_input; + int16_t nchan_output; + RENDERER_TYPE renderer_type; + DIRAC_REND_HANDLE hDirACRend; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; +#ifdef SPLIT_REND_WITH_HEAD_ROT + DIRAC_DEC_BIN_HANDLE hDiracDecBin[MAX_HEAD_ROT_POSES]; +#else + DIRAC_DEC_BIN_HANDLE hDiracDecBin; +#endif + + REVERB_STRUCT_HANDLE hReverb; + HRTFS_PARAMBIN_HANDLE hHrtfParambin; + VBAP_HANDLE hVBAPdata; + float *hoa_dec_mtx; + + HANDLE_CLDFB_FILTER_BANK cldfbAnaRend[MASA_MAX_TRANSPORT_CHANNELS]; + HANDLE_CLDFB_FILTER_BANK cldfbSynRend[MAX_OUTPUT_CHANNELS]; +} MASA_EXT_REND_DATA, *MASA_EXT_REND_HANDLE; +#endif + /*----------------------------------------------------------------------------------* * Multichannel MASA (McMASA) analysis structure *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index a64bdf33b2e966803bf8a4dfd802b05c97fb3e3a..c7e0461ddd9d47641fcebefc4d237a98568303d3 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -212,18 +212,29 @@ typedef struct } input_split_post_rend; #endif +#ifndef NONBE_FIX_225_MASA_EXT_REND /* Due to API of some rendering methods, the renderer has to use the decoder struct. Only struct members relevant for rendering will be initialized, therefore typedef as "dummy" decoder struct */ typedef Decoder_Struct DecoderDummy; +#endif typedef struct { +#ifdef NONBE_FIX_225_MASA_EXT_REND + input_base base; + MASA_METADATA_FRAME masaMetadata; + bool metadataHasBeenFed; + float *bufferData; + MASA_EXT_REND_HANDLE hMasaExtRend; + MASA_PREREND_HANDLE hMasaPrerend; +#else input_base base; DecoderDummy *decDummy; MASA_METADATA_FRAME masaMetadata; bool metadataHasBeenFed; float *bufferData; MASA_PREREND_HANDLE hMasaPrerend; +#endif } input_masa; struct IVAS_REND @@ -267,6 +278,15 @@ struct IVAS_REND }; +#ifdef NONBE_FIX_225_MASA_EXT_REND +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ + +static ivas_error initMasaExtRenderer( input_masa *inputMasa, const AUDIO_CONFIG outConfig ); +static void freeMasaExtRenderer( MASA_EXT_REND_HANDLE *hMasaExtRendOut ); +#endif + /*-------------------------------------------------------------------* * Local functions *-------------------------------------------------------------------*/ @@ -646,18 +666,33 @@ static ivas_error validateOutputSampleRate( /* If no binaural rendering, any sampling rate is supported */ return IVAS_ERR_OK; } - - /* Otherwise rendering to binaural, support the same set as IVAS decoder */ - switch ( sampleRate ) +#ifdef NONBE_FIX_225_MASA_EXT_REND +#ifdef SPLIT_REND_WITH_HEAD_ROT + else if ( ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && sampleRate != 48000 ) { - case 8000: - case 16000: - case 32000: - case 48000: - return IVAS_ERR_OK; + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Error: Only 48kHz output sampling rate is supported for split rendering." ); } + else + { +#endif +#endif - return IVAS_ERR_INVALID_SAMPLING_RATE; + /* Otherwise rendering to binaural, support the same set as IVAS decoder */ + switch ( sampleRate ) + { + case 8000: + case 16000: + case 32000: + case 48000: + return IVAS_ERR_OK; + } + + return IVAS_ERR_INVALID_SAMPLING_RATE; +#ifdef NONBE_FIX_225_MASA_EXT_REND +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif +#endif } @@ -2925,6 +2960,7 @@ static void clearInputSba( } +#ifndef NONBE_FIX_225_MASA_EXT_REND static ivas_error initMasaDummyDecForMcOut( input_masa *inputMasa, const AUDIO_CONFIG outConfig ) @@ -3308,7 +3344,7 @@ static DecoderDummy *initDecoderDummy( return decDummy; } - +#endif static ivas_error setRendInputActiveMasa( void *input, @@ -3353,6 +3389,14 @@ static ivas_error setRendInputActiveMasa( } else { +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( ( error = initMasaExtRenderer( inputMasa, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + inputMasa->metadataHasBeenFed = false; +#else #ifdef SPLIT_REND_WITH_HEAD_ROT inputMasa->decDummy = initDecoderDummy( *rendCtx.pOutSampleRate, numInChannels, outConfig, 0, rendCtx.pSplitRendWrapper ); #else @@ -3365,12 +3409,13 @@ static ivas_error setRendInputActiveMasa( { return error; } +#endif } return IVAS_ERR_OK; } - +#ifndef NONBE_FIX_225_MASA_EXT_REND static void freeDecoderDummy( DecoderDummy **ppDecDummy ) { @@ -3475,7 +3520,7 @@ static void freeDecoderDummy( return; } - +#endif static void clearInputMasa( input_masa *inputMasa ) @@ -3487,9 +3532,14 @@ static void clearInputMasa( freeInputBaseBufferData( &inputMasa->bufferData ); masaPrerendClose( &inputMasa->hMasaPrerend ); +#ifdef NONBE_FIX_225_MASA_EXT_REND + freeMasaExtRenderer( &inputMasa->hMasaExtRend ); +#endif initRendInputBase( &inputMasa->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); +#ifndef NONBE_FIX_225_MASA_EXT_REND freeDecoderDummy( &inputMasa->decDummy ); +#endif return; } @@ -3712,10 +3762,15 @@ ivas_error IVAS_REND_Open( { initRendInputBase( &hIvasRend->inputsMasa[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 ); +#ifndef NONBE_FIX_225_MASA_EXT_REND hIvasRend->inputsMasa[i].decDummy = NULL; +#endif hIvasRend->inputsMasa[i].metadataHasBeenFed = false; hIvasRend->inputsMasa[i].bufferData = NULL; hIvasRend->inputsMasa[i].hMasaPrerend = NULL; +#ifdef NONBE_FIX_225_MASA_EXT_REND + hIvasRend->inputsMasa[i].hMasaExtRend = NULL; +#endif } #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -8058,7 +8113,12 @@ static ivas_error renderActiveInputsSba( static void copyMasaMetadataToDiracRenderer( MASA_METADATA_FRAME *meta, +#ifdef NONBE_FIX_225_MASA_EXT_REND + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, + const int16_t maxBin ) +#else SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom ) +#endif { int16_t band, sf, bin; int16_t meta_write_index; @@ -8072,7 +8132,11 @@ static void copyMasaMetadataToDiracRenderer( for ( band = 0; band < MASA_MAXIMUM_CODING_SUBBANDS; band++ ) { +#ifdef NONBE_FIX_225_MASA_EXT_REND + for ( bin = MASA_band_grouping_24[band]; bin < MASA_band_grouping_24[band + 1] && bin < maxBin; bin++ ) +#else for ( bin = MASA_band_grouping_24[band]; bin < MASA_band_grouping_24[band + 1]; bin++ ) +#endif { hSpatParamRendCom->azimuth[meta_write_index][bin] = (int16_t) meta->directional_meta[0].azimuth[sf][band]; hSpatParamRendCom->elevation[meta_write_index][bin] = (int16_t) meta->directional_meta[0].elevation[sf][band]; @@ -8098,7 +8162,7 @@ static void copyMasaMetadataToDiracRenderer( return; } - +#ifndef NONBE_FIX_225_MASA_EXT_REND static void renderMasaToMc( input_masa *masaInput, IVAS_REND_AudioBuffer outAudio ) @@ -8210,7 +8274,7 @@ static void renderMasaToBinaural( return; } - +#endif static void renderMasaToMasa( input_masa *masaInput, @@ -8345,8 +8409,20 @@ static ivas_error renderInputMasa( IVAS_REND_AudioBuffer outAudio ) { IVAS_REND_AudioBuffer inAudio; +#ifdef NONBE_FIX_225_MASA_EXT_REND + int16_t ch; + int16_t maxBin; + float *tmpBuffer[MAX_OUTPUT_CHANNELS]; + float tmpBuffer_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t cldfb2tdSampleFact; + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#endif +#else #ifdef SPLIT_REND_WITH_HEAD_ROT int16_t cldfb2tdSampleFact; +#endif #endif if ( !masaInput->metadataHasBeenFed ) @@ -8370,11 +8446,90 @@ static ivas_error renderInputMasa( /* Apply input gain to new audio */ v_multc( inAudio.data, masaInput->base.gain, inAudio.data, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); +#ifdef NONBE_FIX_225_MASA_EXT_REND + maxBin = (int16_t) ( *masaInput->base.ctx.pOutSampleRate * INV_CLDFB_BANDWIDTH ); +#endif + #ifdef NONBE_UNIFIED_DECODING_PATHS /* set combined orientation subframe info to start info */ ivas_combined_orientation_set_to_start_index( *( masaInput->base.ctx.pCombinedOrientationData ) ); #endif +#ifdef NONBE_FIX_225_MASA_EXT_REND + if ( getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) + { + /* MASA prerendering path for MASA -> MASA */ + renderMasaToMasa( masaInput, outAudio ); + } + else + { + /* MASA external renderer -> other formats */ + int16_t num_subframes; + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + { + tmpBuffer[ch] = tmpBuffer_buff[ch]; + } + + copyBufferTo2dArray( masaInput->base.inputBuffer, tmpBuffer_buff ); + + num_subframes = (int16_t) ( masaInput->base.inputBuffer.config.numSamplesPerChannel / ( *masaInput->base.ctx.pOutSampleRate / ( IVAS_NUM_FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + /* split rendering. use the combined of the first subframe in all subframes */ + int16_t sf, i, j; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; + pCombinedOrientationData = *masaInput->base.ctx.pCombinedOrientationData; + for ( sf = 1; sf < pCombinedOrientationData->num_subframes; sf++ ) + { + pCombinedOrientationData->Quaternions[sf] = pCombinedOrientationData->Quaternions[0]; + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < 3; j++ ) + { + pCombinedOrientationData->Rmat[sf][i][j] = pCombinedOrientationData->Rmat[0][i][j]; + } + } + } + + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); + + ivas_masa_ext_rend_parambin_render( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, num_subframes, masaInput->base.ctx.pSplitRendWrapper, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); + + accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + } + else + { + /* non-split path */ +#endif + switch ( masaInput->hMasaExtRend->renderer_type ) + { + case RENDERER_DIRAC: + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); + ivas_masa_ext_dirac_render( masaInput->hMasaExtRend, tmpBuffer, num_subframes ); + break; + case RENDERER_STEREO_PARAMETRIC: + case RENDERER_BINAURAL_PARAMETRIC: + case RENDERER_BINAURAL_PARAMETRIC_ROOM: + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_masa_ext_rend_parambin_render( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, num_subframes, NULL, NULL, NULL ); +#else + ivas_masa_ext_rend_parambin_render( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, num_subframes ); +#endif + break; + case RENDERER_DISABLE: + break; /* This happens for 1TC MASA to MONO where we just copy input transport to output */ + default: + return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) ); + } + + accumulate2dArrayToBuffer( tmpBuffer_buff, &outAudio ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif +#else switch ( getAudioConfigType( outConfig ) ) { case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: @@ -8418,6 +8573,7 @@ static ivas_error renderInputMasa( break; default: return IVAS_ERR_INVALID_OUTPUT_FORMAT; +#endif } return IVAS_ERR_OK; @@ -8431,7 +8587,9 @@ static ivas_error renderActiveInputsMasa( int16_t i; input_masa *pCurrentInput; ivas_error error; +#ifndef NONBE_FIX_225_MASA_EXT_REND int16_t sf_idx; +#endif for ( i = 0, pCurrentInput = hIvasRend->inputsMasa; i < RENDERER_MAX_MASA_INPUTS; ++i, ++pCurrentInput ) { @@ -8441,6 +8599,7 @@ static ivas_error renderActiveInputsMasa( continue; } +#ifndef NONBE_FIX_225_MASA_EXT_REND if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && pCurrentInput->decDummy->hHeadTrackData != NULL ) { for ( sf_idx = 0; sf_idx < hIvasRend->num_subframes; ++sf_idx ) @@ -8449,7 +8608,7 @@ static ivas_error renderActiveInputsMasa( pCurrentInput->decDummy->hHeadTrackData->Pos[sf_idx] = hIvasRend->headRotData.Pos[sf_idx]; } } - +#endif if ( ( error = renderInputMasa( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) { return error; @@ -9149,3 +9308,764 @@ int32_t IVAS_REND_GetCntFramesLimited( return hIvasRend->hLimiter->cnt_frames_limited; } #endif + +#ifdef NONBE_FIX_225_MASA_EXT_REND +static ivas_error ivas_masa_ext_rend_dirac_rend_init( + input_masa *inputMasa ) +{ + int16_t nchan_out_woLFE; + int16_t nchan_transport; + uint16_t i, j, k; + float ls_azimuth[MAX_OUTPUT_CHANNELS]; + float ls_elevation[MAX_OUTPUT_CHANNELS]; + int32_t output_Fs; + ivas_error error; + DIRAC_REND_HANDLE hDirACRend; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + + error = IVAS_ERR_OK; + + hDirACRend = NULL; + output_Fs = *( inputMasa->base.ctx.pOutSampleRate ); + + hSpatParamRendCom = inputMasa->hMasaExtRend->hSpatParamRendCom; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + if ( ( hDirACRend = (DIRAC_REND_HANDLE) malloc( sizeof( DIRAC_REND_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC renderer\n" ) ); + } + + nchan_transport = inputMasa->base.inConfig == IVAS_AUDIO_CONFIG_MASA2 ? 2 : 1; + + /*-----------------------------------------------------------------* + * output setup: for parametric binaural renderer, use output setup, otherwise internal setup + *-----------------------------------------------------------------*/ + + ivas_output_init( &hDirACRend->hOutSetup, *inputMasa->base.ctx.pOutConfig ); + + if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) + { + /* Copy from ivas_ls_custom_setup */ + hDirACRend->hOutSetup.nchan_out_woLFE = inputMasa->base.ctx.pCustomLsOut->num_spk; + hDirACRend->hOutSetup.ls_azimuth = inputMasa->base.ctx.pCustomLsOut->ls_azimuth; + hDirACRend->hOutSetup.ls_elevation = inputMasa->base.ctx.pCustomLsOut->ls_elevation; + + hDirACRend->hOutSetup.num_lfe = inputMasa->base.ctx.pCustomLsOut->num_lfe; + hDirACRend->hOutSetup.index_lfe[0] = inputMasa->base.ctx.pCustomLsOut->lfe_idx[0]; + + hDirACRend->hOutSetup.is_loudspeaker_setup = TRUE; + hDirACRend->hOutSetup.is_planar_setup = (int8_t) inputMasa->base.ctx.pCustomLsOut->is_planar_setup; + } + + nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE; + + if ( hDirACRend->hOutSetup.ls_azimuth != NULL && hDirACRend->hOutSetup.ls_elevation != NULL ) + { + mvr2r( hDirACRend->hOutSetup.ls_azimuth, ls_azimuth, nchan_out_woLFE ); + mvr2r( hDirACRend->hOutSetup.ls_elevation, ls_elevation, nchan_out_woLFE ); + } + + if ( hDirACRend->hOutSetup.ambisonics_order == -1 ) + { + hDirACRend->hOutSetup.ambisonics_order = SBA_HOA3_ORDER; /* Order 3 is used by default in DirAC for SHD processing */ + if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_MONO || hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_STEREO ) + { + hDirACRend->hOutSetup.ambisonics_order = SBA_FOA_ORDER; + } + } + else if ( hDirACRend->hOutSetup.ambisonics_order >= SBA_FOA_ORDER ) + { + mvr2r( ls_azimuth_4d4, ls_azimuth, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); + mvr2r( ls_elevation_4d4, ls_elevation, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS ); + } + + /*-----------------------------------------------------------------* + * set input parameters + *-----------------------------------------------------------------*/ + + if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_MONO ) + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_MONO; + hDirACRend->panningConf = DIRAC_PANNING_HOA3; + nchan_out_woLFE = 1; + } + else if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_LS; + hDirACRend->panningConf = DIRAC_PANNING_VBAP; + } + else if ( !hDirACRend->hOutSetup.is_loudspeaker_setup && nchan_transport > 1 ) + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_SHD; + hDirACRend->panningConf = DIRAC_PANNING_HOA3; + } + else + { + hDirACRend->synthesisConf = DIRAC_SYNTHESIS_GAIN_SHD; + hDirACRend->panningConf = DIRAC_PANNING_HOA3; + } + + if ( ( hDirACRend->frequency_axis = (float *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + set_f( hDirACRend->frequency_axis, 0.0f, hSpatParamRendCom->num_freq_bands ); + + ivas_dirac_dec_get_frequency_axis( hDirACRend->frequency_axis, output_Fs, hSpatParamRendCom->num_freq_bands ); + + if ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 && nchan_transport == 2 ) + { + if ( ( hDirACRend->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + ivas_masa_init_stereotype_detection( hDirACRend->masa_stereo_type_detect ); + } + else + { + hDirACRend->masa_stereo_type_detect = NULL; + } + + hSpatParamRendCom->numIsmDirections = 0; + + /*-----------------------------------------------------------------* + * (re)configure sub-modules + *-----------------------------------------------------------------*/ + + /* prototype signal computation */ + /* allocate output setup related arrays */ + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) + { + /* Directional and diffuses components in output LS format */ + hDirACRend->num_outputs_diff = nchan_out_woLFE; + hDirACRend->num_outputs_dir = nchan_out_woLFE; + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + /* Directional and diffuses components in SHD */ + /* Diffuseness components up to 1st order */ + hDirACRend->num_outputs_diff = ( min( hDirACRend->hOutSetup.ambisonics_order, 1 ) + 1 ) * ( min( hDirACRend->hOutSetup.ambisonics_order, 1 ) + 1 ); + hDirACRend->num_outputs_dir = ivas_sba_get_nchan( hDirACRend->hOutSetup.ambisonics_order, 0 ); + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + hDirACRend->num_outputs_diff = DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS; + hDirACRend->num_outputs_dir = nchan_out_woLFE; + } + else if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + hDirACRend->num_outputs_diff = 1; /* There is one output channel in mono */ + hDirACRend->num_outputs_dir = 2; /* Two channels are pre-rendered for stereo type detection */ + } + else + { + assert( 0 && "DirAC: not existing synthesis methods!" ); + } + + if ( ( hDirACRend->proto_index_dir = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirACRend->proto_index_diff = (int16_t *) malloc( sizeof( int16_t ) * hDirACRend->num_outputs_diff ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + set_s( hDirACRend->proto_index_dir, 0, hDirACRend->num_outputs_dir ); + set_s( hDirACRend->proto_index_diff, 0, hDirACRend->num_outputs_diff ); + + hDirACRend->sba_map_tc = sba_map_tc; + + if ( nchan_transport == 1 ) + { + hDirACRend->num_protos_ambi = 1; + hDirACRend->num_protos_dir = 1; + hDirACRend->num_protos_diff = 1; + } + else if ( nchan_transport == 2 ) + { + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + hDirACRend->num_protos_ambi = 2; + hDirACRend->num_protos_diff = 1; + hDirACRend->num_protos_dir = 2; + hDirACRend->proto_index_dir[1] = 1; + } + else if ( hDirACRend->hOutSetup.output_config == IVAS_AUDIO_CONFIG_MONO ) + { + /* Following the foa rendering for code compatibility */ + hDirACRend->num_protos_ambi = 2; + hDirACRend->num_protos_dir = 2; + hDirACRend->num_protos_diff = 3; + hDirACRend->proto_index_dir[0] = 0; + hDirACRend->proto_index_diff[0] = 0; + } + else + { + hDirACRend->num_protos_ambi = 2; + hDirACRend->num_protos_diff = 3; + + for ( k = 0; k < hDirACRend->num_outputs_diff; k++ ) + { + if ( ls_azimuth[k] > 0.0f ) + { + hDirACRend->proto_index_diff[k] = 1; + } + else if ( ls_azimuth[k] < 0.0f ) + { + hDirACRend->proto_index_diff[k] = 2; + } + else + { + hDirACRend->proto_index_diff[k] = 0; + } + } + + if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + { + hDirACRend->num_protos_dir = 3; + mvs2s( hDirACRend->proto_index_diff, hDirACRend->proto_index_dir, nchan_out_woLFE ); + } + else + { + hDirACRend->num_protos_dir = 2; + hDirACRend->proto_index_dir[1] = 1; + } + } + } + + /* direct/diffuse responses */ + if ( ( hDirACRend->diffuse_response_function = (float *) malloc( sizeof( float ) * hDirACRend->num_outputs_dir ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + if ( ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_LS ) || ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) || ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) ) + { + initDiffuseResponses( hDirACRend->diffuse_response_function, nchan_out_woLFE, hDirACRend->hOutSetup.output_config, + hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, MASA_FORMAT, &hDirACRend->num_ele_spk_no_diffuse_rendering, IVAS_AUDIO_CONFIG_INVALID ); + } + else + { + initDiffuseResponses( hDirACRend->diffuse_response_function, hDirACRend->num_outputs_dir, IVAS_AUDIO_CONFIG_FOA, + hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, MASA_FORMAT, &hDirACRend->num_ele_spk_no_diffuse_rendering, IVAS_AUDIO_CONFIG_INVALID ); + } + + hDirACRend->hoa_encoder = NULL; + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD ) + { + if ( ( hDirACRend->hoa_encoder = (float *) malloc( nchan_out_woLFE * hDirACRend->num_outputs_diff * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + + set_f( hDirACRend->hoa_encoder, 0.0f, nchan_out_woLFE * hDirACRend->num_outputs_diff ); + compute_hoa_encoder_mtx( ls_azimuth, ls_elevation, hDirACRend->hoa_encoder, hDirACRend->num_outputs_diff, hDirACRend->hOutSetup.ambisonics_order ); + } + + /* VBAP */ + inputMasa->hMasaExtRend->hVBAPdata = NULL; + + if ( hDirACRend->panningConf == DIRAC_PANNING_VBAP ) + { + if ( ( error = vbap_init_data( &( inputMasa->hMasaExtRend->hVBAPdata ), ls_azimuth, ls_elevation, nchan_out_woLFE, MASA_FORMAT ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* HOA panning/dec */ + hDirACRend->hoa_decoder = NULL; + if ( hDirACRend->panningConf == DIRAC_PANNING_HOA3 ) + { + if ( hDirACRend->hOutSetup.is_loudspeaker_setup ) + { + if ( ( error = ivas_sba_get_hoa_dec_matrix( hDirACRend->hOutSetup, &inputMasa->hMasaExtRend->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ) != IVAS_ERR_OK ) + { + return error; + } + + hDirACRend->hoa_decoder = inputMasa->hMasaExtRend->hoa_dec_mtx; + } + } + + /* decorrelation */ + hDirACRend->proto_signal_decorr_on = 1; + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_MONO ) + { + hDirACRend->proto_signal_decorr_on = 0; + } + + if ( hDirACRend->proto_signal_decorr_on ) + { + if ( ( error = ivas_dirac_dec_decorr_open( &( hDirACRend->h_freq_domain_decorr_ap_params ), + &( hDirACRend->h_freq_domain_decorr_ap_state ), + hSpatParamRendCom->num_freq_bands, + hDirACRend->num_outputs_diff, + hDirACRend->num_protos_diff, + hDirACRend->synthesisConf, + hDirACRend->frequency_axis, + nchan_transport, + output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* output synthesis */ + if ( ( ivas_dirac_dec_output_synthesis_open( hSpatParamRendCom, hDirACRend, RENDERER_DIRAC, nchan_transport, output_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + hDirACRend->h_output_synthesis_psd_params.use_onset_filters = hDirACRend->proto_signal_decorr_on; + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_PSD_SHD || hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + hDirACRend->h_output_synthesis_psd_params.use_onset_filters = 0; + } + + /*-----------------------------------------------------------------* + * memory allocation + *-----------------------------------------------------------------*/ + + if ( hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) + { + hDirACRend->proto_frame_f = NULL; + } + else + { + if ( ( hDirACRend->proto_frame_f = (float *) malloc( sizeof( float ) * 2 * hDirACRend->num_protos_diff * hSpatParamRendCom->num_freq_bands ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) ); + } + } + + + hDirACRend->buffer_energy = NULL; + + for ( i = 0; i < DIRAC_NUM_DIMS; i++ ) + { + for ( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ ) + { + hDirACRend->buffer_intensity_real[i][j] = NULL; + } + } + + /* output synthesis */ + ivas_dirac_dec_output_synthesis_init( hSpatParamRendCom, hDirACRend, nchan_out_woLFE, 0 ); + + /* Allocate stack memory */ + if ( ( error = ivas_dirac_alloc_mem( hDirACRend, RENDERER_DIRAC, hSpatParamRendCom->num_freq_bands, &( hDirACRend->stack_mem ), 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + inputMasa->hMasaExtRend->hDirACRend = hDirACRend; + + return error; +} + +static ivas_error ivas_masa_ext_rend_parambin_init( + input_masa *inputMasa /* i/o: MASA external renderer structure */ +) +{ + DIRAC_DEC_BIN_HANDLE hDiracDecBin; + HRTFS_PARAMBIN_HANDLE hHrtfParambin; + int16_t nBins; + int32_t output_Fs; + RENDERER_TYPE renderer_type; + int16_t j, k, bin; + float binCenterFreq, tmpFloat; + ivas_error error; + float frequency_axis[CLDFB_NO_CHANNELS_MAX]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; +#endif + + error = IVAS_ERR_OK; + + hHrtfParambin = inputMasa->hMasaExtRend->hHrtfParambin; + + /* Set common variables and defaults */ + output_Fs = *( inputMasa->base.ctx.pOutSampleRate ); + nBins = inputMasa->hMasaExtRend->hSpatParamRendCom->num_freq_bands; + renderer_type = inputMasa->hMasaExtRend->renderer_type; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( pos_idx = 0; pos_idx < inputMasa->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses; pos_idx++ ) + { + hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin[pos_idx]; +#else + hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin; +#endif + + /* Init assumes that no reconfiguration is required in external renderer. Instead, free and rebuild whole rendering. */ + 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; + hDiracDecBin->hDiffuseDist = NULL; /* Not used in external renderer */ + hDiracDecBin->useTdDecorr = 0; /* Always use frequency domain decorrelator in external renderer */ + + 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; + + for ( bin = 0; bin < nBins; bin++ ) + { + binCenterFreq = ( (float) bin + 0.5f ) / (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 ); + } + + /* No SPAR in external renderer so set directive diffuse field coherence tables to zero */ + set_zero( hDiracDecBin->diffuseFieldCoherenceX, BINAURAL_COHERENCE_DIFFERENCE_BINS ); + set_zero( hDiracDecBin->diffuseFieldCoherenceY, BINAURAL_COHERENCE_DIFFERENCE_BINS ); + set_zero( hDiracDecBin->diffuseFieldCoherenceZ, BINAURAL_COHERENCE_DIFFERENCE_BINS ); + + 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 ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */ +#else + if ( hDiracDecBin->hReverb == NULL ) +#endif + { + /* Todo Philips: Room acoustics should be passed here once the underlying part works. In this case, it probably should come from render context or somewhere else suitable. */ + if ( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, hHrtfParambin ) ) != IVAS_ERR_OK ) + { + 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 ); + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( pos_idx == 0 ) /* open decorrelator only for the main direction */ + { +#endif + /* Always open frequency domain decorrelator */ + 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; + } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif + /* External renderer uses constant regularization factor */ + hDiracDecBin->reqularizationFactor = 0.4f; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + inputMasa->hMasaExtRend->hDiracDecBin[pos_idx] = hDiracDecBin; + } +#else + inputMasa->hMasaExtRend->hDiracDecBin = hDiracDecBin; +#endif + + return error; +} + +static ivas_error initMasaExtRenderer( + input_masa *inputMasa, + const AUDIO_CONFIG outConfig ) +{ + int16_t i; + ivas_error error; + MASA_EXT_REND_HANDLE hMasaExtRend; + + error = IVAS_ERR_OK; + + if ( ( hMasaExtRend = (MASA_EXT_REND_HANDLE) malloc( sizeof( MASA_EXT_REND_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA external renderer structure\n" ) ); + } + + inputMasa->hMasaExtRend = hMasaExtRend; + + /* Default init */ + hMasaExtRend->renderer_type = RENDERER_DISABLE; + hMasaExtRend->hDirACRend = NULL; + hMasaExtRend->hSpatParamRendCom = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + hMasaExtRend->hDiracDecBin[i] = NULL; + } +#else + hMasaExtRend->hDiracDecBin = NULL; +#endif + hMasaExtRend->hReverb = NULL; + hMasaExtRend->hHrtfParambin = NULL; + hMasaExtRend->hVBAPdata = NULL; + hMasaExtRend->hoa_dec_mtx = NULL; + + if ( ( error = getAudioConfigNumChannels( inputMasa->base.inConfig, &hMasaExtRend->nchan_input ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = getAudioConfigNumChannels( outConfig, &hMasaExtRend->nchan_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + switch ( outConfig ) + { + case IVAS_AUDIO_CONFIG_MONO: + if ( inputMasa->base.inConfig == IVAS_AUDIO_CONFIG_MASA2 ) + { + hMasaExtRend->renderer_type = RENDERER_DIRAC; + } + else + { + /* 1TC MASA to mono does not need rendering. */ + hMasaExtRend->renderer_type = RENDERER_DISABLE; + } + break; + + case IVAS_AUDIO_CONFIG_STEREO: + hMasaExtRend->renderer_type = RENDERER_STEREO_PARAMETRIC; + break; + + case IVAS_AUDIO_CONFIG_5_1: + case IVAS_AUDIO_CONFIG_7_1: + case IVAS_AUDIO_CONFIG_5_1_2: + case IVAS_AUDIO_CONFIG_5_1_4: + case IVAS_AUDIO_CONFIG_7_1_4: + case IVAS_AUDIO_CONFIG_LS_CUSTOM: + case IVAS_AUDIO_CONFIG_FOA: + case IVAS_AUDIO_CONFIG_HOA2: + case IVAS_AUDIO_CONFIG_HOA3: + hMasaExtRend->renderer_type = RENDERER_DIRAC; + break; + + case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: +#endif + hMasaExtRend->renderer_type = RENDERER_BINAURAL_PARAMETRIC; + break; + + case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: + case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: + hMasaExtRend->renderer_type = RENDERER_BINAURAL_PARAMETRIC_ROOM; + break; + + default: + return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) ); + } + + if ( hMasaExtRend->renderer_type != RENDERER_DISABLE ) + { + int16_t subframe; + + if ( ( error = ivas_spat_hSpatParamRendCom_config( &hMasaExtRend->hSpatParamRendCom, DIRAC_OPEN, 0, MASA_FORMAT, MC_MODE_NONE, *( inputMasa->base.ctx.pOutSampleRate ), 0, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Simple population of the metadata index map as no adaptation is present */ + set_s( hMasaExtRend->hSpatParamRendCom->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME ); + for ( subframe = 0; subframe < MAX_PARAM_SPATIAL_SUBFRAMES; subframe++ ) + { + hMasaExtRend->hSpatParamRendCom->render_to_md_map[subframe] = subframe; + } + hMasaExtRend->hSpatParamRendCom->subframes_rendered = 0; + } + + if ( hMasaExtRend->renderer_type == RENDERER_DIRAC ) + { + if ( ( error = ivas_masa_ext_rend_dirac_rend_init( inputMasa ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC || hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || hMasaExtRend->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + if ( hMasaExtRend->renderer_type != RENDERER_STEREO_PARAMETRIC ) + { + if ( ( error = ivas_dirac_dec_binaural_copy_hrtfs( &inputMasa->hMasaExtRend->hHrtfParambin ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( ( error = ivas_masa_ext_rend_parambin_init( inputMasa ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Init CLDFB for analysis & synthesis if renderer is used. Otherwise, NULL. */ + for ( i = 0; i < MASA_MAX_TRANSPORT_CHANNELS; i++ ) + { + hMasaExtRend->cldfbAnaRend[i] = NULL; + } + + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + hMasaExtRend->cldfbSynRend[i] = NULL; + } + + if ( hMasaExtRend->renderer_type != RENDERER_DISABLE ) + { + for ( i = 0; i < hMasaExtRend->nchan_input; i++ ) + { + if ( ( error = openCldfb( &( hMasaExtRend->cldfbAnaRend[i] ), CLDFB_ANALYSIS, *inputMasa->base.ctx.pOutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + for ( i = 0; i < hMasaExtRend->nchan_output; i++ ) + { + if ( ( error = openCldfb( &( hMasaExtRend->cldfbSynRend[i] ), CLDFB_SYNTHESIS, *inputMasa->base.ctx.pOutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + inputMasa->hMasaExtRend = hMasaExtRend; + + return IVAS_ERR_OK; +} + + +static void freeMasaExtRenderer( + MASA_EXT_REND_HANDLE *hMasaExtRendOut ) +{ + MASA_EXT_REND_HANDLE hMasaExtRend; + int16_t i; + + if ( hMasaExtRendOut == NULL || *hMasaExtRendOut == NULL ) + { + return; + } + + hMasaExtRend = *hMasaExtRendOut; + + if ( hMasaExtRend->hDirACRend != NULL ) + { + ivas_dirac_rend_close( &hMasaExtRend->hDirACRend ); + } + + if ( hMasaExtRend->hSpatParamRendCom != NULL ) + { + ivas_spat_hSpatParamRendCom_close( &hMasaExtRend->hSpatParamRendCom ); + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + if ( hMasaExtRend->hDiracDecBin[i] != NULL ) + { + ivas_dirac_dec_close_binaural_data( &hMasaExtRend->hDiracDecBin[i] ); + } + } + +#else + if ( hMasaExtRend->hDiracDecBin != NULL ) + { + ivas_dirac_dec_close_binaural_data( &hMasaExtRend->hDiracDecBin ); + } +#endif + + if ( hMasaExtRend->hReverb != NULL ) + { + ivas_binaural_reverb_close( &hMasaExtRend->hReverb ); + } + + if ( hMasaExtRend->hHrtfParambin != NULL ) + { + ivas_HRTF_parambin_binary_close( &hMasaExtRend->hHrtfParambin ); + } + + if ( hMasaExtRend->hVBAPdata != NULL ) + { + vbap_free_data( &hMasaExtRend->hVBAPdata ); + } + + if ( hMasaExtRend->hoa_dec_mtx != NULL ) + { + free( hMasaExtRend->hoa_dec_mtx ); + } + + for ( i = 0; i < MASA_MAX_TRANSPORT_CHANNELS; i++ ) + { + if ( hMasaExtRend->cldfbAnaRend[i] != NULL ) + { + deleteCldfb( &hMasaExtRend->cldfbAnaRend[i] ); + } + } + + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + if ( hMasaExtRend->cldfbSynRend[i] != NULL ) + { + deleteCldfb( &hMasaExtRend->cldfbSynRend[i] ); + } + } + + free( hMasaExtRend ); + *hMasaExtRendOut = NULL; + + return; +} +#endif