diff --git a/apps/decoder.c b/apps/decoder.c index 163661f195be4fe69ece86a507908978fec0efac..0bb428c4974c3501e2636f36efd5062e2f38f2e3 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -51,6 +51,11 @@ #include "wmc_auto.h" #include "options.h" #include "stl.h" +#ifdef OBJ_EDITING_API +#ifdef OBJ_EDITING_EXAMPLE +#include +#endif +#endif #define WMC_TOOL_SKIP @@ -135,6 +140,9 @@ typedef struct AcousticEnvironmentSequence aeSequence; bool dpidEnabled; uint16_t directivityPatternId[IVAS_MAX_NUM_OBJECTS]; +#ifdef OBJ_EDITING_EXAMPLE + bool objEditEnabled; +#endif } DecArguments; @@ -859,6 +867,9 @@ static bool parseCmdlIVAS_dec( { arg->directivityPatternId[i] = 65535; } +#ifdef OBJ_EDITING_EXAMPLE + arg->objEditEnabled = false; +#endif /*-----------------------------------------------------------------* * Initialization @@ -1310,6 +1321,13 @@ static bool parseCmdlIVAS_dec( i += tmp; } +#ifdef OBJ_EDITING_EXAMPLE + else if ( strcmp( argv_to_upper, "-OBJ_EDIT" ) == 0 ) + { + arg->objEditEnabled = true; + i++; + } +#endif /*-----------------------------------------------------------------* * Option not recognized @@ -1846,6 +1864,11 @@ static ivas_error decodeG192( int16_t isSplitRend, isSplitCoded; IVAS_RENDER_CONFIG_DATA renderConfig; RenderConfigReader *renderConfigReader = NULL; +#ifdef OBJ_EDITING_API +#ifdef OBJ_EDITING_EXAMPLE + IVAS_EDITABLE_PARAMETERS editableParameters; +#endif +#endif if ( ( error = IVAS_DEC_is_split_rendering_enabled( hIvasDec, &isSplitRend ) ) != IVAS_ERR_OK ) { @@ -2120,6 +2143,65 @@ static ivas_error decodeG192( } #ifdef OBJ_EDITING_API +#ifdef OBJ_EDITING_EXAMPLE + if ( arg.objEditEnabled ) + { + + /* Do object info editing here */ + /* get object parameters */ + if ( ( error = IVAS_DEC_GetEditableParameters( hIvasDec, &editableParameters ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: could not get the editable parameters: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + /* edit object parameters...*/ + + /* put the objects equally spaced at the horizontal plane */ + /* and play a little bit with the gains... */ + Word16 obj_idx, non_diegetic_obj_idx; + Word16 num_nondiegetic_objects; + + num_nondiegetic_objects = 0; + for ( obj_idx = 0; obj_idx < editableParameters.num_obj; obj_idx++ ) + { + if ( !editableParameters.ism_metadata[obj_idx].non_diegetic_flag ) + { + num_nondiegetic_objects++; + } + } + if ( num_nondiegetic_objects ) + { + float start_angle, angle_inc; + angle_inc = 360.0f / (float) num_nondiegetic_objects; + start_angle = angle_inc / 2.0f; + for ( obj_idx = 0, non_diegetic_obj_idx = 0; obj_idx < editableParameters.num_obj; obj_idx++ ) + { + if ( !editableParameters.ism_metadata[obj_idx].non_diegetic_flag ) + { + editableParameters.ism_metadata[obj_idx].elevation_fx = 0; + editableParameters.ism_metadata[obj_idx].azimuth_fx = (Word32) ( ( start_angle + (float) non_diegetic_obj_idx * angle_inc ) * powf( 2.0f, 22.0f ) ); + non_diegetic_obj_idx++; + } + } + } + + /* breakover object gains */ + for ( obj_idx = 0; obj_idx < editableParameters.num_obj; obj_idx++ ) + { + editableParameters.ism_metadata[obj_idx].gain_fx = (Word32) ( ( 0.5f + (float) ( ( frame + obj_idx * 50 ) % 250 ) / 250.0f ) * powf( 2.0f, 29.0f ) ); + } + + editableParameters.gain_bed_fx = ( 1 << 28 ); // 0.5 in Q29 + + /* set new object parameters*/ + if ( ( error = IVAS_DEC_SetEditableParameters( hIvasDec, editableParameters ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError: could not set the editable parameters: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + } +#endif /* Do the final preparations needed for rendering */ if ( ( error = IVAS_DEC_PrepareRenderer( hIvasDec ) ) != IVAS_ERR_OK ) { diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 8ef02aeed50d3694dd2967ace1af31f503084dcd..bb0f9244530b3744bd2fe24cfde2b10dc6a85b9b 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -126,7 +126,7 @@ typedef struct _IVAS_ISM_METADATA Word32 elevation_fx; /* Q22 */ Word16 radius_fx; /* Q9 */ Word32 spread_fx; /* Q22 */ - Word32 gainFactor_fx; /* Q31 */ + Word32 gainFactor_fx; /* Q29 */ Word32 yaw_fx; /* Q22 */ Word32 pitch_fx; /* Q22 */ float azimuth; @@ -138,7 +138,7 @@ typedef struct _IVAS_ISM_METADATA float pitch; Word16 non_diegetic_flag; #ifdef OBJ_EDITING_API - Word32 gain_fx; + Word32 gain_fx; // Q29 #endif } IVAS_ISM_METADATA; @@ -148,7 +148,7 @@ typedef struct _IVAS_EDITABLE_PARAMETERS { Word16 num_obj; IVAS_ISM_METADATA ism_metadata[IVAS_MAX_NUM_OBJECTS]; - Word32 gain_bed_fx; + Word32 gain_bed_fx; // Q29 } IVAS_EDITABLE_PARAMETERS; #endif diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 4e5f8871cfed61375177e1647afc3c7444647d92..6c68005315eae3430a52e738f4b616e8787a6dc4 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1256,10 +1256,15 @@ enum #define MASA_MAXIMUM_TWO_DIR_BANDS 24 #define NBITS_HR_COH 4 #define OMASA_TDREND_MATCHING_GAIN_FX 26026 +//TODO: insert proper Q representations +#ifdef OMASA_OBJECT_EDITING +#define OMASA_GAIN_EDIT_THR_FX 246 /* OMASA gain change threshold, 0.06f in Q12 */ +#define OMASA_AZI_EDIT_THR_FX ONE_IN_Q22 /* OMASA-DISC azimuth change threshold, 1.0f in Q22 */ +#define OMASA_ELE_EDIT_THR_FX ONE_IN_Q23 /* OMASA-DISC elevation change threshold, 2.0f in Q22 */ +#endif #define MASA_INV_ANGLE_AT_EQUATOR_DEG_Q30 1453366656l /* 1.353553128183453f in Q30 */ - #define MASA_JBM_RINGBUFFER_FRAMES 3 #define TOLERANCE_360_Q22 1510033326 /* 360 in Q22 + 0.02 in Q22*/ #define MINUS_TOLERANCE_360_Q22 -1510033326 /* - (360 in Q22 + 0.02 in Q22) */ diff --git a/lib_com/ivas_ism_com_fx.c b/lib_com/ivas_ism_com_fx.c index 30cd2f29e095ddb08699ac2b5a0e5ca2de9fccbc..8514fb9c20301a10076b50b3e35bd31faf779c0f 100644 --- a/lib_com/ivas_ism_com_fx.c +++ b/lib_com/ivas_ism_com_fx.c @@ -471,13 +471,13 @@ void ivas_ism_reset_metadata( move16(); #ifdef OBJ_EDITING_API - hIsmMeta->edited_gain_fx = ONE_IN_Q31; + hIsmMeta->edited_gain_fx = ONE_IN_Q29; hIsmMeta->edited_azimuth_fx = 0; hIsmMeta->edited_elevation_fx = 0; hIsmMeta->edited_pitch_fx = 0; hIsmMeta->edited_yaw_fx = 0; hIsmMeta->edited_radius_fx = ONE_IN_Q9; - hIsmMeta->gain_fx = ONE_IN_Q31; + hIsmMeta->gain_fx = ONE_IN_Q29; hIsmMeta->non_diegetic_flag = 0; #endif diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 3f4da4484417cd078ce823528d30fe4593519739..bc88119669d5f0d05641cfc55864d737d173dd5c 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -3956,16 +3956,20 @@ void ivas_set_ism_importance_interformat_fx( const Word16 lp_noise_CPE_fx, /* i : LP filtered total noise estimation */ Word16 ism_imp[] /* o : ISM importance flags */ ); - +#ifdef OMASA_OBJECT_EDITING +void ivas_omasa_preProcessStereoTransportsForEditedObjects_fx( +#else void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( +#endif Decoder_Struct *st_ivas, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ Word16 *cldfb_buf_q, const Word16 nBins, - const Word16 subframe + const Word16 subframe ); + void ivas_omasa_decode_masa_to_total_fx( UWord16 *bit_stream, Word16 *index, diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 3c24b682315d2f2f108f56482978e7c6a0efcccf..5072e385f79bdc52d1785322daae59dde072cfa3 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -294,6 +294,9 @@ extern const Word32 diffuseness_thresholds_hr_fx[HR_MASA_ER_LEVELS + 1]; extern const Word32 no_phi_masa_inv_fx[NO_SPHERICAL_GRIDS][MAX_NO_THETA]; extern const Word32 azimuth_cb_fx[8]; extern const Word32 delta_theta_masa_fx[NO_SPHERICAL_GRIDS - 2]; +#ifdef OBJ_EDIT_BASOP +extern const Word32 delta_theta_masa_inv_fx[NO_SPHERICAL_GRIDS - 2]; +#endif extern const Word16 coherence_cb0_masa_Q14[DIRAC_DIFFUSE_LEVELS * 2 * MASA_NO_CV_COH]; extern const Word32 coherence_cb0_masa_fx[DIRAC_DIFFUSE_LEVELS * 2 * MASA_NO_CV_COH]; extern const Word16 coherence_cb1_masa_Q15[MASA_NO_CV_COH1 * MASA_MAXIMUM_CODING_SUBBANDS]; /* 25 */ diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index 395a3c08f49c990f899bcab877a20a60ff2f5bf6..4b14f6d5acaa16e1b3e765a0169d67a7e0659e50 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -4406,6 +4406,13 @@ const Word32 delta_theta_masa_fx[NO_SPHERICAL_GRIDS - 2] = { 188743680, 188743680, 150994944, 106954752, 83886080, 62914560, 45214596, 28101836, 20971520 }; +#ifdef OBJ_EDIT_BASOP +// Q31 +const Word32 delta_theta_masa_inv_fx[NO_SPHERICAL_GRIDS - 2] = { + 47721859, 47721859, 59652324, 84215045, 107374182, 143165577, 199209986, 320519947, 429496730 +}; +#endif + // q = 14 const Word16 coherence_cb0_masa_Q14[DIRAC_DIFFUSE_LEVELS * 2 * MASA_NO_CV_COH] = { 783, 4173, 9036, 16163, 22238, 27587, 32234, 0, diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 1f7ea778d06534d594480c2be3ad04c0278fed6d..db2c6ca695b953398933f156ceb0294310dff352 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -66,7 +66,7 @@ typedef struct Word32 pitch_fx; /* pitch value read from the input metadata file */ /* Q22 */ #ifdef OBJ_EDITING_API - Word32 gain_fx; /* Q31 */ + Word32 gain_fx; /* Q29 */ Word32 edited_azimuth_fx; /* Q22 */ Word32 edited_elevation_fx; /* Q22 */ @@ -74,7 +74,7 @@ typedef struct Word32 edited_yaw_fx; /* Q22 */ Word32 edited_pitch_fx; /* Q22 */ - Word32 edited_gain_fx; /* Q31 */ + Word32 edited_gain_fx; /* Q29 */ #endif Word16 non_diegetic_flag; /* Non-diegetic (non-headtracked) object flag */ diff --git a/lib_com/options.h b/lib_com/options.h index 8dd94bcd6ab7c4a6d186e5b7670be0ea46f8ab30..a43f4053df65dd7d350fa0f34d88c6200da80c0b 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -119,11 +119,20 @@ #define FIX_1288_SPLIT_REND_XSAN /* Dlb: Fix asan, msan and usan issues in split rendering mode*/ // object-editing feature porting +#define OBJ_EDITING_INTERFACE /* Interface for object editing */ #define OBJ_EDITING_API /* object editing changes related to the API */ #ifdef OBJ_EDITING_API #define TMP_FIX_SPLIT_REND // temporary fix to split-rendering (it follows the later state of the framework but it is needed now because of current test-conditions) #define TMP_FIX_OMASA_SR_BE // temporary fix to keep OMASA split-rendering BE +#define OBJ_EDITING_EXAMPLE /* obj editing example code in decoder.c */ +#define OMASA_OBJECT_EDITING /* Nokia: object editing interface for OMASA */ +#ifdef OMASA_OBJECT_EDITING +#define NONBE_1399_1400_FIX_OBJ_EDIT_ISSUES // Nokia: Fix 1399_1400 issue in float, this is essential for the BASOP porting #endif +#define OBJ_EDITING_PARAMISM_BIN /* Nokia: object editing for ParamISM to binaural */ +#define OBJ_EDIT_BASOP +#endif + /* #################### End BASOP porting switches ############################ */ diff --git a/lib_dec/ivas_dirac_dec_fx.c b/lib_dec/ivas_dirac_dec_fx.c index f252f760cddeb0be80ade8389b475c164796e93b..1c20d23a8c66c89ca0db413ec8f61746db8d2796 100644 --- a/lib_dec/ivas_dirac_dec_fx.c +++ b/lib_dec/ivas_dirac_dec_fx.c @@ -2807,6 +2807,16 @@ void ivas_dirac_dec_render_sf_fx( move16(); } +#ifdef OMASA_OBJECT_EDITING + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { +#ifdef FIX_1319_STACK_SBA_DECODER + ivas_omasa_preProcessStereoTransportsForEditedObjects_fx( st_ivas, Cldfb_RealBuffer_Binaural_fx[0], Cldfb_ImagBuffer_Binaural_fx[0], &cldfb_buf_q, hSpatParamRendCom->num_freq_bands, subframe_idx ); +#else + ivas_omasa_preProcessStereoTransportsForEditedObjects_fx( st_ivas, Cldfb_RealBuffer_Temp_fx, Cldfb_ImagBuffer_Temp_fx, &cldfb_buf_q, hSpatParamRendCom->num_freq_bands, subframe_idx ); +#endif + } +#else test(); IF( ( NE_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) ) { @@ -2816,6 +2826,7 @@ void ivas_dirac_dec_render_sf_fx( ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( st_ivas, Cldfb_RealBuffer_Temp_fx, Cldfb_ImagBuffer_Temp_fx, &cldfb_buf_q, hSpatParamRendCom->num_freq_bands, subframe_idx ); #endif } +#endif } FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) @@ -3767,8 +3778,12 @@ void ivas_dirac_dec_render_sf_fx( const Word32 ele_fx = L_shl( el1_32, Q22 - Q16 ); // Q16 -> Q22 efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], azi_fx, ele_fx, EFAP_MODE_EFAP ); #ifdef OBJ_EDITING_API - // TODO: Enable gain editing feature - // v_multc_fixed( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], nchan_out_woLFE ); // Q30, Q30 --> Q30 + // TODO: Align Q-values + IF( NE_32( st_ivas->hIsmMetaData[i]->edited_gain_fx, ONE_IN_Q29 ) ) + { + v_multc_fx( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], nchan_out_woLFE ); // Q30, Q29 --> Q28 + Scale_sig32( st_ivas->hIsmRendererData->gains_fx[i], nchan_out_woLFE, Q2 ); // Q28 --> Q30 + } #endif } } diff --git a/lib_dec/ivas_init_dec_fx.c b/lib_dec/ivas_init_dec_fx.c index 0944f3d7d32768fac5987b818be2d17490f98a4f..4a21cada16efc8eba68a73ffafd2c8df13cb1156 100644 --- a/lib_dec/ivas_init_dec_fx.c +++ b/lib_dec/ivas_init_dec_fx.c @@ -1786,6 +1786,16 @@ ivas_error ivas_init_decoder_fx( { st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed2 = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->seed3; move16(); +#ifdef OBJ_EDITING_PARAMISM_BIN + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + /* reusing OMASA function for allocating and initializing MASA_ISM rendering handle (even though not in OMASA) */ + IF( NE_32( ( error = ivas_omasa_data_open_fx( st_ivas ) ), IVAS_ERR_OK ) ) + { + return error; + } + } +#endif } ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_DISC ) ) { @@ -2150,13 +2160,15 @@ ivas_error ivas_init_decoder_fx( } reset_indices_dec( st_ivas->hSCE[0]->hCoreCoder[0] ); - +#ifndef OMASA_OBJECT_EDITING IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) { +#endif if ( ( error = ivas_ism_metadata_dec_create_fx( st_ivas, st_ivas->nchan_ism, NULL ) ) != IVAS_ERR_OK ) { return error; } +#ifndef OMASA_OBJECT_EDITING } else { @@ -2165,6 +2177,7 @@ ivas_error ivas_init_decoder_fx( return error; } } +#endif } ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) { diff --git a/lib_dec/ivas_ism_dec_fx.c b/lib_dec/ivas_ism_dec_fx.c index 1e0147398f42bfc0dff8b97fc71418f63a16363f..e5e05ab0a7382e74370a9733471420a3b214f923 100644 --- a/lib_dec/ivas_ism_dec_fx.c +++ b/lib_dec/ivas_ism_dec_fx.c @@ -189,6 +189,10 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( { /* close the parametric binaural renderer */ ivas_dirac_dec_close_binaural_data_fx( st_ivas->hDiracDecBin ); +#ifdef OBJ_EDITING_PARAMISM_BIN + /* Close omasa data struct (used for object editing) */ + ivas_omasa_data_close_fx( &st_ivas->hMasaIsmData ); +#endif /* Open the TD Binaural renderer */ test(); @@ -224,6 +228,12 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( /* close the parametric binaural renderer */ ivas_dirac_dec_close_binaural_data_fx( st_ivas->hDiracDecBin ); + +#ifdef OBJ_EDITING_PARAMISM_BIN + /* Close omasa data struct (used for object editing) */ + ivas_omasa_data_close_fx( &st_ivas->hMasaIsmData ); +#endif + /* Open Crend Binaural renderer */ IF( NE_32( ( error = ivas_rend_openCrend_fx( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hRenderConfig, st_ivas->hHrtfCrend, st_ivas->hHrtfStatistics, st_ivas->hDecoderConfig->output_Fs, 0, ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ) ), IVAS_ERR_OK ) ) @@ -255,6 +265,13 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( { return error; } +#ifdef OBJ_EDITING_PARAMISM_BIN + /* Open omasa data struct (used for object editing) */ + IF( ( error = ivas_omasa_data_open_fx( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif /* Close the TD Binaural renderer */ ivas_td_binaural_close_fx( &st_ivas->hBinRendererTd ); @@ -283,6 +300,13 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( return error; } +#ifdef OBJ_EDITING_PARAMISM_BIN + /* Open omasa data struct (used for object editing) */ + IF( ( error = ivas_omasa_data_open_fx( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif /* close the crend binaural renderer */ ivas_rend_closeCrend_fx( &( st_ivas->hCrendWrapper ) ); } diff --git a/lib_dec/ivas_ism_param_dec_fx.c b/lib_dec/ivas_ism_param_dec_fx.c index 89d4f101d62cd19842893e9be4691a43f9b464b7..7e25eeb0951bdaf889d340ff1dc6f7809805d635 100644 --- a/lib_dec/ivas_ism_param_dec_fx.c +++ b/lib_dec/ivas_ism_param_dec_fx.c @@ -1000,8 +1000,13 @@ void ivas_ism_dec_digest_tc_fx( move32(); st_ivas->hIsmRendererData->gains_fx[i][1] = L_shr( L_deposit_h( gains_fx[1] ), 1 ); // Q31 -> Q30 move32(); - // TODO: Enable gain editing feature - // v_multc_fixed( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], CPE_CHANNELS ); // Q30, Q30 --> Q30 + // TODO: Align Q values + IF( NE_32( st_ivas->hIsmMetaData[i]->edited_gain_fx, ONE_IN_Q29 ) ) + { + v_multc_fx( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], CPE_CHANNELS ); // Q30, Q29 --> Q28 + Scale_sig32( st_ivas->hIsmRendererData->gains_fx[i], CPE_CHANNELS, Q2 ); // Q28 --> Q30 + } + #else Word16 gains_fx[2]; ivas_ism_get_stereo_gains_fx( (Word16) L_shr( st_ivas->hIsmMetaData[i]->azimuth_fx, 22 ), (Word16) L_shr( st_ivas->hIsmMetaData[i]->elevation_fx, 22 ), &gains_fx[0], &gains_fx[1] ); @@ -1049,8 +1054,12 @@ void ivas_ism_dec_digest_tc_fx( elevation_fx = L_shl( elevation_fx, Q22 ); // Q22 efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); #ifdef OBJ_EDITING_API - // TODO: Enable gain editing feature - // v_multc_fixed( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hEFAPdata->numSpk ); + // TODO: align Q values properly + IF( NE_32( st_ivas->hIsmMetaData[i]->edited_gain_fx, ONE_IN_Q29 ) ) + { + v_multc_fx( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hEFAPdata->numSpk ); // Q30, Q29 --> Q28 + Scale_sig32( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hEFAPdata->numSpk, Q2 ); // Q28 --> Q30 + } #endif } } @@ -1063,8 +1072,12 @@ void ivas_ism_dec_digest_tc_fx( Word16 ele = shr( extract_h( st_ivas->hIsmMetaData[i]->elevation_fx ), 22 - 16 ); // Q0 ivas_dirac_dec_get_response_fx( azi, ele, st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIntSetup.ambisonics_order, Q30 ); #ifdef OBJ_EDITING_API - // TODO: Enable gain editing feature - // v_multc_fixed( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], ivas_sba_get_nchan_fx( st_ivas->hIntSetup.ambisonics_order, 0 ) ); // Q30, Q30 --> Q30 + // TODO: Align Q-values + IF( NE_32( st_ivas->hIsmMetaData[i]->edited_gain_fx, ONE_IN_Q29 ) ) + { + v_multc_fx( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], ivas_sba_get_nchan_fx( st_ivas->hIntSetup.ambisonics_order, 0 ) ); // Q30, Q29 --> Q28 + Scale_sig32( st_ivas->hIsmRendererData->gains_fx[i], ivas_sba_get_nchan_fx( st_ivas->hIntSetup.ambisonics_order, 0 ), Q2 ); // Q28 --> 30 + } #endif } } @@ -1998,13 +2011,23 @@ void ivas_param_ism_params_to_masa_param_mapping_fx( Word16 azimuth[2]; Word16 elevation[2]; Word16 power_ratio_fx[2]; /* Q15 */ +#ifdef OBJ_EDITING_PARAMISM_BIN + MASA_ISM_DATA_HANDLE hMasaIsmData; + Word16 obj; + Word16 obj_idx; +#endif #ifndef OBJ_EDITING_API Word32 ivas_total_brate; #endif hParamIsmDec = st_ivas->hParamIsmDec; + move16(); hSpatParamRendCom = st_ivas->hSpatParamRendCom; + move16(); +#ifdef OBJ_EDITING_PARAMISM_BIN + hMasaIsmData = st_ivas->hMasaIsmData; +#endif nBins = hSpatParamRendCom->num_freq_bands; move16(); #ifndef OBJ_EDITING_API @@ -2026,138 +2049,150 @@ void ivas_param_ism_params_to_masa_param_mapping_fx( } #endif - IF( GT_16( st_ivas->nchan_ism, 1 ) ) + + IF( st_ivas->hISMDTX.dtx_flag ) { - IF( st_ivas->hISMDTX.dtx_flag ) - { - Word32 energy_ratio_fx; /* Q30 */ - energy_ratio_fx = L_mult0( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx, st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx ); /* Q15 + Q15 -> Q30 */ + Word32 energy_ratio_fx; /* Q30 */ + energy_ratio_fx = L_mult0( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx, st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->coherence_fx ); /* Q15 + Q15 -> Q30 */ - hSpatParamRendCom->numSimultaneousDirections = 1; - move16(); - azimuth[0] = extract_l( L_shr( L_add( hParamIsmDec->azimuth_values_fx[0], ONE_IN_Q21 ), 22 ) ); // Q0 - move16(); - elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[0], ONE_IN_Q21 ), 22 ) ); // Q0 - move16(); + hSpatParamRendCom->numSimultaneousDirections = 1; + move16(); + azimuth[0] = extract_l( L_shr( L_add( hParamIsmDec->azimuth_values_fx[0], ONE_IN_Q21 ), 22 ) ); // Q0 + move16(); + elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[0], ONE_IN_Q21 ), 22 ) ); // Q0 + move16(); - FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + FOR( bin_idx = 0; bin_idx < nBins; bin_idx++ ) { - FOR( bin_idx = 0; bin_idx < nBins; bin_idx++ ) - { - hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; - move16(); - hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; - move16(); - hSpatParamRendCom->energy_ratio1_fx[sf_idx][bin_idx] = energy_ratio_fx; - move16(); - hSpatParamRendCom->spreadCoherence_fx[sf_idx][bin_idx] = 0; - move16(); - hSpatParamRendCom->surroundingCoherence_fx[sf_idx][bin_idx] = 0; - move16(); - } + hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; + move16(); + hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; + move16(); + hSpatParamRendCom->energy_ratio1_fx[sf_idx][bin_idx] = energy_ratio_fx; + move16(); + hSpatParamRendCom->spreadCoherence_fx[sf_idx][bin_idx] = 0; + move16(); + hSpatParamRendCom->surroundingCoherence_fx[sf_idx][bin_idx] = 0; + move16(); } } - ELSE + } + ELSE + { + hSpatParamRendCom->numSimultaneousDirections = 2; + move16(); + FOR( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ ) { - hSpatParamRendCom->numSimultaneousDirections = 2; + brange[0] = hParamIsmDec->hParamIsm->band_grouping[band_idx]; move16(); - FOR( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ ) - { - brange[0] = hParamIsmDec->hParamIsm->band_grouping[band_idx]; - move16(); #ifdef OBJ_EDITING_API - brange[1] = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1]; - move16(); + brange[1] = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1]; + move16(); - azimuth[0] = extract_l( L_shr( L_add( hParamIsmDec->edited_azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); - elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->edited_elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); + azimuth[0] = extract_l( L_shr( L_add( hParamIsmDec->edited_azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); + elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->edited_elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); #else - brange[1] = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1]; - move16(); + brange[1] = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1]; + move16(); - azimuth[0] = extract_l( L_shr( L_add( hParamIsmDec->azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); - elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); + azimuth[0] = extract_l( L_shr( L_add( hParamIsmDec->azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); + elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); #endif - power_ratio_fx[0] = hParamIsmDec->power_ratios_fx[band_idx][0][0]; - move16(); + power_ratio_fx[0] = hParamIsmDec->power_ratios_fx[band_idx][0][0]; + move16(); #ifdef OBJ_EDITING_API - azimuth[1] = extract_l( L_shr( L_add( hParamIsmDec->edited_azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); - elevation[1] = extract_l( L_shr( L_add( hParamIsmDec->edited_elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); + azimuth[1] = extract_l( L_shr( L_add( hParamIsmDec->edited_azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); + elevation[1] = extract_l( L_shr( L_add( hParamIsmDec->edited_elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); #else - azimuth[1] = extract_l( L_shr( L_add( hParamIsmDec->azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); - elevation[1] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); + azimuth[1] = extract_l( L_shr( L_add( hParamIsmDec->azimuth_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); + elevation[1] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]], ( 1 << 21 ) ), 22 ) ); // Q0 + move16(); #endif - power_ratio_fx[1] = hParamIsmDec->power_ratios_fx[band_idx][0][1]; - move16(); - - FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) - { - FOR( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) - { - hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; - move16(); - hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; - move16(); - hSpatParamRendCom->energy_ratio1_fx[sf_idx][bin_idx] = L_shl( power_ratio_fx[0], Q15 ); // Q30 - move32(); - hSpatParamRendCom->azimuth2[sf_idx][bin_idx] = azimuth[1]; - move16(); - hSpatParamRendCom->elevation2[sf_idx][bin_idx] = elevation[1]; - move16(); - hSpatParamRendCom->energy_ratio2_fx[sf_idx][bin_idx] = L_shl( power_ratio_fx[1], Q15 ); // Q30 - move32(); - } - } - } + power_ratio_fx[1] = hParamIsmDec->power_ratios_fx[band_idx][0][1]; + move16(); FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) { - FOR( bin_idx = 0; bin_idx < nBins; bin_idx++ ) + FOR( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) { - hSpatParamRendCom->spreadCoherence_fx[sf_idx][bin_idx] = 0; + hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; move16(); - hSpatParamRendCom->spreadCoherence2_fx[sf_idx][bin_idx] = 0; + hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; + move16(); + hSpatParamRendCom->energy_ratio1_fx[sf_idx][bin_idx] = L_shl( power_ratio_fx[0], Q15 ); // Q30 + move32(); + hSpatParamRendCom->azimuth2[sf_idx][bin_idx] = azimuth[1]; move16(); - hSpatParamRendCom->surroundingCoherence_fx[sf_idx][bin_idx] = 0; + hSpatParamRendCom->elevation2[sf_idx][bin_idx] = elevation[1]; move16(); + hSpatParamRendCom->energy_ratio2_fx[sf_idx][bin_idx] = L_shl( power_ratio_fx[1], Q15 ); // Q30 + move32(); } } } - } - ELSE - { - hSpatParamRendCom->numSimultaneousDirections = 1; - move16(); - azimuth[0] = extract_l( L_shr( ( L_add( hParamIsmDec->azimuth_values_fx[0], ( 1 << 21 ) ) ), 22 ) ); // Q0 - move16(); - elevation[0] = extract_l( L_shr( L_add( hParamIsmDec->elevation_values_fx[0], ( 1 << 21 ) ), 22 ) ); // Q0 - move16(); FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) { FOR( bin_idx = 0; bin_idx < nBins; bin_idx++ ) { - hSpatParamRendCom->azimuth[sf_idx][bin_idx] = azimuth[0]; - move16(); - hSpatParamRendCom->elevation[sf_idx][bin_idx] = elevation[0]; - move16(); - hSpatParamRendCom->energy_ratio1_fx[sf_idx][bin_idx] = ONE_IN_Q30; /* 1.0f in Q30 */ - move32(); hSpatParamRendCom->spreadCoherence_fx[sf_idx][bin_idx] = 0; move16(); + hSpatParamRendCom->spreadCoherence2_fx[sf_idx][bin_idx] = 0; + move16(); hSpatParamRendCom->surroundingCoherence_fx[sf_idx][bin_idx] = 0; move16(); } } + +#ifdef OBJ_EDITING_PARAMISM_BIN + FOR( obj = 0; obj < st_ivas->nchan_ism; obj++ ) + { + FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + hMasaIsmData->azimuth_ism_fx[obj][sf_idx] = extract_l( L_shr( ( L_add( hParamIsmDec->azimuth_values_fx[obj], ( 1 << 21 ) ) ), 22 ) ); // Q0 + hMasaIsmData->elevation_ism_fx[obj][sf_idx] = extract_l( L_shr_r( L_add( hParamIsmDec->elevation_values_fx[obj], ( 1 << 21 ) ), 22 ) ); // Scale to Q0 + } + + hMasaIsmData->azimuth_ism_edited_fx[obj] = extract_l( L_shr( ( L_add( hParamIsmDec->edited_azimuth_values_fx[obj], ( 1 << 21 ) ) ), 22 ) ); + hMasaIsmData->elevation_ism_edited_fx[obj] = extract_l( L_shr( ( L_add( hParamIsmDec->edited_azimuth_values_fx[obj], ( 1 << 21 ) ) ), 22 ) ); + + FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + set_zero_fx( hMasaIsmData->energy_ratio_ism_fx[obj][sf_idx], CLDFB_NO_CHANNELS_MAX ); + } + } + + FOR( obj = 0; obj < MAX_PARAM_ISM_WAVE; obj++ ) + { + FOR( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ ) + { + brange[0] = hParamIsmDec->hParamIsm->band_grouping[band_idx]; + brange[1] = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1]; + + obj_idx = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][obj]; + power_ratio_fx[obj] = hParamIsmDec->power_ratios_fx[band_idx][0][obj]; // Q15 + + FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + FOR( bin_idx = brange[0]; bin_idx < brange[1]; bin_idx++ ) + { + hMasaIsmData->energy_ratio_ism_fx[obj_idx][sf_idx][bin_idx] = L_shl( power_ratio_fx[obj], 15 ); // Q15 -> Q30 + } + } + } + } +#endif } + return; } diff --git a/lib_dec/ivas_ism_renderer_fx.c b/lib_dec/ivas_ism_renderer_fx.c index 97b5b05c3ebe18337ec5c44f76703a59bbdb05b8..e9edd161cd574ec9cd23455dd4fa0c3b986dd72a 100644 --- a/lib_dec/ivas_ism_renderer_fx.c +++ b/lib_dec/ivas_ism_renderer_fx.c @@ -279,8 +279,12 @@ void ivas_ism_render_sf_fx( { efap_determine_gains_fx( st_ivas->hEFAPdata, st_ivas->hIsmRendererData->gains_fx[i], L_shl( azimuth, 22 ), L_shl( elevation, 22 ), EFAP_MODE_EFAP ); #ifdef OBJ_EDITING_API - // TODO: Enable gain editing feature - // v_multc_fixed( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], nchan_out_woLFE ); // Q30, Q30 --> Q30 + // TODO: Align Q-values + IF( NE_32( st_ivas->hIsmMetaData[i]->edited_gain_fx, ONE_IN_Q29 ) ) + { + v_multc_fx( st_ivas->hIsmRendererData->gains_fx[i], st_ivas->hIsmMetaData[i]->edited_gain_fx, st_ivas->hIsmRendererData->gains_fx[i], nchan_out_woLFE ); // Q30, Q29 --> Q28 + Scale_sig32( st_ivas->hIsmRendererData->gains_fx[i], nchan_out_woLFE, Q2 ); // Q28 --> Q30 + } #endif } } @@ -624,17 +628,52 @@ void ivas_omasa_separate_object_render_jbm_fx( IF( single_separated ) { +#ifdef OMASA_OBJECT_EDITING + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) && st_ivas->hMasaIsmData->ism_dir_is_edited[st_ivas->hMasaIsmData->idx_separated_ism] ) + { + azimuth = st_ivas->hMasaIsmData->azimuth_ism_edited_fx[st_ivas->hMasaIsmData->idx_separated_ism]; + move16(); + elevation = st_ivas->hMasaIsmData->elevation_ism_edited_fx[st_ivas->hMasaIsmData->idx_separated_ism]; + move16(); + } + ELSE + { + azimuth = st_ivas->hMasaIsmData->azimuth_separated_ism_fx[md_idx]; + move16(); + elevation = st_ivas->hMasaIsmData->elevation_separated_ism_fx[md_idx]; + move16(); + } +#else azimuth = st_ivas->hMasaIsmData->azimuth_separated_ism[md_idx]; move16(); elevation = st_ivas->hMasaIsmData->elevation_separated_ism[md_idx]; move16(); +#endif } ELSE { +#ifdef OMASA_OBJECT_EDITING + IF( st_ivas->hMasaIsmData->ism_dir_is_edited[obj] ) + { + azimuth = st_ivas->hMasaIsmData->azimuth_ism_edited_fx[obj]; + move16(); + elevation = st_ivas->hMasaIsmData->elevation_ism_edited_fx[obj]; + move16(); + } + ELSE + { + azimuth = st_ivas->hMasaIsmData->azimuth_ism_fx[obj][md_idx]; + move16(); + elevation = st_ivas->hMasaIsmData->elevation_ism_fx[obj][md_idx]; + move16(); + } +#else azimuth = st_ivas->hMasaIsmData->azimuth_ism[obj][md_idx]; move16(); elevation = st_ivas->hMasaIsmData->elevation_ism[obj][md_idx]; move16(); +#endif } if ( st_ivas->hOutSetup.is_planar_setup ) diff --git a/lib_dec/ivas_jbm_dec_fx.c b/lib_dec/ivas_jbm_dec_fx.c index 627127187983495b5576b351bf619569d8064cdf..086102fdc1c39fd6e40fa65cb26bac98acc95afd 100644 --- a/lib_dec/ivas_jbm_dec_fx.c +++ b/lib_dec/ivas_jbm_dec_fx.c @@ -2229,13 +2229,13 @@ ivas_error ivas_jbm_dec_render_fx( Word32 gain = st_ivas->hSbaIsmData->gain_bed_fx; test(); // TODO: Enable gain editing feature (NE_32 ( gain, ONE_IN_Q_gain ) ) - IF( NE_32( gain, ONE_IN_Q31 ) && GT_32( gain, 0 ) ) + IF( NE_32( gain, ONE_IN_Q29 ) && GT_32( gain, 0 ) ) { FOR( n = 0; n < nchan_out; n++ ) { FOR( i = 0; i < *nSamplesRendered; i++ ) { - Word32 tmp1 = Mpy_32_32( p_tc_fx[n + st_ivas->nchan_ism][i], gain ); // Q11 + Q30 - 32 = Q9 + Word32 tmp1 = Mpy_32_32( p_tc_fx[n + st_ivas->nchan_ism][i], gain ); // Q11 + Q29 - 31 = Q9 tmp1 = L_shl( tmp1, 2 ); // Q9 --> Q11 p_output_fx[n][i] = L_add_sat( p_output_fx[n][i], tmp1 ); // Q11 } @@ -4719,10 +4719,36 @@ void ivas_jbm_dec_prepare_renderer( test(); IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) { +#ifdef OMASA_OBJECT_EDITING + + v_multc_fx_16( st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], OMASA_TDREND_MATCHING_GAIN_FX, st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], st_ivas->hTcBuffer->n_samples_available ); + + IF( st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) + { + v_multc_fx_16( st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], st_ivas->hMasaIsmData->gain_ism_edited_fx[n], st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], st_ivas->hTcBuffer->n_samples_available ); + Scale_sig32( st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], st_ivas->hTcBuffer->n_samples_available, Q3 ); // Q8 -> Q11 + } +#else v_multc_fx_16( st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], OMASA_TDREND_MATCHING_GAIN_FX, st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], st_ivas->hTcBuffer->n_samples_available ); +#endif } delay_signal32_fx( st_ivas->hTcBuffer->tc_fx[CPE_CHANNELS + n], st_ivas->hTcBuffer->n_samples_available, st_ivas->hMasaIsmData->delayBuffer_fx[n], st_ivas->hMasaIsmData->delayBuffer_size ); + // TODO: check if tis is a bug in main already } +#ifdef OMASA_OBJECT_EDITING + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) + { + IF( st_ivas->hMasaIsmData->masa_gain_is_edited ) + { + FOR( n = 0; n < 2; n++ ) + { + v_multc_fx_16( st_ivas->hTcBuffer->tc_fx[n], st_ivas->hMasaIsmData->gain_masa_edited_fx, st_ivas->hTcBuffer->tc_fx[n], st_ivas->hTcBuffer->n_samples_available ); // Q8 + Scale_sig32( st_ivas->hTcBuffer->tc_fx[n], st_ivas->hTcBuffer->n_samples_available, Q3 ); // Q8 -> Q11 + } + } + } +#endif } } ELSE IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) diff --git a/lib_dec/ivas_masa_dec_fx.c b/lib_dec/ivas_masa_dec_fx.c index b6d514e7e1c7101147f483fe1182a003d63a5cc4..1938761f25a596e027e78f014881a55c58041ca1 100644 --- a/lib_dec/ivas_masa_dec_fx.c +++ b/lib_dec/ivas_masa_dec_fx.c @@ -501,9 +501,9 @@ ivas_error ivas_masa_decode_fx( FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) { meta_write_index = add( st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx, sf ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length; - st_ivas->hMasaIsmData->azimuth_separated_ism[meta_write_index] = st_ivas->hMasaIsmData->azimuth_ism[obj][meta_write_index]; + st_ivas->hMasaIsmData->azimuth_separated_ism_fx[meta_write_index] = st_ivas->hMasaIsmData->azimuth_ism_fx[obj][meta_write_index]; move16(); - st_ivas->hMasaIsmData->elevation_separated_ism[meta_write_index] = st_ivas->hMasaIsmData->elevation_ism[obj][meta_write_index]; + st_ivas->hMasaIsmData->elevation_separated_ism_fx[meta_write_index] = st_ivas->hMasaIsmData->elevation_ism_fx[obj][meta_write_index]; move16(); } } @@ -834,9 +834,15 @@ ivas_error ivas_masa_dec_open_fx( move32(); /* ISM metadata */ + +#ifdef OMASA_OBJECT_EDITING + test(); + IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->hIsmMetaData[0] != NULL ) +#else test(); test(); IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->hIsmMetaData[0] != NULL && EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) +#endif { /* these are not needed -> clean. EXT metafile writer in OMASA needs only the number of ISMs and writes default null-data */ ivas_ism_metadata_close( st_ivas->hIsmMetaData, 0 ); @@ -3352,6 +3358,9 @@ static Word16 ivas_decode_masaism_metadata_fx( FOR( obj = 0; obj < nchan_ism; obj++ ) { +#ifdef OMASA_OBJECT_EDITING + hMasaIsmData->bits_ism[obj] = bits_ism[obj]; +#endif index = 0; move16(); IF( LT_16( bits_ism[obj], 8 ) ) /* if low resolution, can look to the past */ @@ -3428,9 +3437,9 @@ static Word16 ivas_decode_masaism_metadata_fx( Word16 int_azi = rint_fx( L_shr( azimuth, Q22 - 16 ) ); // Q0, extra -16 is added as int_azi is W16 and azimuth is W32 Word16 int_ele = rint_fx( L_shr( elevation, Q22 - 16 ) ); // Q0 - hMasaIsmData->azimuth_ism[obj][meta_write_index] = int_azi; // Q0 + hMasaIsmData->azimuth_ism_fx[obj][meta_write_index] = int_azi; // Q0 move16(); - hMasaIsmData->elevation_ism[obj][meta_write_index] = int_ele; // Q0 + hMasaIsmData->elevation_ism_fx[obj][meta_write_index] = int_ele; // Q0 move16(); } } diff --git a/lib_dec/ivas_objectRenderer_internal_fx.c b/lib_dec/ivas_objectRenderer_internal_fx.c index 6de0709034bbf422519cb6ff418a1e3106118d16..21613852e08a25c9c1d718539e89febeecc0bd5b 100644 --- a/lib_dec/ivas_objectRenderer_internal_fx.c +++ b/lib_dec/ivas_objectRenderer_internal_fx.c @@ -243,7 +243,7 @@ ivas_error ivas_td_binaural_renderer_sf_fx( return error; } } - else + ELSE #endif { IF( NE_16( error = TDREND_Update_object_positions_fx( st_ivas->hBinRendererTd, nchan_ism, st_ivas->ivas_format, st_ivas->hIsmMetaData ), IVAS_ERR_OK ) ) diff --git a/lib_dec/ivas_omasa_dec_fx.c b/lib_dec/ivas_omasa_dec_fx.c index e537470728681055f55b83f525e4d71f7bf8166e..bc822cd719d97a19f66d49674f475350d8c9b906 100644 --- a/lib_dec/ivas_omasa_dec_fx.c +++ b/lib_dec/ivas_omasa_dec_fx.c @@ -315,7 +315,11 @@ ivas_error ivas_omasa_data_open_fx( ) { MASA_ISM_DATA_HANDLE hMasaIsmData; +#ifdef OMASA_OBJECT_EDITING + Word16 ch; +#else Word16 ch, bin; +#endif Word16 sf, obj_idx; IF( ( hMasaIsmData = (MASA_ISM_DATA_HANDLE) malloc( sizeof( MASA_ISM_DATA ) ) ) == NULL ) @@ -323,6 +327,39 @@ ivas_error ivas_omasa_data_open_fx( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA ISM data\n" ) ); } +#ifdef OMASA_OBJECT_EDITING + FOR( Word16 band_idx = 0; band_idx < MASA_FREQUENCY_BANDS; band_idx++ ) + { + FOR( ch = 0; ch < 2; ch++ ) + { + + hMasaIsmData->ismPreprocMatrix_fx[ch][ch][band_idx] = ONE_IN_Q28; + move32(); + hMasaIsmData->ismPreprocMatrix_fx[sub( 1, ch )][ch][band_idx] = 0; + move32(); + hMasaIsmData->eneMoveIIR_fx[ch][band_idx] = 0; + move32(); + hMasaIsmData->eneMoveIIR_e[ch][band_idx] = 0; + move16(); + hMasaIsmData->enePreserveIIR_fx[ch][band_idx] = 0; + move32(); + hMasaIsmData->enePreserveIIR_e[ch][band_idx] = 0; + move16(); + } + + hMasaIsmData->eneOrigIIR_fx[band_idx] = 0; + move32(); + hMasaIsmData->eneOrigIIR_e[band_idx] = 0; + move16(); + hMasaIsmData->preprocEneTarget_fx[band_idx] = 0; + move32(); + hMasaIsmData->preprocEneRealized_fx[band_idx] = 0; + move32(); + } + + hMasaIsmData->objectsEdited = 0; + move32(); +#else FOR( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) { FOR( ch = 0; ch < 2; ch++ ) @@ -344,29 +381,42 @@ ivas_error ivas_omasa_data_open_fx( hMasaIsmData->objectsMoved = 0; move16(); +#endif hMasaIsmData->delayBuffer_fx = NULL; + move16(); FOR( ch = 0; ch < MAX_NUM_OBJECTS; ch++ ) { +#ifdef OMASA_OBJECT_EDITING + hMasaIsmData->ism_dir_is_edited[ch] = 0; + hMasaIsmData->ism_gain_is_edited[ch] = 0; +#else hMasaIsmData->ism_is_edited[ch] = 0; move16(); +#endif hMasaIsmData->q_elevation_old_fx[ch] = 0; // Q22 move32(); hMasaIsmData->q_azimuth_old_fx[ch] = 0; // Q22 move32(); } +#ifdef OMASA_OBJECT_EDITING + hMasaIsmData->masa_gain_is_edited = 0; + hMasaIsmData->idx_separated_ism = -1; + move16(); +#endif + FOR( obj_idx = 0; obj_idx < MAX_NUM_OBJECTS; obj_idx++ ) { - set16_fx( hMasaIsmData->azimuth_ism[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); - set16_fx( hMasaIsmData->elevation_ism[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + set16_fx( hMasaIsmData->azimuth_ism_fx[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + set16_fx( hMasaIsmData->elevation_ism_fx[obj_idx], 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR; sf++ ) { set32_fx( hMasaIsmData->energy_ratio_ism_fx[obj_idx][sf], 0, CLDFB_NO_CHANNELS_MAX ); } } - set16_fx( hMasaIsmData->azimuth_separated_ism, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); - set16_fx( hMasaIsmData->elevation_separated_ism, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + set16_fx( hMasaIsmData->azimuth_separated_ism_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); + set16_fx( hMasaIsmData->elevation_separated_ism_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR ); hMasaIsmData->hExtData = NULL; move32(); @@ -471,7 +521,11 @@ ivas_error ivas_omasa_dec_config_fx( Word16 *num_src, Word16 SrcInd[MAX_NUM_TDREND_CHANNELS] ) { +#ifdef OMASA_OBJECT_EDITING + Word16 k, sce_id, nSCE_old, nchan_hp20_old, numCldfbAnalyses_old, numCldfbSyntheses_old; +#else Word16 k, sce_id, nSCE_old, nchan_hp20_old, numCldfbAnalyses_old, numCldfbSyntheses_old, n_MD; +#endif Word32 ivas_total_brate, ism_total_brate, cpe_brate; Word32 brate_SCE, brate_CPE; ISM_MODE ism_mode_old; @@ -597,6 +651,22 @@ ivas_error ivas_omasa_dec_config_fx( IF( NE_16( ism_mode_old, st_ivas->ism_mode ) ) { /* ISM MD reconfig. */ +#ifdef OMASA_OBJECT_EDITING + IF( st_ivas->hIsmMetaData[0] == NULL ) + { + IF( ( error = ivas_ism_metadata_dec_create_fx( st_ivas, st_ivas->nchan_ism, NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + FOR( k = 0; k < st_ivas->nchan_ism; k++ ) + { + ivas_ism_reset_metadata_handle_dec_fx( st_ivas->hIsmMetaData[k] ); + } + } +#else n_MD = 0; move16(); @@ -655,6 +725,7 @@ ivas_error ivas_omasa_dec_config_fx( ivas_ism_metadata_close( st_ivas->hIsmMetaData, n_MD ); } +#endif st_ivas->hCPE[0]->element_brate = L_sub( ivas_total_brate, ism_total_brate ); @@ -1019,9 +1090,9 @@ ivas_error ivas_omasa_ism_metadata_dec_fx( { meta_write_index = ( add( dirac_bs_md_write_idx, block ) ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length; move16(); - st_ivas->hMasaIsmData->azimuth_ism[n][meta_write_index] = azimuth_ism; + st_ivas->hMasaIsmData->azimuth_ism_fx[n][meta_write_index] = azimuth_ism; move16(); - st_ivas->hMasaIsmData->elevation_ism[n][meta_write_index] = elevation_ism; + st_ivas->hMasaIsmData->elevation_ism_fx[n][meta_write_index] = elevation_ism; move16(); } } @@ -1043,9 +1114,9 @@ ivas_error ivas_omasa_ism_metadata_dec_fx( { meta_write_index = ( add( dirac_bs_md_write_idx, block ) ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length; move16(); - st_ivas->hMasaIsmData->azimuth_separated_ism[meta_write_index] = azimuth_ism; + st_ivas->hMasaIsmData->azimuth_separated_ism_fx[meta_write_index] = azimuth_ism; move16(); - st_ivas->hMasaIsmData->elevation_separated_ism[meta_write_index] = elevation_ism; + st_ivas->hMasaIsmData->elevation_separated_ism_fx[meta_write_index] = elevation_ism; move16(); } } @@ -1065,15 +1136,15 @@ ivas_error ivas_omasa_ism_metadata_dec_fx( FOR( block = 0; block < 2; block++ ) { - st_ivas->hMasaIsmData->azimuth_separated_ism[block] = st_ivas->hMasaIsmData->azimuth_separated_ism[add( block, 2 )]; - st_ivas->hMasaIsmData->elevation_separated_ism[block] = st_ivas->hMasaIsmData->elevation_separated_ism[add( block, 2 )]; + st_ivas->hMasaIsmData->azimuth_separated_ism_fx[block] = st_ivas->hMasaIsmData->azimuth_separated_ism_fx[add( block, 2 )]; + st_ivas->hMasaIsmData->elevation_separated_ism_fx[block] = st_ivas->hMasaIsmData->elevation_separated_ism_fx[add( block, 2 )]; move16(); move16(); } FOR( block = 2; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) { - st_ivas->hMasaIsmData->azimuth_separated_ism[block] = azimuth_ism; - st_ivas->hMasaIsmData->elevation_separated_ism[block] = elevation_ism; + st_ivas->hMasaIsmData->azimuth_separated_ism_fx[block] = azimuth_ism; + st_ivas->hMasaIsmData->elevation_separated_ism_fx[block] = elevation_ism; move16(); move16(); } @@ -1113,13 +1184,47 @@ void ivas_omasa_dirac_rend_jbm_fx( IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) { Copy32( &output_f[CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[0], *nSamplesRendered ); +#ifdef OMASA_OBJECT_EDITING + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + /* Gain separated object, if edited */ + FOR( n = 0; n < st_ivas->nchan_ism; n++ ) + { + test(); + IF( st_ivas->hMasaIsmData->ism_gain_is_edited[n] && EQ_16( st_ivas->hMasaIsmData->idx_separated_ism, n ) ) + { + v_multc_fx_16( data_separated_objects[0], st_ivas->hMasaIsmData->gain_ism_edited_fx[n], data_separated_objects[0], *nSamplesRendered ); // Q = 8 + Scale_sig32( data_separated_objects[0], *nSamplesRendered, Q3 ); // Q = 11 + } + } + } +#endif } ELSE { FOR( n = 0; n < st_ivas->nchan_ism; n++ ) { Copy32( &output_f[n + CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[n], *nSamplesRendered ); +#ifdef OMASA_OBJECT_EDITING + /* Gain discrete objects, if edited */ + IF( st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) + { + v_multc_fx_16( data_separated_objects[n], st_ivas->hMasaIsmData->gain_ism_edited_fx[n], data_separated_objects[n], *nSamplesRendered ); // Q = 8 + Scale_sig32( data_separated_objects[n], *nSamplesRendered, Q3 ); // Q = 11 + } +#endif } +#ifdef OMASA_OBJECT_EDITING + /* Gain MASA part, if edited */ + IF( st_ivas->hMasaIsmData->masa_gain_is_edited ) + { + FOR( n = 0; n < 2; n++ ) + { + v_multc_fx_16( output_f[n], st_ivas->hMasaIsmData->gain_masa_edited_fx, output_f[n], *nSamplesRendered ); // Q = 8 + Scale_sig32( output_f[n], *nSamplesRendered, Q3 ); // Q = 11 + } + } +#endif } } @@ -1493,8 +1598,8 @@ void ivas_omasa_combine_separate_ism_with_masa_fx( { Word32 ele, azi; - ele = st_ivas->hMasaIsmData->elevation_separated_ism[sf]; - azi = st_ivas->hMasaIsmData->azimuth_separated_ism[sf]; + ele = st_ivas->hMasaIsmData->elevation_separated_ism_fx[sf]; + azi = st_ivas->hMasaIsmData->azimuth_separated_ism_fx[sf]; directionIndex = index_theta_phi_16_fx( &ele, &azi, st_ivas->hMasa->data.sph_grid16 ); @@ -1520,10 +1625,10 @@ void ivas_omasa_combine_separate_ism_with_masa_fx( eneIsm_frac, eneIsm_exp ); /* Mix the separated object audio signal to the MASA audio signals */ - ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism[0], - st_ivas->hMasaIsmData->elevation_separated_ism[0], old_panning_gains_q15_fx ); - ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism[2], - st_ivas->hMasaIsmData->elevation_separated_ism[2], new_panning_gains_q15_fx ); + ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism_fx[0], + st_ivas->hMasaIsmData->elevation_separated_ism_fx[0], old_panning_gains_q15_fx ); + ivas_get_stereo_panning_gains_fx( st_ivas->hMasaIsmData->azimuth_separated_ism_fx[2], + st_ivas->hMasaIsmData->elevation_separated_ism_fx[2], new_panning_gains_q15_fx ); /* Subsequent processing in Q31 format */ FOR( n = 0; n < MASA_MAX_TRANSPORT_CHANNELS; n++ ) @@ -1742,8 +1847,8 @@ void ivas_omasa_render_objects_from_mix_fx( FOR( n = 0; n < nchan_ism; n++ ) { // Q0 -> Q22 - Word32 azi = L_shl( st_ivas->hMasaIsmData->azimuth_ism[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 ); - Word32 ele = L_shl( st_ivas->hMasaIsmData->elevation_ism[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 ); + Word32 azi = L_shl( st_ivas->hMasaIsmData->azimuth_ism_fx[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 ); + Word32 ele = L_shl( st_ivas->hMasaIsmData->elevation_ism_fx[n][st_ivas->hSpatParamRendCom->dirac_read_idx], Q22 ); st_ivas->hIsmMetaData[n]->azimuth_fx = azi; st_ivas->hIsmMetaData[n]->elevation_fx = ele; diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index e9a61da56f071c464a464c6633744ec0273bf26c..68188621f3d65b889a1a0b8b57589e90435bf594 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -464,8 +464,8 @@ typedef struct ivas_param_ism_dec_data_structure Word16 power_ratios_fx[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS][MAX_PARAM_ISM_WAVE]; /* Q15 */ #ifdef OBJ_EDITING_API - Word32 edited_azimuth_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; - Word32 edited_elevation_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; + Word32 edited_azimuth_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; // Q22 + Word32 edited_elevation_values_fx[MAX_PARAM_SPATIAL_SUBFRAMES * IVAS_MAX_NUM_BANDS]; // Q22 #endif /*sub-modules*/ @@ -721,7 +721,7 @@ typedef struct ivas_osba_data Word16 delayBuffer_nchan; #ifdef OBJ_EDITING_API - Word32 gain_bed_fx; + Word32 gain_bed_fx; // Q29 #endif } SBA_ISM_DATA, *SBA_ISM_DATA_HANDLE; @@ -955,32 +955,65 @@ typedef struct ivas_masa_ism_ext_data_structure /* Data structure for MASA_ISM rendering */ typedef struct ivas_masa_ism_data_structure { - Word16 azimuth_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; - Word16 elevation_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + Word16 azimuth_ism_fx[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; // Q0 + Word16 elevation_ism_fx[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; // Q0 Word32 energy_ratio_ism_fx[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; /* Q30 */ Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; /* Q30 */ - Word16 azimuth_ism_edited[MAX_NUM_OBJECTS]; - Word16 elevation_ism_edited[MAX_NUM_OBJECTS]; + Word16 azimuth_ism_edited_fx[MAX_NUM_OBJECTS]; // Q0 + Word16 elevation_ism_edited_fx[MAX_NUM_OBJECTS]; // Q0 + +#ifdef OMASA_OBJECT_EDITING + UWord8 ism_dir_is_edited[MAX_NUM_OBJECTS]; +#else UWord8 ism_is_edited[MAX_NUM_OBJECTS]; +#endif #ifdef OBJ_EDITING_API - Word32 gain_ism[MAX_NUM_OBJECTS]; - Word32 gain_masa; + Word16 gain_ism_fx[MAX_NUM_OBJECTS]; + Word16 gain_masa_fx; +#endif + +#ifdef OMASA_OBJECT_EDITING + Word16 gain_ism_edited_fx[MAX_NUM_OBJECTS]; // Q12 + UWord8 ism_gain_is_edited[MAX_NUM_OBJECTS]; + Word16 gain_masa_edited_fx; // Q12 + UWord8 masa_gain_is_edited; +#else + Word16 azimuth_ism_edited[MAX_NUM_OBJECTS]; + Word16 elevation_ism_edited[MAX_NUM_OBJECTS]; + // UWord8 ism_is_edited[MAX_NUM_OBJECTS]; #endif Word16 idx_separated_ism; - Word16 azimuth_separated_ism[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; - Word16 elevation_separated_ism[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + Word16 azimuth_separated_ism_fx[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; + Word16 elevation_separated_ism_fx[MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; Word32 q_azimuth_old_fx[MAX_NUM_OBJECTS]; /* Q22 */ Word32 q_elevation_old_fx[MAX_NUM_OBJECTS]; /* Q22 */ +#ifdef OMASA_OBJECT_EDITING + UWord8 objectsEdited; + Word32 preprocEneTarget_fx[MASA_FREQUENCY_BANDS]; + Word16 preprocEneTarget_e[MASA_FREQUENCY_BANDS]; + Word32 preprocEneRealized_fx[MASA_FREQUENCY_BANDS]; + Word16 preprocEneRealized_e[MASA_FREQUENCY_BANDS]; + Word32 ismPreprocMatrix_fx[2][2][MASA_FREQUENCY_BANDS]; // Q28? + // Word16 ismPreprocMatrix_e[2][2][MASA_FREQUENCY_BANDS]; // Not needed? + Word32 eneMoveIIR_fx[2][MASA_FREQUENCY_BANDS]; + Word16 eneMoveIIR_e[2][MASA_FREQUENCY_BANDS]; + Word32 enePreserveIIR_fx[2][MASA_FREQUENCY_BANDS]; + Word16 enePreserveIIR_e[2][MASA_FREQUENCY_BANDS]; + Word32 eneOrigIIR_fx[MASA_FREQUENCY_BANDS]; + Word16 eneOrigIIR_e[MASA_FREQUENCY_BANDS]; + Word16 bits_ism[MAX_NUM_OBJECTS]; +#else Word16 ismPreprocMatrix_fx[2][2][CLDFB_NO_CHANNELS_MAX]; /* Q15 */ UWord8 objectsMoved; Word32 eneMoveIIR_fx[2][CLDFB_NO_CHANNELS_MAX]; /*Q-22*/ Word32 enePreserveIIR_fx[2][CLDFB_NO_CHANNELS_MAX]; /*Q-22*/ Word32 preprocEneTarget_fx[CLDFB_NO_CHANNELS_MAX]; /*Q-19*/ Word32 preprocEneRealized_fx[CLDFB_NO_CHANNELS_MAX]; /*Q-19*/ +#endif Word32 **delayBuffer_fx; /* Q11 */ Word16 delayBuffer_size; diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index a68fed3a11dfad9ffe94e6b09aa8a7a4d0f77b44..b7fc02d968c7d4614cd5fbe08f6bb011152f15db 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -166,16 +166,16 @@ ivas_error IVAS_DEC_GetSamples( #ifdef OBJ_EDITING_API ivas_error IVAS_DEC_GetEditableParameters( IVAS_DEC_HANDLE hIvasDec, - IVAS_EDITABLE_PARAMETERS *hIvasEditableParameters + IVAS_EDITABLE_PARAMETERS *hIvasEditableParameters ); ivas_error IVAS_DEC_SetEditableParameters( IVAS_DEC_HANDLE hIvasDec, - IVAS_EDITABLE_PARAMETERS hIvasEditableParameters + IVAS_EDITABLE_PARAMETERS hIvasEditableParameters ); ivas_error IVAS_DEC_PrepareRenderer( - IVAS_DEC_HANDLE hIvasDec + IVAS_DEC_HANDLE hIvasDec ); #endif diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 559a4444e6e409b8d12d3d505a3bc492bbe82451..3d1c4366e6439df51cb2da4d3dad983927fae641 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -1,4 +1,4 @@ -/****************************************************************************************************** +/****************************************************************************************************** (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., @@ -38,6 +38,9 @@ #include "ivas_prot_rend_fx.h" #include "prot_fx.h" #include "isar_prot.h" +#ifdef OMASA_OBJECT_EDITING +#include "ivas_rom_com.h" +#endif #include "lib_isar_pre_rend.h" #include "ivas_prot_fx.h" #include "jbm_jb4sb.h" @@ -2287,7 +2290,7 @@ ivas_error IVAS_DEC_GetObjectMetadata( metadata->yaw_fx = 0; // Q22 metadata->pitch_fx = 0; // Q22 metadata->spread_fx = 0; // Q22 - metadata->gainFactor_fx = ONE_IN_Q31; // Q31 + metadata->gainFactor_fx = ONE_IN_Q29; // Q31 metadata->non_diegetic_flag = 0; } ELSE @@ -2314,7 +2317,7 @@ ivas_error IVAS_DEC_GetObjectMetadata( metadata->yaw_fx = hIsmMeta->yaw_fx; metadata->pitch_fx = hIsmMeta->pitch_fx; metadata->spread_fx = 0; - metadata->gainFactor_fx = ONE_IN_Q31; + metadata->gainFactor_fx = ONE_IN_Q29; metadata->non_diegetic_flag = hIsmMeta->non_diegetic_flag; } ELSE IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) @@ -2337,7 +2340,7 @@ ivas_error IVAS_DEC_GetObjectMetadata( metadata->yaw_fx = hIsmMeta->yaw_fx; // Q22 metadata->pitch_fx = hIsmMeta->pitch_fx; // Q22 metadata->spread_fx = 0; // Q22 - metadata->gainFactor_fx = ONE_IN_Q31; + metadata->gainFactor_fx = ONE_IN_Q29; metadata->non_diegetic_flag = hIsmMeta->non_diegetic_flag; } } @@ -3924,7 +3927,14 @@ ivas_error IVAS_DEC_GetSamplesDecoder( { IF( hIvasDec->st_ivas->ivas_format == ISM_FORMAT || hIvasDec->st_ivas->ivas_format == MASA_ISM_FORMAT || hIvasDec->st_ivas->ivas_format == SBA_ISM_FORMAT ) { +#ifdef OMASA_OBJECT_EDITING + test(); + test(); + test(); + IF( EQ_32( hIvasDec->st_ivas->ism_mode, ISM_MODE_DISC ) || EQ_32( hIvasDec->st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( hIvasDec->st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( hIvasDec->st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) +#else IF( hIvasDec->st_ivas->ism_mode == ISM_MODE_DISC || hIvasDec->st_ivas->ism_mode == ISM_MASA_MODE_DISC || hIvasDec->st_ivas->ism_mode == ISM_SBA_MODE_DISC ) +#endif { Word16 obj; ISM_METADATA_HANDLE *hIsmMetaData = hIvasDec->st_ivas->hIsmMetaData; @@ -3935,12 +3945,12 @@ ivas_error IVAS_DEC_GetSamplesDecoder( hIsmMetaData[obj]->edited_yaw_fx = hIsmMetaData[obj]->yaw_fx; hIsmMetaData[obj]->edited_pitch_fx = hIsmMetaData[obj]->pitch_fx; hIsmMetaData[obj]->edited_radius_fx = hIsmMetaData[obj]->radius_fx; - hIsmMetaData[obj]->edited_gain_fx = ONE_IN_Q31; + hIsmMetaData[obj]->edited_gain_fx = ONE_IN_Q29; // TODO: Check Q value } IF( hIvasDec->st_ivas->ism_mode == ISM_SBA_MODE_DISC ) { - hIvasDec->st_ivas->hSbaIsmData->gain_bed_fx = ONE_IN_Q31; + hIvasDec->st_ivas->hSbaIsmData->gain_bed_fx = ONE_IN_Q29; // TODO: Check Q value } } } @@ -3975,7 +3985,7 @@ ivas_error IVAS_DEC_GetEditableParameters( IVAS_DEC_HANDLE hIvasDec, IVAS_EDITABLE_PARAMETERS *hIvasEditableParameters ) { - Word16 obj; + Word16 obj, dirac_read_idx; Decoder_Struct *st_ivas; ISM_MODE ism_mode; @@ -4011,7 +4021,7 @@ ivas_error IVAS_DEC_GetEditableParameters( } #endif - hIvasEditableParameters->gain_bed_fx = ONE_IN_Q30; + hIvasEditableParameters->gain_bed_fx = ONE_IN_Q29; move32(); hIvasEditableParameters->num_obj = st_ivas->nchan_ism; move16(); @@ -4043,7 +4053,7 @@ ivas_error IVAS_DEC_GetEditableParameters( IF( EQ_32( ism_mode, ISM_SBA_MODE_DISC ) ) { - hIvasEditableParameters->gain_bed_fx = ONE_IN_Q30; + hIvasEditableParameters->gain_bed_fx = ONE_IN_Q29; move32(); } } @@ -4061,17 +4071,66 @@ ivas_error IVAS_DEC_GetEditableParameters( move32(); hIvasEditableParameters->ism_metadata[obj].radius_fx = 0; move16(); - hIvasEditableParameters->ism_metadata[obj].gain_fx = ONE_IN_Q31; + hIvasEditableParameters->ism_metadata[obj].gain_fx = ONE_IN_Q29; // TODO check Q-value move32(); hIvasEditableParameters->ism_metadata[obj].non_diegetic_flag = 0; move16(); } } - else + ELSE { assert( 0 && "This should never happen!" ); } } +#ifdef OMASA_OBJECT_EDITING + ELSE IF( hIvasDec->st_ivas->ivas_format == MASA_ISM_FORMAT && ( hIvasDec->st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || hIvasDec->st_ivas->ism_mode == ISM_MASA_MODE_DISC ) ) + { + /* object editing possible only in two highest OMASA modes */ + IF( hIvasDec->st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + FOR( obj = 0; obj < hIvasEditableParameters->num_obj; obj++ ) + { + hIvasEditableParameters->ism_metadata[obj].azimuth_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->azimuth_fx; + hIvasEditableParameters->ism_metadata[obj].elevation_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->elevation_fx; + hIvasEditableParameters->ism_metadata[obj].yaw_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->yaw_fx; + hIvasEditableParameters->ism_metadata[obj].pitch_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->pitch_fx; + hIvasEditableParameters->ism_metadata[obj].radius_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->radius_fx; + + /* reset the otherwise unused "gain" field for the object */ + hIvasDec->st_ivas->hIsmMetaData[obj]->edited_gain_fx = ONE_IN_Q29; + hIvasEditableParameters->ism_metadata[obj].gain_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->edited_gain_fx; + hIvasEditableParameters->ism_metadata[obj].non_diegetic_flag = hIvasDec->st_ivas->hIsmMetaData[obj]->non_diegetic_flag; + } + } + ELSE + { + /* Handle MONO output */ + IF( hIvasDec->st_ivas->renderer_type != RENDERER_MONO_DOWNMIX ) + { + dirac_read_idx = hIvasDec->st_ivas->hSpatParamRendCom->render_to_md_map[hIvasDec->st_ivas->hSpatParamRendCom->subframes_rendered]; + } + ELSE + { + dirac_read_idx = 0; + } + + FOR( obj = 0; obj < hIvasEditableParameters->num_obj; obj++ ) + { + hIvasEditableParameters->ism_metadata[obj].azimuth_fx = L_shl( L_deposit_l( hIvasDec->st_ivas->hMasaIsmData->azimuth_ism_fx[obj][dirac_read_idx] ), Q22 ); + hIvasEditableParameters->ism_metadata[obj].elevation_fx = L_shl( L_deposit_l( hIvasDec->st_ivas->hMasaIsmData->elevation_ism_fx[obj][dirac_read_idx] ), Q22 ); + + hIvasEditableParameters->ism_metadata[obj].yaw_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->yaw_fx; + hIvasEditableParameters->ism_metadata[obj].pitch_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->pitch_fx; + hIvasEditableParameters->ism_metadata[obj].radius_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->radius_fx; + + /* reset the otherwise unused "gain" field for the object */ + hIvasDec->st_ivas->hIsmMetaData[obj]->edited_gain_fx = ONE_IN_Q29; + hIvasEditableParameters->ism_metadata[obj].gain_fx = hIvasDec->st_ivas->hIsmMetaData[obj]->edited_gain_fx; + hIvasEditableParameters->ism_metadata[obj].non_diegetic_flag = hIvasDec->st_ivas->hIsmMetaData[obj]->non_diegetic_flag; + } + } + } +#endif return IVAS_ERR_OK; } @@ -4087,6 +4146,10 @@ ivas_error IVAS_DEC_SetEditableParameters( IVAS_DEC_HANDLE hIvasDec, IVAS_EDITABLE_PARAMETERS hIvasEditableParameters ) { +#ifdef OMASA_OBJECT_EDITING + Word16 dirac_read_idx; +#endif + Word16 obj; Decoder_Struct *st_ivas; ISM_MODE ism_mode; @@ -4153,13 +4216,159 @@ ivas_error IVAS_DEC_SetEditableParameters( { FOR( obj = 0; obj < hIvasEditableParameters.num_obj; obj++ ) { +#ifdef OBJ_EDITING_PARAMISM_BIN + hIvasDec->st_ivas->hParamIsmDec->edited_azimuth_values_fx[obj] = hIvasEditableParameters.ism_metadata[obj].azimuth_fx; + hIvasDec->st_ivas->hParamIsmDec->edited_elevation_values_fx[obj] = hIvasEditableParameters.ism_metadata[obj].elevation_fx; + hIvasDec->st_ivas->hMasaIsmData->gain_ism_edited_fx[obj] = shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ); // Q29 -> Q12 + + /* Detect direction editing in Param-ISM mode */ + IF( GT_32( L_abs( L_sub( hIvasDec->st_ivas->hParamIsmDec->azimuth_values_fx[obj], hIvasEditableParameters.ism_metadata[obj].azimuth_fx ) ), OMASA_AZI_EDIT_THR_FX ) || + GT_32( L_abs( L_sub( hIvasDec->st_ivas->hParamIsmDec->elevation_values_fx[obj], hIvasEditableParameters.ism_metadata[obj].elevation_fx ) ), OMASA_ELE_EDIT_THR_FX ) ) + { + hIvasDec->st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1; + } + ELSE + { + hIvasDec->st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0; + } + + /* Detect gain editing in Param-ISM mode */ + IF( GT_16( abs_s( sub( ONE_IN_Q12, shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ) ) ), OMASA_GAIN_EDIT_THR_FX ) ) // TODO: check Q values + { + hIvasDec->st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1; + } + ELSE + { + hIvasDec->st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 0; + } +#endif } +#ifdef OBJ_EDITING_PARAMISM_BIN + /* MASA is not present with the ISM format */ + hIvasDec->st_ivas->hMasaIsmData->masa_gain_is_edited = 0; +#endif } - else + ELSE { assert( 0 && "This should never happen!" ); } } +#ifdef OMASA_OBJECT_EDITING + ELSE IF( EQ_16( hIvasDec->st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_16( hIvasDec->st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( hIvasDec->st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) ) + { + Word32 id_th; + Word32 threshold_azi, threshold_ele; + + FOR( obj = 0; obj < hIvasEditableParameters.num_obj; obj++ ) + { + IF( hIvasDec->st_ivas->hMasaIsmData != NULL ) + { + /* copy relevant fields also to OMASA structs, but only if the value has been changed. original values are in st_ivas->hIsmMetaData */ + /* first, need to convert float values to ints used internally */ + Word16 new_azi, new_ele; + new_azi = extract_l( L_shr( L_add( L_abs( hIvasEditableParameters.ism_metadata[obj].azimuth_fx ), 2097152 ), Q22 ) ); // Q22->Q0 + IF( LT_32( hIvasEditableParameters.ism_metadata[obj].azimuth_fx, 0 ) ) + { + new_azi = negate( new_azi ); + } + + new_ele = extract_l( L_shr( L_add( L_abs( hIvasEditableParameters.ism_metadata[obj].elevation_fx ), 2097152 ), Q22 ) ); // Q22->Q0 + IF( LT_32( hIvasEditableParameters.ism_metadata[obj].elevation_fx, 0 ) ) + { + new_ele = negate( new_ele ); + } + + IF( EQ_16( hIvasDec->st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + /* Handle MONO output */ + IF( NE_16( hIvasDec->st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) + { + dirac_read_idx = hIvasDec->st_ivas->hSpatParamRendCom->render_to_md_map[hIvasDec->st_ivas->hSpatParamRendCom->subframes_rendered]; + } + ELSE + { + dirac_read_idx = 0; + } + + /* determine thresholds for detecting object metadata edit for direction based on quantization resolution of the spatial direction parameters. + * these depend from the number of bits used to transmit the directions, + * which in turn depends from the object priority and importance: + * importance -> priority -> number of bits -> elevation resolution -> elevation ring index -> azimuth resolution. + * leading to elevation_resolution -> elevation threshold and azimuth resolution -> azimuth threshold */ + id_th = extract_l( L_shr( L_add( Mpy_32_16_1( delta_theta_masa_inv_fx[hIvasDec->st_ivas->hMasaIsmData->bits_ism[obj] - 3], abs_s( hIvasDec->st_ivas->hMasaIsmData->elevation_ism_fx[obj][dirac_read_idx] ) ), 32768 ), 16 ) ); // + 0.5f in Q16 + threshold_azi = Mpy_32_32( 1509949440, no_phi_masa_inv_fx[hIvasDec->st_ivas->hMasaIsmData->bits_ism[obj] - 1][id_th] ); // Q = 22; + threshold_ele = delta_theta_masa_fx[hIvasDec->st_ivas->hMasaIsmData->bits_ism[obj] - 3]; + + test(); + IF( ( GT_32( L_shl( abs_s( sub( new_azi, hIvasDec->st_ivas->hMasaIsmData->azimuth_ism_fx[obj][dirac_read_idx] ) ), 22 ), threshold_azi ) ) || + ( GT_32( L_shl( abs_s( sub( new_ele, hIvasDec->st_ivas->hMasaIsmData->elevation_ism_fx[obj][dirac_read_idx] ) ), 22 ), threshold_ele ) ) ) + { + /* at least one of the threshold is exceeded, so use new direction value and set editing detection flag */ + hIvasDec->st_ivas->hMasaIsmData->azimuth_ism_edited_fx[obj] = new_azi; + hIvasDec->st_ivas->hMasaIsmData->elevation_ism_edited_fx[obj] = new_ele; + + hIvasDec->st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1; + } + ELSE + { + hIvasDec->st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0; + } + } + ELSE + { + /* detect editing in ISM_MASA_MODE_DISC. optionally, add quantization-resolution -based thresholds */ + test(); + IF( L_abs( L_sub( hIvasDec->st_ivas->hIsmMetaData[obj]->azimuth_fx, hIvasEditableParameters.ism_metadata[obj].azimuth_fx ) ) > OMASA_AZI_EDIT_THR_FX || + L_abs( L_sub( hIvasDec->st_ivas->hIsmMetaData[obj]->elevation_fx, hIvasEditableParameters.ism_metadata[obj].elevation_fx ) ) > OMASA_ELE_EDIT_THR_FX ) + { + hIvasDec->st_ivas->hMasaIsmData->azimuth_ism_edited_fx[obj] = new_azi; + hIvasDec->st_ivas->hMasaIsmData->elevation_ism_edited_fx[obj] = new_ele; + + hIvasDec->st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 1; + } + ELSE + { + hIvasDec->st_ivas->hMasaIsmData->ism_dir_is_edited[obj] = 0; + } + } + + /* compare pre-edit gain and the edited one to detect editing */ + IF( GT_16( abs_s( sub( shr( extract_h( hIvasDec->st_ivas->hIsmMetaData[obj]->edited_gain_fx ), Q1 ), shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ) ) ), OMASA_GAIN_EDIT_THR_FX ) ) // TODO: check incoming Q value + { + hIvasDec->st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 1; + hIvasDec->st_ivas->hMasaIsmData->gain_ism_edited_fx[obj] = shr( extract_h( hIvasEditableParameters.ism_metadata[obj].gain_fx ), Q1 ); // Q29 --> Q12 + } + ELSE + { + hIvasDec->st_ivas->hMasaIsmData->ism_gain_is_edited[obj] = 0u; + } + } + + /* Copy edited values to hIsmMetaData struct */ + IF( hIvasDec->st_ivas->hIsmMetaData[obj] != NULL ) + { + hIvasDec->st_ivas->hIsmMetaData[obj]->azimuth_fx = hIvasEditableParameters.ism_metadata[obj].azimuth_fx; + hIvasDec->st_ivas->hIsmMetaData[obj]->elevation_fx = hIvasEditableParameters.ism_metadata[obj].elevation_fx; + hIvasDec->st_ivas->hIsmMetaData[obj]->yaw_fx = hIvasEditableParameters.ism_metadata[obj].yaw_fx; + hIvasDec->st_ivas->hIsmMetaData[obj]->pitch_fx = hIvasEditableParameters.ism_metadata[obj].pitch_fx; + hIvasDec->st_ivas->hIsmMetaData[obj]->radius_fx = hIvasEditableParameters.ism_metadata[obj].radius_fx; + hIvasDec->st_ivas->hIsmMetaData[obj]->edited_gain_fx = hIvasEditableParameters.ism_metadata[obj].gain_fx; // TODO: check incoming Q value + hIvasDec->st_ivas->hIsmMetaData[obj]->non_diegetic_flag = hIvasEditableParameters.ism_metadata[obj].non_diegetic_flag; + } + } + + IF( GT_16( abs_s( sub( shr( extract_h( hIvasEditableParameters.gain_bed_fx ), Q1 ), ONE_IN_Q12 ) ), OMASA_GAIN_EDIT_THR_FX ) ) // TODO: check Q value + { + hIvasDec->st_ivas->hMasaIsmData->gain_masa_edited_fx = shr( extract_h( hIvasEditableParameters.gain_bed_fx ), Q1 ); // TODO: check type + move32(); + hIvasDec->st_ivas->hMasaIsmData->masa_gain_is_edited = 1; + } + ELSE + { + hIvasDec->st_ivas->hMasaIsmData->masa_gain_is_edited = 0; + } + } +#endif return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_dirac_dec_binaural_functions_fx.c b/lib_rend/ivas_dirac_dec_binaural_functions_fx.c index 71e361f153383dba12614280ef8a4fd1cdc53ed2..e6c8df704baa3a92f73c70aaa1fa55b1fceb0632 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions_fx.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions_fx.c @@ -962,11 +962,26 @@ static void ivas_dirac_dec_binaural_internal_fx( test(); test(); test(); +#ifdef OMASA_OBJECT_EDITING +#ifdef OBJ_EDITING_PARAMISM_BIN + test(); + test(); + IF( ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) ) ) ) || EQ_32( st_ivas->ivas_format, ISM_FORMAT ) ) +#else + test(); + IF( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) ) +#endif + { + ivas_omasa_preProcessStereoTransportsForEditedObjects_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, &q_inp, nBins, subframe ); + } + +#else IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( nchan_transport, 2 ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) { /* Un-tested function. No test-case is hitting.*/ ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, &q_inp, nBins, subframe ); } +#endif IF( hCombinedOrientationData ) { @@ -1296,7 +1311,7 @@ static void ivas_dirac_dec_decorrelate_slot_fx( } } - *q_out = q_decorrelatedFrameInterleaved; + *q_out = q_decorrelatedFrameInterleaved; // q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame // return; } @@ -1706,6 +1721,15 @@ static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( UWord16 ismDirIndex; ismDirIndex = sub( dirIndex, hSpatParamRendCom->numParametricDirections ); assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" ); +#ifdef OMASA_OBJECT_EDITING + IF( hMasaIsmData->ism_dir_is_edited[ismDirIndex] ) + { + aziDeg = hMasaIsmData->azimuth_ism_edited_fx[ismDirIndex]; + move16(); + eleDeg = hMasaIsmData->elevation_ism_edited_fx[ismDirIndex]; + move16(); + } +#else IF( hMasaIsmData->ism_is_edited[ismDirIndex] ) { aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex]; @@ -1713,11 +1737,12 @@ static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex]; move16(); } +#endif ELSE { - aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx]; + aziDeg = hMasaIsmData->azimuth_ism_fx[ismDirIndex][dirac_read_idx]; move16(); - eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx]; + eleDeg = hMasaIsmData->elevation_ism_fx[ismDirIndex][dirac_read_idx]; move16(); } ratio_fx = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin]; @@ -2567,17 +2592,52 @@ static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( { IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) ) { +#ifdef OMASA_OBJECT_EDITING + IF( hMasaIsmData->ism_dir_is_edited[chB] ) + { + aziDeg = hMasaIsmData->azimuth_ism_edited_fx[chB]; + move16(); + eleDeg = hMasaIsmData->elevation_ism_edited_fx[chB]; + move16(); + } + ELSE + { + aziDeg = hMasaIsmData->azimuth_ism_fx[chB][dirac_read_idx]; + move16(); + eleDeg = hMasaIsmData->elevation_ism_fx[chB][dirac_read_idx]; + move16(); + } +#else aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx]; move16(); eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx]; move16(); +#endif } ELSE { +#ifdef OMASA_OBJECT_EDITING + test(); + IF( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hMasaIsmData->ism_dir_is_edited[hMasaIsmData->idx_separated_ism] ) + { + aziDeg = hMasaIsmData->azimuth_ism_edited_fx[hMasaIsmData->idx_separated_ism]; + move16(); + eleDeg = hMasaIsmData->elevation_ism_edited_fx[hMasaIsmData->idx_separated_ism]; + move16(); + } + ELSE + { + aziDeg = hMasaIsmData->azimuth_separated_ism_fx[dirac_read_idx]; + move16(); + eleDeg = hMasaIsmData->elevation_separated_ism_fx[dirac_read_idx]; + move16(); + } +#else aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx]; move16(); eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx]; move16(); +#endif instantChange = 1; move16(); } @@ -4899,6 +4959,139 @@ static void getDirectPartGains_fx( IF( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */ { +#ifdef OMASA_OBJECT_EDITING + *lImagp = 0; + *rImagp = 0; + move32(); + move32(); + + test(); + IF( EQ_16( aziDeg, gainCache->azi ) && EQ_16( eleDeg, gainCache->ele ) ) + { + *lRealp = gainCache->shVec_fx[0]; /* Reused memory */ + *rRealp = gainCache->shVec_fx[1]; /* Reused memory */ + move32(); + move32(); + } + ELSE + { + /* Convert azi and ele to an azi value of the cone of confusion */ + + // y = ( sinf( aziRad ) * cosf( eleRad ) ); + + IF( GT_16( abs_s( eleDeg ), 180 ) ) + { + // cos(180 + x) = -cos(x) + cos_val = -ptr_cos[sub( abs_s( eleDeg ), 180 )]; // Q31 + } + ELSE + { + cos_val = ptr_cos[abs_s( eleDeg )]; // Q31 + } + move32(); + + IF( GT_16( aziDeg, 180 ) ) + { + // sin(180 + x) = -sin(x) + sin_val = -ptr_sin[sub( aziDeg, 180 )]; // Q31 + } + ELSE IF( LT_16( aziDeg, -180 ) ) + { + // sin(-(180 + x)) = sin(180 + x) = sinx + sin_val = ptr_sin[sub( abs_s( aziDeg ), 180 )]; // Q31 + } + ELSE + { + sin_val = ptr_sin[aziDeg]; // Q31 + } + move32(); + + y = Mpy_32_32( sin_val, cos_val ); // Q31 + e_mappedX = 0; + move16(); + mappedX = Sqrt32( L_max( 0, L_sub( ONE_IN_Q31, Mpy_32_32( y, y ) ) ), &e_mappedX ); + + aziRadMapped = BASOP_util_atan2( y, mappedX, negate( e_mappedX ) ); // Q13 + + /* Determine the real valued amplitude panning gains */ + move32(); + move32(); + IF( GE_16( aziRadMapped, shr( LsAngleRad, 2 ) ) ) + { /* Left side */ + *lRealp = ONE_IN_Q31; + *rRealp = 0; + move32(); + move32(); + } + ELSE IF( LE_16( aziRadMapped, negate( shr( LsAngleRad, 2 ) ) ) ) + { /* Right side */ + *lRealp = 0; + *rRealp = ONE_IN_Q31; + move32(); + move32(); + } + ELSE /* Tangent panning law */ + { + Word16 e_div, div, e_a, e_a3, temp_16_1, temp_16_2, e_num, e_den; + div = BASOP_Util_Divide3232_Scale( y, mappedX, &e_div ); + e_div = sub( e_div, e_mappedX ); + + A = mult( div, INV_TAN30_FX ); + e_a = add( e_div, 1 ); + + e_num = BASOP_Util_Add_MantExp( A, e_a, -32767, 0, &temp_16_1 ); + e_den = BASOP_Util_Add_MantExp( A, e_a, 32767, 0, &temp_16_2 ); + IF( temp_16_2 <= 0 ) + { + temp_16_2 = 32; + e_den = 0; + move16(); + move16(); + } + A2 = BASOP_Util_Divide1616_Scale( temp_16_1, temp_16_2, &e_div ); + e_div = add( e_div, sub( e_num, e_den ) ); + + e_den = BASOP_Util_Add_MantExp( mult( A2, A2 ), add( e_div, e_div ), 32767, 0, &temp_16_2 ); + A3 = BASOP_Util_Divide1616_Scale( 32767, temp_16_2, &e_a3 ); + e_a3 = sub( e_a3, e_den ); + // A3 = 1.0f / ( A2 * A2 + 1.0f ); // Q15 + Word32 temp_32 = L_shr( L_deposit_h( A3 ), sub( 0, e_a3 ) ); + Word16 temp_e = 0; + e_a3 = 0; + move16(); + move16(); + *lRealp = Sqrt32( temp_32, &e_a3 ); + *rRealp = Sqrt32( L_sub( ONE_IN_Q31, temp_32 ), &temp_e ); + *lRealp = L_shr( *lRealp, sub( 0, e_a3 ) ); // Q31 + *rRealp = L_shr( *rRealp, sub( 0, temp_e ) ); // Q31 + move32(); + move32(); + move32(); + move32(); + } + + /* Scaling to have the same expected gain as for the HRTF rendering */ + *lRealp = Mpy_32_32( *lRealp, SQRT2_FX ); // Q30 + *rRealp = Mpy_32_32( *rRealp, SQRT2_FX ); // Q30 + + *lRealp = L_shr( *lRealp, 2 ); // Q28 + *rRealp = L_shr( *rRealp, 2 ); // Q28 + move32(); + move32(); + move32(); + move32(); + + /* Store to gain cache */ + gainCache->azi = aziDeg; + gainCache->ele = eleDeg; + gainCache->shVec_fx[0] = *lRealp; /* Reuse memory */ + gainCache->shVec_fx[1] = *rRealp; /* Reuse memory */ + move16(); + move16(); + move32(); + move32(); + } +#else /* Convert azi and ele to an azi value of the cone of confusion */ // y = ( sinf( aziRad ) * cosf( eleRad ) ); @@ -5006,6 +5199,7 @@ static void getDirectPartGains_fx( move32(); move32(); move32(); +#endif } ELSE /* In regular binaural rendering mode */ { @@ -5185,29 +5379,57 @@ Word16 configure_reqularization_factor_fx( return reqularizationFactor; } +#ifdef OMASA_OBJECT_EDITING /*-------------------------------------------------------------------* - * ivas_omasa_preProcessStereoTransportsForMovedObjects_fx() + * ivas_omasa_preProcessStereoTransportsForEditedObjects() * * *-------------------------------------------------------------------*/ -void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( +void ivas_omasa_preProcessStereoTransportsForEditedObjects_fx( Decoder_Struct *st_ivas, - Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ - Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 *cldfb_buf_q, const Word16 nBins, const Word16 subframe ) { - Word16 bin, ch, inCh, outCh, ismDirIndex, slot; + Word16 bin, ch, inCh, outCh, ismDirIndex, slot, band_idx, bin_lo, bin_hi, max_band, n_ism; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; MASA_ISM_DATA_HANDLE hMasaIsmData; +#ifdef OBJ_EDITING_PARAMISM_BIN + PARAM_ISM_DEC_HANDLE hParamIsmDec; +#endif UWord8 enableCentering; Word16 dirac_read_idx; Word16 nSlots; + Word16 panGainsOut[4][2]; + Word16 panGainsIn[4][2]; + Word16 panEnesOut[4][2]; + Word16 panEnesIn[4][2]; + UWord8 ismGainEdited[4]; + UWord8 ismDirEdited[4]; + UWord8 masaGainEdited; +#ifdef OBJ_EDITING_PARAMISM_BIN + UWord8 masaIsmMode; +#endif hSpatParamRendCom = st_ivas->hSpatParamRendCom; hMasaIsmData = st_ivas->hMasaIsmData; +#ifdef OBJ_EDITING_PARAMISM_BIN + hParamIsmDec = st_ivas->hParamIsmDec; + + IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + masaIsmMode = 1; + move16(); + } + ELSE + { + masaIsmMode = 0; + move16(); + } +#endif test(); test(); @@ -5222,95 +5444,1294 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( move16(); } - /* Bypass processing until first object is moved */ - IF( hMasaIsmData->objectsMoved == 0 ) +#ifdef OBJ_EDITING_PARAMISM_BIN + test(); + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ivas_format, ISM_FORMAT ) ) +#else + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) +#endif { - FOR( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ ) + n_ism = st_ivas->nchan_ism; + move16(); + } + ELSE + { + n_ism = hSpatParamRendCom->numIsmDirections; + move16(); + } + + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) + { + ismGainEdited[ismDirIndex] = hMasaIsmData->ism_gain_is_edited[ismDirIndex]; + move16(); + ismDirEdited[ismDirIndex] = hMasaIsmData->ism_dir_is_edited[ismDirIndex]; + move16(); + } + masaGainEdited = hMasaIsmData->masa_gain_is_edited; + move16(); + + /* Bypass processing until first object is moved or gained */ + IF( EQ_32( hMasaIsmData->objectsEdited, 0 ) ) + { + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) { - if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) + IF( ismDirEdited[ismDirIndex] ) { - hMasaIsmData->objectsMoved = 1; + hMasaIsmData->objectsEdited = 1; + move16(); + } + + IF( ismGainEdited[ismDirIndex] ) + { + hMasaIsmData->objectsEdited = 1; move16(); } } - IF( hMasaIsmData->objectsMoved == 0 ) + + IF( masaGainEdited ) + { + hMasaIsmData->objectsEdited = 1; + move16(); + } + + IF( EQ_32( hMasaIsmData->objectsEdited, 0 ) ) { /* No objects have moved so far */ return; } } - /* Perform object-movement based processing */ - nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; - move16(); - dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; - move16(); + /* OMASA gaining for discrete OMASA mode with stereo_param/bin_room_param renderer */ + test(); + test(); + test(); + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + /* ISM gaining */ + FOR( ch = 0; ch < n_ism; ch++ ) + { + IF( st_ivas->hMasaIsmData->ism_gain_is_edited[ch] ) + { + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + { + Word16 gain; + gain = st_ivas->hMasaIsmData->gain_ism_edited_fx[ch]; + move32(); - FOR( bin = 0; bin < nBins; bin++ ) + v_multc_fx_16( inRe_fx[ch + 2][slot], gain, inRe_fx[ch + 2][slot], nBins ); // Q = *cldfb_buf_q - 3 + Scale_sig32( inRe_fx[ch + 2][slot], nBins, Q3 ); // Q = *cldfb_buf_q + + v_multc_fx_16( inIm_fx[ch + 2][slot], gain, inIm_fx[ch + 2][slot], nBins ); // Q = *cldfb_buf_q - 3 + Scale_sig32( inIm_fx[ch + 2][slot], nBins, Q3 ); // Q = *cldfb_buf_q + } + } + } + + /* MASA gaining */ + FOR( ch = 0; ch < 2; ch++ ) + { + IF( masaGainEdited ) + { + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + { + Word16 gain_masa; + gain_masa = st_ivas->hMasaIsmData->gain_masa_edited_fx; + move32(); + + v_multc_fx_16( inRe_fx[ch][slot], gain_masa, inRe_fx[ch][slot], nBins ); // Q = *cldfb_buf_q - 3 + Scale_sig32( inRe_fx[ch][slot], nBins, Q3 ); // Q = *cldfb_buf_q + + v_multc_fx_16( inIm_fx[ch][slot], gain_masa, inIm_fx[ch][slot], nBins ); // Q = *cldfb_buf_q - 3 + Scale_sig32( inIm_fx[ch][slot], nBins, Q3 ); // Q = *cldfb_buf_q + } + } + } + } +#ifdef OBJ_EDITING_PARAMISM_BIN + ELSE IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && st_ivas->hISMDTX.dtx_flag ) /* If dtx on, perform just the smoothing of the processing gains */ { - Word16 ismPreprocMtxNew_fx[2][2]; - Word16 ismPreprocMtxIncrement_fx[2][2]; - Word16 eneMove_fx[2]; - Word16 enePreserve_fx[2]; - Word16 ismRatioAcc_fx; - Word32 subframeEne_fx; - Word32 Enes_fx[2]; - Word16 normEnes_fx[2]; - Word16 remainderNormEne_fx; - Word16 normEnes_q_fx[2], temp_q = 0; - Word16 eneMove_q_fx[2], enePreserve_q_fx[2], temp1; + Word32 totalTargetEne; + Word32 ismPreprocMtxNew[2][2]; + Word32 ismPreprocMtxIncrement[2][2]; + Word32 outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 eqVal; Word32 temp; + Word16 temp_q; + Word64 temp64; + Word16 exp1; + Word16 totalTargetEne_e; - set16_fx( ismPreprocMtxNew_fx[0], 0, 2 ); - set16_fx( ismPreprocMtxNew_fx[1], 0, 2 ); - set16_fx( ismPreprocMtxIncrement_fx[0], 0, 2 ); - set16_fx( ismPreprocMtxIncrement_fx[1], 0, 2 ); - set16_fx( eneMove_fx, 0, 2 ); - set16_fx( enePreserve_fx, 0, 2 ); - ismRatioAcc_fx = 0; + nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; move16(); - subframeEne_fx = 0; - move32(); - set16_fx( normEnes_fx, 0, 2 ); - set32_fx( Enes_fx, 0, 2 ); - set16_fx( normEnes_q_fx, Q31, 2 ); - set16_fx( eneMove_q_fx, Q31, 2 ); - set16_fx( enePreserve_q_fx, Q31, 2 ); - /* Determine transport normalized energies and subframe energy */ + /* Use diagonal mixing matrix as the instant mixing matrix, to slowly fade away the editing during dtx */ + FOR( ch = 0; ch < 2; ch++ ) + { + ismPreprocMtxNew[ch][ch] = ONE_IN_Q28; + move32(); + ismPreprocMtxNew[sub( 1, ch )][ch] = 0; + move32(); + } + + /* Determine the highest band */ + max_band = 0; + move16(); + test(); + WHILE( GT_16( sub( MAX_PARAM_ISM_NBANDS, max_band ), 0 ) && GT_16( sub( nBins, hParamIsmDec->hParamIsm->band_grouping[max_band] ), 0 ) ) + { + max_band++; + } + + /* Init out array */ FOR( slot = 0; slot < nSlots; slot++ ) { - FOR( ch = 0; ch < 2; ch++ ) + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 - move32(); - Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 - move32(); + set32_fx( outSlotRe[ch][slot], 0, CLDFB_NO_CHANNELS_MAX ); + set32_fx( outSlotIm[ch][slot], 0, CLDFB_NO_CHANNELS_MAX ); } + } - subframeEne_fx = L_add( Enes_fx[0], Enes_fx[1] ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 + // /* Perform the processing in frequency bands */ + FOR( band_idx = 0; band_idx < max_band; band_idx++ ) + { + bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx]; + bin_hi = s_min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins ); + move16(); + move16(); - IF( subframeEne_fx != 0 ) + /* Determine transport energies */ + totalTargetEne = 0; + totalTargetEne_e = 0; + move32(); + move16(); + FOR( slot = 0; slot < nSlots; slot++ ) { - normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], subframeEne_fx, &temp_q ); - move32(); - normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12 - move32(); - normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], subframeEne_fx, &temp_q ); - move32(); - normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12 - move32(); + FOR( ch = 0; ch < 2; ch++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + + Word32 instEne_fx; + temp64 = W_mult0_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ); // 2q-3 + temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // 2q-3 + exp1 = W_norm( temp64 ); + instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2*cldfb_buf_q - 32 + exp1 + exp1 = 31 - ( 2 * ( *cldfb_buf_q ) - 32 + exp1 ); + move16(); + + BASOP_Util_Add_Mant32Exp( totalTargetEne, totalTargetEne_e, instEne_fx, exp1, &totalTargetEne_e ); + } + } } - ELSE + + /* Get increment value for temporal interpolation */ + FOR( inCh = 0; inCh < 2; inCh++ ) { - normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], EPSILON_FX, &temp_q ); - move32(); - normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12 - move32(); - normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], EPSILON_FX, &temp_q ); - move32(); - normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12 - move32(); + FOR( outCh = 0; outCh < 2; outCh++ ) + { + temp = L_sub( ismPreprocMtxNew[outCh][inCh], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] ); // Q28 + ismPreprocMtxIncrement[outCh][inCh] = L_shr( temp, 2 ); // Divide by 4 + move32(); + } + } + + /* Mix signals */ + hMasaIsmData->preprocEneTarget_fx[band_idx] = Mpy_32_16_1( hMasaIsmData->preprocEneTarget_fx[band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = preprocEneTarget_e + move32(); + + hMasaIsmData->preprocEneRealized_fx[band_idx] = Mpy_32_16_1( hMasaIsmData->preprocEneRealized_fx[band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = preprocEneRealized_e + move32(); + + hMasaIsmData->preprocEneTarget_fx[band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->preprocEneTarget_fx[band_idx], hMasaIsmData->preprocEneTarget_e[band_idx], totalTargetEne, totalTargetEne_e, &hMasaIsmData->preprocEneTarget_e[band_idx] ); // Q = 31-preprocEneTarget_e + move32(); + + FOR( outCh = 0; outCh < 2; outCh++ ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( inCh = 0; inCh < 2; inCh++ ) + { + hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] = L_add( hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx], ismPreprocMtxIncrement[outCh][inCh] ); // Q28 + + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + temp = Mpy_32_32( inRe_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] ); // Q = q_cldfb* + 28 - 31 = q_cldfb - 3 + outSlotRe[outCh][slot][bin] = L_add( outSlotRe[outCh][slot][bin], L_shl( temp, 3 ) ); // Q = q_cldfb* + move32(); + + temp = Mpy_32_32( inIm_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] ); // Q = q_cldfb* + 28 - 31 = q_cldfb*-3 + outSlotIm[outCh][slot][bin] = L_add( outSlotIm[outCh][slot][bin], L_shl( temp, 3 ) ); // Q = q_cldfb* + move32(); + } + } + + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + Word32 instEne_fx; + temp64 = W_mult0_32_32( outSlotRe[outCh][slot][bin], outSlotRe[outCh][slot][bin] ); // 2q-3 + temp64 = W_add( temp64, W_mult0_32_32( outSlotIm[outCh][slot][bin], outSlotIm[outCh][slot][bin] ) ); // 2q-3 + exp1 = W_norm( temp64 ); + instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2*cldfb_buf_q - 32 + exp1 + exp1 = 31 - ( 2 * ( *cldfb_buf_q ) - 32 + exp1 ); + move16(); + + hMasaIsmData->preprocEneRealized_fx[band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->preprocEneRealized_fx[band_idx], hMasaIsmData->preprocEneRealized_e[band_idx], instEne_fx, exp1, &hMasaIsmData->preprocEneRealized_e[band_idx] ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19); + move32(); + } + } + } + + test(); + IF( hMasaIsmData->preprocEneTarget_fx[band_idx] > 0 && hMasaIsmData->preprocEneRealized_fx[band_idx] > 0 ) + { + temp = BASOP_Util_Divide3232_Scale_newton( hMasaIsmData->preprocEneTarget_fx[band_idx], L_max( 1, hMasaIsmData->preprocEneRealized_fx[band_idx] ), &temp_q ); + temp_q = sub( Q31, sub( sub( Q31, temp_q ), sub( hMasaIsmData->preprocEneTarget_e[band_idx], hMasaIsmData->preprocEneRealized_e[band_idx] ) ) ); + temp = Sqrt32( temp, &temp_q ); // Q: 31-temp_q + temp = L_shl( temp, sub( temp_q, 3 ) ); // Q28 + temp_q = Q28; + move32(); + } + ELSE + { + temp = 0; + move32(); + } + + IF( GT_32( ONE_IN_Q30, temp ) ) + { + eqVal = temp; + move32(); + } + ELSE + { + eqVal = ONE_IN_Q30; // 4 in Q28 + move32(); + } + + FOR( ch = 0; ch < 2; ch++ ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + temp = Mpy_32_32( outSlotRe[ch][slot][bin], eqVal ); // Q = (cldfb_q) + 28 -31 = cldfb_q - 3 + inRe_fx[ch][slot][bin] = L_shl( temp, 3 ); + move32(); + + temp = Mpy_32_32( outSlotIm[ch][slot][bin], eqVal ); // Q = (cldfb_q) + 28 -31 = cldfb_q - 3 + inIm_fx[ch][slot][bin] = L_shl( temp, 3 ); + move32(); + } + } + } + } + } +#endif + ELSE /* Other processing modes */ + { + Word32 subframeEne; + Word32 subframeEneCh[2]; + Word32 normEnes[2]; + Word32 ratioAccOrig; + Word32 ratioAccNew; + Word32 ratio; + Word32 ismEneThis; + Word32 ismTargetEneThis; + Word32 ismTargetEneThisCh[2]; + Word32 totalTargetEneCh[2]; + Word32 totalTargetEne; + Word32 masaTargetEneThisCh[2]; + Word32 ismPreprocMtxNew[2][2]; + Word16 ismPreprocMtxNew_e[2][2]; + Word32 ismPreprocMtxIncrement[2][2]; + Word16 ismPreprocMtxIncrement_e[2][2]; + Word32 eneMove[2]; + Word32 enePreserve[2]; + Word32 ismRatioAcc; + Word32 remainderNormEne; + Word16 centeringFactor; + Word16 eneMoveThis; + Word16 enePreserveThis; + Word32 normVal; + Word32 eqVal; + Word32 outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 newRatios[6]; + Word16 gainIsmThis; + Word16 gainMasaPow2; + Word32 tempDivisor; + Word32 masaEneThisCh[2]; + Word32 ratioAccNewDivisor; + Word32 temp; + Word16 temp_q = 0; + Word16 temp1; + Word64 temp64; + Word16 norm, shift = 31; + Word16 exp, exp1; + Word16 subframeEneCh_e[2]; + Word16 subframeEneCh_Q[2]; + Word16 subQ = 0; + move16(); + move16(); + move16(); + + set16_fx( subframeEneCh_e, 0, 2 ); + temp = 0; + move32(); + + gainMasaPow2 = ONE_IN_Q9; + move16(); + IF( masaGainEdited ) + { + gainMasaPow2 = hMasaIsmData->gain_masa_edited_fx; // Q12 + move16(); + gainMasaPow2 = mult( gainMasaPow2, gainMasaPow2 ); // Q = 12 + 12 - 15 = 9 + move16(); + } + + nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + move16(); + dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + move16(); + + /* Determine panning gains and energies for each object */ + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) + { + /* Get input and output panning gains */ + ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism_fx[ismDirIndex][dirac_read_idx], + hMasaIsmData->elevation_ism_fx[ismDirIndex][dirac_read_idx], + panGainsIn[ismDirIndex] ); // Q15 + + IF( ismDirEdited[ismDirIndex] ) + { + ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism_edited_fx[ismDirIndex], + hMasaIsmData->elevation_ism_edited_fx[ismDirIndex], + panGainsOut[ismDirIndex] ); // Q15 + } + ELSE + { + /* When not edited, input and output pan gains are the same */ + FOR( ch = 0; ch < 2; ch++ ) + { + panGainsOut[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch]; + move16(); + } + } + + /* Determine pan enes */ + FOR( ch = 0; ch < 2; ch++ ) + { + panEnesOut[ismDirIndex][ch] = mult( panGainsOut[ismDirIndex][ch], panGainsOut[ismDirIndex][ch] ); // Q15 + move16(); + panEnesIn[ismDirIndex][ch] = mult( panGainsIn[ismDirIndex][ch], panGainsIn[ismDirIndex][ch] ); // Q15 + move16(); + } + } + + /* Determine the highest band */ + max_band = 0; + move16(); +#ifdef OBJ_EDITING_PARAMISM_BIN + IF( masaIsmMode ) + { +#endif + test(); + WHILE( GT_16( sub( MASA_FREQUENCY_BANDS, max_band ), 0 ) && GT_16( sub( nBins, MASA_band_grouping_24[max_band] ), 0 ) ) + { + max_band++; + } +#ifdef OBJ_EDITING_PARAMISM_BIN + } + ELSE + { + test(); + WHILE( GT_16( sub( MAX_PARAM_ISM_NBANDS, max_band ), 0 ) && GT_16( sub( nBins, hParamIsmDec->hParamIsm->band_grouping[max_band] ), 0 ) ) + { + max_band++; + } + } +#endif + + /* Init out array */ + FOR( Word16 k = 0; k < nSlots; k++ ) + { + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + set_zero_fx( outSlotRe[ch][k], CLDFB_NO_CHANNELS_MAX ); + set_zero_fx( outSlotIm[ch][k], CLDFB_NO_CHANNELS_MAX ); + + norm = s_min( L_norm_arr( inRe_fx[ch][k], nBins ), L_norm_arr( inIm_fx[ch][k], nBins ) ); + shift = s_min( norm, shift ); + } + } + + + /* Perform the processing in frequency bands */ + FOR( band_idx = 0; band_idx < max_band; band_idx++ ) + { + ratioAccOrig = 0; + move32(); + ratioAccNew = 0; + move32(); + ismRatioAcc = 0; + move32(); + + set32_fx( eneMove, 0, 2 ); + set32_fx( enePreserve, 0, 2 ); + set32_fx( subframeEneCh, 0, 2 ); + set32_fx( normEnes, 0, 2 ); + set32_fx( ismTargetEneThisCh, 0, 2 ); + set32_fx( totalTargetEneCh, 0, 2 ); + set32_fx( masaTargetEneThisCh, 0, 2 ); + set32_fx( ismPreprocMtxNew[0], 0, 2 ); + set32_fx( ismPreprocMtxNew[1], 0, 2 ); + set16_fx( ismPreprocMtxNew_e[0], 0, 2 ); + set16_fx( ismPreprocMtxNew_e[1], 0, 2 ); + set32_fx( ismPreprocMtxIncrement[0], 0, 2 ); + set32_fx( ismPreprocMtxIncrement[1], 0, 2 ); + set16_fx( ismPreprocMtxIncrement_e[1], 0, 2 ); + set16_fx( ismPreprocMtxIncrement_e[1], 0, 2 ); + +#ifdef OBJ_EDITING_PARAMISM_BIN + IF( masaIsmMode ) + { +#endif + bin_lo = MASA_band_grouping_24[band_idx]; + move16(); + bin_hi = s_min( MASA_band_grouping_24[band_idx + 1], nBins ); + move16(); +#ifdef OBJ_EDITING_PARAMISM_BIN + } + ELSE + { + bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx]; + move16(); + bin_hi = s_min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins ); + move16(); + } +#endif + + exp = sub( 63, shl( *cldfb_buf_q, 1 ) ); + Word16 guardBits = 5; + move16(); + + /* Determine transport normalized energies and subframe energy */ + FOR( ch = 0; ch < 2; ch++ ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + + Word32 instEne_fx; + temp64 = W_mult0_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ); // 2q + temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // 2q + exp1 = W_norm( temp64 ); + instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2*cldfb_buf_q - 32 + exp1 + /* exp of instEne_fx = 31 - (2q -32 + exp1) = 63 - 2q - exp1 = exp - exp1*/ + + subframeEneCh[ch] = BASOP_Util_Add_Mant32Exp( subframeEneCh[ch], subframeEneCh_e[ch], instEne_fx, sub( exp, exp1 ), &subframeEneCh_e[ch] ); + subframeEneCh_Q[ch] = 31 - subframeEneCh_e[ch]; + move32(); + move32(); + } + } + } + + // Align subframeEneCh Q values, shift 1 bit right to avoid overflow from sum + IF( EQ_32( subframeEneCh_Q[0], subframeEneCh_Q[1] ) ) + { + subframeEneCh[0] = L_shr( subframeEneCh[0], 1 ); + subframeEneCh[1] = L_shr( subframeEneCh[1], 1 ); + subframeEne = L_add( subframeEneCh[0], subframeEneCh[1] ); // subQ + subframeEneCh_Q[1] = sub( subframeEneCh_Q[1], 1 ); + subframeEneCh_Q[0] = sub( subframeEneCh_Q[0], 1 ); + subQ = subframeEneCh_Q[0]; + + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + IF( GT_32( subframeEneCh_Q[0], subframeEneCh_Q[1] ) ) + { + temp1 = sub( subframeEneCh_Q[0], subframeEneCh_Q[1] ); + subframeEneCh[0] = L_shr( subframeEneCh[0], temp1 ); + subframeEneCh[0] = L_shr( subframeEneCh[0], 1 ); + subframeEneCh[1] = L_shr( subframeEneCh[1], 1 ); + subframeEne = L_add( subframeEneCh[0], subframeEneCh[1] ); // subQ + subframeEneCh_Q[0] = sub( subframeEneCh_Q[1], 1 ); + subframeEneCh_Q[1] = sub( subframeEneCh_Q[1], 1 ); + subQ = subframeEneCh_Q[1]; + + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + temp1 = sub( subframeEneCh_Q[1], subframeEneCh_Q[0] ); + subframeEneCh[1] = L_shr( subframeEneCh[1], temp1 ); + subframeEneCh[0] = L_shr( subframeEneCh[0], 1 ); + subframeEneCh[1] = L_shr( subframeEneCh[1], 1 ); + + subframeEne = L_add( subframeEneCh[0], subframeEneCh[1] ); + subframeEneCh_Q[1] = sub( subframeEneCh_Q[0], 1 ); + subframeEneCh_Q[0] = sub( subframeEneCh_Q[0], 1 ); + subQ = subframeEneCh_Q[0]; + + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + + /* Shift subframeEnes right by the number of guard bits to avoid overflow */ + subframeEne = L_shr( subframeEne, guardBits ); + subframeEneCh[0] = L_shr( subframeEneCh[0], guardBits ); + subframeEneCh[1] = L_shr( subframeEneCh[1], guardBits ); + + subQ = sub( subQ, guardBits ); + subframeEneCh_Q[0] = sub( subframeEneCh_Q[0], guardBits ); + subframeEneCh_Q[1] = sub( subframeEneCh_Q[1], guardBits ); + + move16(); + move16(); + move16(); + move16(); + + /* Zero check */ + IF( GT_32( subframeEne, 0 ) ) + { + totalTargetEneCh[0] = subframeEneCh[0]; // subQch[0] + move32(); + totalTargetEneCh[1] = subframeEneCh[1]; // subQch[1] + move32(); + masaEneThisCh[0] = subframeEneCh[0]; // subQch[0] + move32(); + masaEneThisCh[1] = subframeEneCh[1]; // subQch[1] + move32(); + } + + /* Gain editing */ + /* For each object, estimate new target energy per channel based on the applied gain */ + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) + { + ratio = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin_lo]; // Q30 + move32(); + + ratioAccOrig = L_add( ratioAccOrig, ratio ); // Q30 + + /* Calculate MASA energy as a residual of original channel energies subtracted with ISM energies */ + FOR( ch = 0; ch < 2; ch++ ) + { + temp = Mpy_32_32( ratio, subframeEne ); // Q = 30 + subEneQ - 31 = subEneQ-1 + temp = Mpy_32_16_1( temp, panEnesIn[ismDirIndex][ch] ); // Q = subEneQ-1 + + temp_q = sub( subframeEneCh_Q[ch], sub( subQ, 1 ) ); + masaEneThisCh[ch] = L_sub( masaEneThisCh[ch], L_shl( temp, temp_q ) ); // Q = subframeEneCh_Q + move32(); + } + + /* Calculate target energy, gained ratio for accumulation, and transports gains, if ism gain is edited */ + IF( ismGainEdited[ismDirIndex] ) + { + gainIsmThis = hMasaIsmData->gain_ism_edited_fx[ismDirIndex]; // Q12 + move16(); + + /* ISM original energy */ + ismEneThis = Mpy_32_32( ratio, subframeEne ); // Q = 30 + subEneQ - 31 = subQ-1 + move32(); + + /* ISM target energy */ + temp1 = shl_sat( mult( gainIsmThis, gainIsmThis ), 2 ); // Q = 12 + 12 - 15 + 2 = 11 + ismTargetEneThis = Mpy_32_16_1( ismEneThis, temp1 ); // Q = (subQ-1) + 11 - 15 = subQ-5 + move32(); + + ratio = L_shl( Mpy_32_16_1( ratio, temp1 ), 1 ); // Q = 30 + 11 - 15 + 1 = 27 + move32(); + + + /* Determine panning energies and channel target energies */ + FOR( ch = 0; ch < 2; ch++ ) + { + /* Ism target energy per channel */ + ismTargetEneThisCh[ch] = Mpy_32_16_1( ismTargetEneThis, panEnesIn[ismDirIndex][ch] ); // Q = subQ-5 + 15 + 1 - 16 = subQ-5 + move32(); + + /* Reduce original ism energy */ + temp = Mpy_32_16_1( ismEneThis, panEnesIn[ismDirIndex][ch] ); // subEneQ-1 + 15 + 1 - 16 = subQ-1 + totalTargetEneCh[ch] = L_sub( totalTargetEneCh[ch], L_shl( temp, 1 ) ); // subEneQ + move32(); + + /* Add ism target energy per channel */ + totalTargetEneCh[ch] = L_add( totalTargetEneCh[ch], L_shl( ismTargetEneThisCh[ch], 5 ) ); // SubQ + move32(); + } + + + /* If separated ism edited, apply gain directly to the separated ism */ + IF( EQ_16( ismDirIndex, hMasaIsmData->idx_separated_ism ) ) + { + /* Separated object gaining is done elsewhere with DIRAC renderer */ + IF( NE_32( st_ivas->renderer_type, RENDERER_DIRAC ) ) + { + /* Gain transport channel of separated ism */ + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + temp = Mpy_32_16_1( inRe_fx[2][slot][bin], gainIsmThis ); // Q = *cldfb_buf_q + 12 + 1 - 16 = *cldfb_buf_q - 3 + inRe_fx[2][slot][bin] = L_shl( temp, Q3 ); + move32(); + + temp = Mpy_32_16_1( inIm_fx[2][slot][bin], gainIsmThis ); // Q = *cldfb_buf_q + 12 + 1 - 16 = *cldfb_buf_q - 3 + inIm_fx[2][slot][bin] = L_shl( temp, Q3 ); + move32(); + } + } + } + } + ratioAccNew = L_add( ratioAccNew, ratio ); // Q27 + move32(); + } + ELSE + { + ratioAccNew = L_add( ratioAccNew, L_shr( ratio, 3 ) ); // Q27 + move32(); + } + } + +#ifdef OBJ_EDITING_PARAMISM_BIN + IF( masaIsmMode ) + { +#endif + /* MASA original ratios */ + ratio = L_add( hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin_lo], hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin_lo] ); // Q30 + move32(); + ratioAccOrig = L_add( ratioAccOrig, ratio ); // Q30 + move32(); + + /* Estimate MASA original energies and determine adjusted target energies and gained ratio for accumulation, if a gain is applied to MASA */ + IF( masaGainEdited ) + { + /* Gained MASA ratio */ + ratio = L_shl( Mpy_32_16_1( ratio, gainMasaPow2 ), 3 ); // Q = 30 + 9 - 15 + 3 = 27 + move32(); + + + /* Calculate MASA target energies and add to total target energy estimation */ + FOR( ch = 0; ch < 2; ch++ ) + { + /* MASA original energy per channel */ + masaEneThisCh[ch] = L_max( masaEneThisCh[ch], 0 ); // Q5 + move32(); + + /* MASA target energy per channel */ + temp = Mpy_32_16_1( masaEneThisCh[ch], shl( gainMasaPow2, 2 ) ); // Q = SubQ + 11 + 1 - 16 = SubQ-4 + masaTargetEneThisCh[ch] = L_shl( temp, 4 ); // SubQ + move32(); + + /* Reduce original energy per channel */ + totalTargetEneCh[ch] = L_sub( totalTargetEneCh[ch], masaEneThisCh[ch] ); // SubQ + move32(); + + /* Add target energy per channel */ + totalTargetEneCh[ch] = L_add( totalTargetEneCh[ch], masaTargetEneThisCh[ch] ); // SubQ + move32(); + } + ratioAccNew = L_add( ratioAccNew, ratio ); // Q27 + } + ELSE + { + ratioAccNew = L_add( ratioAccNew, L_shr( ratio, 3 ) ); // Q27 + } + +#ifdef OBJ_EDITING_PARAMISM_BIN + } +#endif + + +#ifdef NONBE_1399_1400_FIX_OBJ_EDIT_ISSUES + /* Limit target energies to non-negative values */ + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + totalTargetEneCh[ch] = L_max( 0, totalTargetEneCh[ch] ); + } +#endif + + /* due to rounding, the sum may exceed 1.0f ever so slightly, so clip it */ + ratioAccOrig = L_min( ratioAccOrig, ONE_IN_Q30 ); + move32(); + IF( masaGainEdited ) + { + temp = Mpy_32_16_1( L_sub( ONE_IN_Q30, ratioAccOrig ), gainMasaPow2 ); // Q = 30 + 9 + 1 - 16 = 24 + ratioAccNew = L_add_sat( ratioAccNew, L_shl_sat( temp, 3 ) ); // Q27 + move32(); + } + ELSE + { + ratioAccNew = L_add( ratioAccNew, L_shr( L_sub( ONE_IN_Q30, ratioAccOrig ), 3 ) ); // Q27 + move32(); + } + + + /* New target total energy ratio divider */ + IF( ratioAccNew > 0 ) + { + ratioAccNewDivisor = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q27, ratioAccNew, &temp_q ); + ratioAccNewDivisor = L_shl_sat( ratioAccNewDivisor, sub( temp_q, 4 ) ); // Q27, saturate to 16 in Q27 + + /* Determine and process object energy ratios based on gaining */ + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) + { + newRatios[ismDirIndex + 2] = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin_lo]; // Q30 + move32(); + + IF( ismGainEdited[ismDirIndex] ) + { + gainIsmThis = hMasaIsmData->gain_ism_edited_fx[ismDirIndex]; + move16(); + + /* Gain original object energy ratio, if edited */ + temp1 = mult( gainIsmThis, gainIsmThis ); // Q = 12 + 12 - 15 = 9 + newRatios[ismDirIndex + 2] = Mpy_32_16_1( newRatios[ismDirIndex + 2], temp1 ); // Q = 30 + 9 + 1 - 16 = 24 + move32(); + } + ELSE + { + newRatios[ismDirIndex + 2] = L_shr( newRatios[ismDirIndex + 2], 6 ); + move32(); + } + /* Divide with new target total ratio */ + newRatios[ismDirIndex + 2] = Mpy_32_32( newRatios[ismDirIndex + 2], ratioAccNewDivisor ); // Q = 24 + 27 - 31 = 20 + move32(); + } + + /* Determine and process MASA energy ratios based on gaining */ + newRatios[0] = hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin_lo]; // Q30 + newRatios[1] = hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin_lo]; // Q30 + move32(); + move32(); + + IF( masaGainEdited ) + { + newRatios[0] = Mpy_32_16_1( newRatios[0], gainMasaPow2 ); // Q = 30 + 9 + 1 - 16 = 24 + newRatios[1] = Mpy_32_16_1( newRatios[1], gainMasaPow2 ); // Q = 30 + 9 + 1 - 16 = 24 + move32(); + move32(); + } + ELSE + { + newRatios[0] = L_shr( newRatios[0], 6 ); // Q = 30 + 9 + 1 - 16 = 24 + newRatios[1] = L_shr( newRatios[0], 6 ); + move32(); + move32(); + } + newRatios[0] = Mpy_32_32( newRatios[0], ratioAccNewDivisor ); // Q = 24 + 27 - 31 = 20 + newRatios[1] = Mpy_32_32( newRatios[1], ratioAccNewDivisor ); // Q = 24 + 27 - 31 = 20 + move32(); + move32(); + + /* Set adjusted energy ratios */ + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) + { + hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin] = L_shl( newRatios[ismDirIndex + 2], 10 ); // Q30 + move32(); + } + + IF( masaIsmMode ) + { + hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin] = L_shl( newRatios[0], 10 ); + hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin] = L_shl( newRatios[1], 10 ); + move32(); + move32(); + } + } + } + + + /* Direction editing */ + /* Determine new energetic values after gaining */ + totalTargetEne = L_add( totalTargetEneCh[0], totalTargetEneCh[1] ); // SubQ + + IF( GT_32( totalTargetEne, 0 ) ) + { + tempDivisor = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q28, max( EPSILON_FX, totalTargetEne ), &temp_q ); + + temp_q = sub( sub( Q31, temp_q ), sub( sub( Q31, Q28 ), sub( Q31, subQ ) ) ); + + normEnes[0] = Mpy_32_32( totalTargetEneCh[0], tempDivisor ); // Q = 25 + normEnes[1] = Mpy_32_32( totalTargetEneCh[1], tempDivisor ); // Q = 25 + temp_q = sub( add( subQ, temp_q ), Q31 ); + normEnes[0] = L_shl( normEnes[0], sub( Q25, temp_q ) ); + normEnes[1] = L_shl( normEnes[1], sub( Q25, temp_q ) ); + move32(); + move32(); + move32(); + move32(); + } + ELSE + { + normEnes[0] = 0; + normEnes[1] = 0; + move32(); + move32(); + } + + /* For each ismDir, determine moved and preserve energy ratio per channel */ + FOR( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ ) + { + ratio = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin_lo]; // Q30 + move32(); + + ismRatioAcc = L_add( ismRatioAcc, ratio ); // Q30 + + IF( enableCentering ) + { + temp1 = abs_s( sub( panEnesIn[ismDirIndex][0], panEnesOut[ismDirIndex][0] ) ); // 2*sub(enes) -> Q14 + centeringFactor = max( 0, sub( temp1, ONE_IN_Q14 ) ); // Q14 + + FOR( ch = 0; ch < 2; ch++ ) + { + temp1 = sub( ONE_IN_Q14, centeringFactor ); + panEnesOut[ismDirIndex][ch] = mult( panEnesOut[ismDirIndex][ch], temp1 ); // Q = 15 + 14 - 15 = 14 + move16(); + + temp1 = shr( centeringFactor, 1 ); // * 0.5f = Divide by 2 + panEnesOut[ismDirIndex][ch] = add( panEnesOut[ismDirIndex][ch], temp1 ); // Q14 + panEnesOut[ismDirIndex][ch] = shl( panEnesOut[ismDirIndex][ch], 1 ); // Q15 + move16(); + move16(); + } + } + + FOR( ch = 0; ch < 2; ch++ ) + { + eneMoveThis = s_max( 0, sub( panEnesIn[ismDirIndex][ch], panEnesOut[ismDirIndex][ch] ) ); // Q15 + move16(); + + enePreserveThis = sub( panEnesIn[ismDirIndex][ch], eneMoveThis ); // Q15 + move16(); + + temp = Mpy_32_16_1( ratio, eneMoveThis ); // Q = 30 + 15 + 1 - 16 = 30 + eneMove[ch] = L_add( eneMove[ch], temp ); // Q30 + move32(); + + temp = Mpy_32_16_1( ratio, enePreserveThis ); // Q = 30 + 15 + 1 - 16 = 30 + enePreserve[ch] = L_add( enePreserve[ch], temp ); // 30 + move32(); + + /* Subtract object parts from normEnes */ + temp = Mpy_32_16_1( L_shr( ratio, 5 ), panEnesIn[ismDirIndex][ch] ); // Q = 25 + 15 + 1 = 16 = 25; + normEnes[ch] = L_sub( normEnes[ch], temp ); // Q25 + move32(); + } + } + + /* Any remaining (non-object) energy is set to be preserved at both channels */ + temp = L_sub( ONE_IN_Q25, L_shr( ismRatioAcc, 5 ) ); + temp = L_sub( temp, normEnes[0] ); + temp = L_sub( temp, normEnes[1] ); + remainderNormEne = L_max( 0, temp ); // Q25 + + /* Normalize */ + FOR( ch = 0; ch < 2; ch++ ) + { + temp = L_shr( remainderNormEne, 1 ); // Division by 2, Q25 + temp = L_add( normEnes[ch], temp ); // Q25 + enePreserve[ch] = L_add( L_shr( enePreserve[ch], 5 ), L_max( 0, temp ) ); // Q25 + + temp = L_add( L_shr( eneMove[ch], 5 ), enePreserve[ch] ); // Q25 + temp = L_max( EPSILON_FX, temp ); + normVal = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q25, temp, &temp_q ); + normVal = L_shl_sat( normVal, sub( temp_q, 6 ) ); // Q25 + + temp = L_max( EPSILON_FX, subframeEneCh[ch] ); // SubQ + temp = BASOP_Util_Divide3232_Scale_newton( totalTargetEneCh[ch], temp, &temp_q ); + temp = L_shl_sat( temp, sub( temp_q, 6 ) ); // Q25 + normVal = Mpy_32_32( normVal, L_min( 335544320, temp ) ); // Q = 25 + 25 + 1 - 32 = 19 + + eneMove[ch] = Mpy_32_32( eneMove[ch], normVal ); // Q = 30 + 19 + 1 - 32 = 18 + move32(); + + enePreserve[ch] = Mpy_32_32( L_shl_sat( enePreserve[ch], 5 ), normVal ); // Q = 30 + 19 + 1 - 32 = 18 + move32(); + + enePreserve[ch] = L_shl_sat( enePreserve[ch], 8 ); // Q26 + eneMove[ch] = L_shl_sat( eneMove[ch], 8 ); // Q26 + move32(); + move32(); + } + + /* Temporally average target energy */ + hMasaIsmData->eneOrigIIR_fx[band_idx] = Mpy_32_16_1( hMasaIsmData->eneOrigIIR_fx[band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = origIIR_Q + 15 + 1 - 16 = origIIR_Q + hMasaIsmData->eneOrigIIR_fx[band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->eneOrigIIR_fx[band_idx], hMasaIsmData->eneOrigIIR_e[band_idx], totalTargetEne, sub( Q31, subQ ), &hMasaIsmData->eneOrigIIR_e[band_idx] ); + move32(); + move32(); + + /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix for + * gaining objects and moving objects between left and right */ + FOR( ch = 0; ch < 2; ch++ ) + { + hMasaIsmData->eneMoveIIR_fx[ch][band_idx] = Mpy_32_16_1( hMasaIsmData->eneMoveIIR_fx[ch][band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = Enemove_Q + 15 + 1 -16 = Enemove_Q + move32(); + + temp = Mpy_32_32( totalTargetEne, eneMove[ch] ); // Q = SubQ + 26 + 1 - 32 = SubQ-5 + shift = norm_l( temp ); + temp = L_shl( temp, shift ); // Q = subQ-5+shift + hMasaIsmData->eneMoveIIR_fx[ch][band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->eneMoveIIR_fx[ch][band_idx], hMasaIsmData->eneMoveIIR_e[ch][band_idx], temp, sub( Q31, add( sub( subQ, 5 ), shift ) ), &hMasaIsmData->eneMoveIIR_e[ch][band_idx] ); + move32(); + + hMasaIsmData->enePreserveIIR_fx[ch][band_idx] = Mpy_32_16_1( hMasaIsmData->enePreserveIIR_fx[ch][band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = enePreserve_Q + 15 + 1 - 16 = enePreserve_Q = 31- enePreserve_e + move32(); + + temp = Mpy_32_32( totalTargetEne, enePreserve[ch] ); // Q = subQ + 26 + 1 - 32 = subQ-5 + shift = norm_l( temp ); + temp = L_shl( temp, shift ); // Q = subQ-5+shift + hMasaIsmData->enePreserveIIR_fx[ch][band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->enePreserveIIR_fx[ch][band_idx], hMasaIsmData->enePreserveIIR_e[ch][band_idx], temp, sub( Q31, add( sub( subQ, 5 ), shift ) ), &hMasaIsmData->enePreserveIIR_e[ch][band_idx] ); + move32(); + + temp_q = norm_l( hMasaIsmData->enePreserveIIR_fx[ch][band_idx] ); + hMasaIsmData->enePreserveIIR_fx[ch][band_idx] = L_shl( hMasaIsmData->enePreserveIIR_fx[ch][band_idx], temp_q ); + hMasaIsmData->enePreserveIIR_e[ch][band_idx] = sub( hMasaIsmData->enePreserveIIR_e[ch][band_idx], temp_q ); + move32(); + move32(); + + IF( GT_32( hMasaIsmData->enePreserveIIR_fx[ch][band_idx], 0 ) ) + { + temp = BASOP_Util_Divide3232_Scale_newton( hMasaIsmData->enePreserveIIR_fx[ch][band_idx], L_max( 1, hMasaIsmData->eneOrigIIR_fx[band_idx] ), &temp_q ); + temp_q = sub( Q31, sub( sub( Q31, temp_q ), sub( hMasaIsmData->enePreserveIIR_e[ch][band_idx], hMasaIsmData->eneOrigIIR_e[band_idx] ) ) ); + temp = Sqrt32( temp, &temp_q ); // Q = 31-temp_q + temp = L_shl_sat( temp, sub( temp_q, 3 ) ); // Q28 + } + ELSE + { + temp = 0; + move32(); + } + + IF( GT_32( ONE_IN_Q30, temp ) ) + { + ismPreprocMtxNew[ch][ch] = temp; + move32(); + } + ELSE + { + ismPreprocMtxNew[ch][ch] = ONE_IN_Q30; // 4 in Q28 + move32(); + } + + ismPreprocMtxNew_e[ch][ch] = Q28; + move32(); + + temp_q = norm_l( hMasaIsmData->eneMoveIIR_fx[ch][band_idx] ); + hMasaIsmData->eneMoveIIR_fx[ch][band_idx] = L_shl( hMasaIsmData->eneMoveIIR_fx[ch][band_idx], temp_q ); + hMasaIsmData->eneMoveIIR_e[ch][band_idx] = sub( hMasaIsmData->eneMoveIIR_e[ch][band_idx], temp_q ); + move32(); + move16(); + + IF( GT_32( hMasaIsmData->eneMoveIIR_fx[ch][band_idx], 0 ) ) + { + temp = BASOP_Util_Divide3232_Scale_newton( hMasaIsmData->eneMoveIIR_fx[ch][band_idx], L_max( 1, hMasaIsmData->eneOrigIIR_fx[band_idx] ), &temp_q ); + temp_q = sub( Q31, sub( sub( Q31, temp_q ), sub( hMasaIsmData->eneMoveIIR_e[ch][band_idx], hMasaIsmData->eneOrigIIR_e[band_idx] ) ) ); + temp = Sqrt32( temp, &temp_q ); + temp = L_shl_sat( temp, sub( temp_q, 3 ) ); // Q28 + } + ELSE + { + temp = 0; + move32(); + } + + IF( GT_32( ONE_IN_Q30, temp ) ) + { + ismPreprocMtxNew[1 - ch][ch] = temp; + move32(); + } + ELSE + { + ismPreprocMtxNew[1 - ch][ch] = ONE_IN_Q30; // 4 in Q28 + move32(); + } + ismPreprocMtxNew_e[1 - ch][ch] = Q28; // This may be removed + move32(); + } + + /* Get increment value for temporal interpolation */ + FOR( inCh = 0; inCh < 2; inCh++ ) + { + FOR( outCh = 0; outCh < 2; outCh++ ) + { + temp = L_sub( ismPreprocMtxNew[outCh][inCh], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] ); // Q28 + ismPreprocMtxIncrement[outCh][inCh] = L_shr( temp, 2 ); // Divide by 4 + move32(); + } + } + + /* Mix signals */ + hMasaIsmData->preprocEneTarget_fx[band_idx] = Mpy_32_16_1( hMasaIsmData->preprocEneTarget_fx[band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = preprocEneTarget_e + move32(); + + hMasaIsmData->preprocEneRealized_fx[band_idx] = Mpy_32_16_1( hMasaIsmData->preprocEneRealized_fx[band_idx], STEREO_PREPROCESS_IIR_FACTOR_Q15 ); // Q = preprocEneRealized_e + move32(); + + hMasaIsmData->preprocEneTarget_fx[band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->preprocEneTarget_fx[band_idx], hMasaIsmData->preprocEneTarget_e[band_idx], totalTargetEne, sub( Q31, subQ ), &hMasaIsmData->preprocEneTarget_e[band_idx] ); // Q = 31-preprocEneTarget_e + move32(); + + FOR( outCh = 0; outCh < 2; outCh++ ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( inCh = 0; inCh < 2; inCh++ ) + { + hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] = L_add( hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx], ismPreprocMtxIncrement[outCh][inCh] ); // Q28 + move32(); + + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + temp = Mpy_32_32( inRe_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] ); // Q = q_cldfb* + 28 - 31 = q_cldfb - 3 + outSlotRe[outCh][slot][bin] = L_add( outSlotRe[outCh][slot][bin], L_shl( temp, 3 ) ); // Q = q_cldfb* + move32(); + + temp = Mpy_32_32( inIm_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][band_idx] ); // Q = q_cldfb* + 28 - 31 = q_cldfb*-3 + outSlotIm[outCh][slot][bin] = L_add( outSlotIm[outCh][slot][bin], L_shl( temp, 3 ) ); // Q = q_cldfb* + move32(); + } + } + + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + Word32 instEne_fx; + temp64 = W_mult0_32_32( outSlotRe[outCh][slot][bin], outSlotRe[outCh][slot][bin] ); // 2q-3 + temp64 = W_add( temp64, W_mult0_32_32( outSlotIm[outCh][slot][bin], outSlotIm[outCh][slot][bin] ) ); // 2q-3 + exp1 = W_norm( temp64 ); + instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2*cldfb_buf_q - 32 + exp1 + exp1 = 31 - ( 2 * ( *cldfb_buf_q ) - 32 + exp1 ); + + hMasaIsmData->preprocEneRealized_fx[band_idx] = BASOP_Util_Add_Mant32Exp( hMasaIsmData->preprocEneRealized_fx[band_idx], hMasaIsmData->preprocEneRealized_e[band_idx], instEne_fx, exp1, &hMasaIsmData->preprocEneRealized_e[band_idx] ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19); + move32(); + } + } + } + + + test(); + IF( hMasaIsmData->preprocEneTarget_fx[band_idx] > 0 && hMasaIsmData->preprocEneRealized_fx[band_idx] > 0 ) + { + temp = BASOP_Util_Divide3232_Scale_newton( hMasaIsmData->preprocEneTarget_fx[band_idx], L_max( 1, hMasaIsmData->preprocEneRealized_fx[band_idx] ), &temp_q ); + temp_q = sub( Q31, sub( sub( Q31, temp_q ), sub( hMasaIsmData->preprocEneTarget_e[band_idx], hMasaIsmData->preprocEneRealized_e[band_idx] ) ) ); + temp = Sqrt32( temp, &temp_q ); // Q: 31-temp_q + temp = L_shl( temp, sub( temp_q, 3 ) ); // Q28 + temp_q = Q28; + move16(); + } + ELSE + { + temp = 0; + move32(); + } + + IF( GT_32( ONE_IN_Q30, temp ) ) + { + eqVal = temp; + move32(); + } + ELSE + { + eqVal = ONE_IN_Q30; // 4 in Q28 + move32(); + } + + FOR( ch = 0; ch < 2; ch++ ) + { + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + temp = Mpy_32_32( outSlotRe[ch][slot][bin], eqVal ); // Q = (cldfb_q) + 28 -31 = cldfb_q - 3 + inRe_fx[ch][slot][bin] = L_shl_sat( temp, 3 ); + move32(); + + temp = Mpy_32_32( outSlotIm[ch][slot][bin], eqVal ); // Q = (cldfb_q) + 28 -31 = cldfb_q - 3 + inIm_fx[ch][slot][bin] = L_shl_sat( temp, 3 ); + move32(); + } + } + } + } + +#ifdef OBJ_EDITING_PARAMISM_BIN + IF( !masaIsmMode ) + { + Word16 obj_idx1, obj_idx2; + + FOR( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ ) + { + bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx]; + bin_hi = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1]; + move16(); + move16(); + + obj_idx1 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0]; + obj_idx2 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1]; + move16(); + move16(); + + FOR( bin = bin_lo; bin < bin_hi; bin++ ) + { + hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism_fx[obj_idx1][dirac_read_idx][bin]; + hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism_fx[obj_idx2][dirac_read_idx][bin]; + move32(); + move32(); + } + } + } +#endif + } + + return; +} +#else +/*-------------------------------------------------------------------* + * ivas_omasa_preProcessStereoTransportsForMovedObjects_fx() + * + * + *-------------------------------------------------------------------*/ + +void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( + Decoder_Struct *st_ivas, + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/ + Word16 *cldfb_buf_q, + const Word16 nBins, + const Word16 subframe ) +{ + Word16 bin, ch, inCh, outCh, ismDirIndex, slot; + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; + MASA_ISM_DATA_HANDLE hMasaIsmData; + UWord8 enableCentering; + Word16 dirac_read_idx; + Word16 nSlots; + + hSpatParamRendCom = st_ivas->hSpatParamRendCom; + hMasaIsmData = st_ivas->hMasaIsmData; + + test(); + test(); + IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_HOA3 ) ) + { + enableCentering = 0; + move16(); + } + ELSE + { + enableCentering = 1; + move16(); + } + + /* Bypass processing until first object is moved */ + IF( EQ_16( hMasaIsmData->objectsMoved, 0 ) ) + { + FOR( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ ) + { + if ( hMasaIsmData->ism_is_edited[ismDirIndex] ) + { + hMasaIsmData->objectsMoved = 1; + move16(); + } + } + IF( EQ_16( hMasaIsmData->objectsMoved, 0 ) ) + { + /* No objects have moved so far */ + return; + } + } + + /* Perform object-movement based processing */ + nSlots = hSpatParamRendCom->subframe_nbslots[subframe]; + move16(); + dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + move16(); + + FOR( bin = 0; bin < nBins; bin++ ) + { + Word16 ismPreprocMtxNew_fx[2][2]; + Word16 ismPreprocMtxIncrement_fx[2][2]; + Word16 eneMove_fx[2]; + Word16 enePreserve_fx[2]; + Word16 ismRatioAcc_fx; + Word32 subframeEne_fx; + Word32 Enes_fx[2]; + Word16 normEnes_fx[2]; + Word16 remainderNormEne_fx; + Word16 normEnes_q_fx[2], temp_q = 0; + Word16 eneMove_q_fx[2], enePreserve_q_fx[2], temp1; + Word32 temp; + + set16_fx( ismPreprocMtxNew_fx[0], 0, 2 ); + set16_fx( ismPreprocMtxNew_fx[1], 0, 2 ); + set16_fx( ismPreprocMtxIncrement_fx[0], 0, 2 ); + set16_fx( ismPreprocMtxIncrement_fx[1], 0, 2 ); + set16_fx( eneMove_fx, 0, 2 ); + set16_fx( enePreserve_fx, 0, 2 ); + ismRatioAcc_fx = 0; + move16(); + subframeEne_fx = 0; + move32(); + set16_fx( normEnes_fx, 0, 2 ); + set32_fx( Enes_fx, 0, 2 ); + set16_fx( normEnes_q_fx, Q31, 2 ); + set16_fx( eneMove_q_fx, Q31, 2 ); + set16_fx( enePreserve_q_fx, Q31, 2 ); + + /* Determine transport normalized energies and subframe energy */ + FOR( slot = 0; slot < nSlots; slot++ ) + { + FOR( ch = 0; ch < 2; ch++ ) + { + Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 + move32(); + Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 + move32(); + } + + subframeEne_fx = L_add( Enes_fx[0], Enes_fx[1] ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19 + + IF( NE_32( subframeEne_fx, 0 ) ) + { + normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], subframeEne_fx, &temp_q ); + move32(); + normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12 + move32(); + normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], subframeEne_fx, &temp_q ); + move32(); + normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12 + move32(); + } + ELSE + { + normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], EPSILON_FX, &temp_q ); + move32(); + normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12 + move32(); + normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], EPSILON_FX, &temp_q ); + move32(); + normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12 + move32(); } @@ -5524,7 +6945,7 @@ void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( return; } - +#endif static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, diff --git a/lib_rend/ivas_dirac_output_synthesis_dec_fx.c b/lib_rend/ivas_dirac_output_synthesis_dec_fx.c index 326811bd5f14656d8b54b2adefc03399427fb97a..e79973c7753567b47239b060944f33b63c641bf5 100644 --- a/lib_rend/ivas_dirac_output_synthesis_dec_fx.c +++ b/lib_rend/ivas_dirac_output_synthesis_dec_fx.c @@ -2853,13 +2853,20 @@ void ivas_dirac_dec_compute_directional_responses_fx( FOR( dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++ ) { +#ifdef OMASA_OBJECT_EDITING + IF( hMasaIsm->ism_dir_is_edited[dir] ) + { + ivas_dirac_dec_get_response_fx( hMasaIsm->azimuth_ism_edited_fx[dir], hMasaIsm->elevation_ism_edited_fx[dir], direct_response_temp_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 ); + } +#else IF( hMasaIsm->ism_is_edited[dir] ) { ivas_dirac_dec_get_response_fx( hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], direct_response_temp_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 ); } +#endif ELSE { - ivas_dirac_dec_get_response_fx( hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], direct_response_temp_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 ); + ivas_dirac_dec_get_response_fx( hMasaIsm->azimuth_ism_fx[dir][md_idx], hMasaIsm->elevation_ism_fx[dir][md_idx], direct_response_temp_fx, hDirACRend->hOutSetup.ambisonics_order, Q29 ); } exp_direct_response_temp = 2; move16(); @@ -3104,13 +3111,20 @@ void ivas_dirac_dec_compute_directional_responses_fx( FOR( dir = 0; dir < hSpatParamRendCom->numIsmDirections; dir++ ) { +#ifdef OMASA_OBJECT_EDITING + IF( hMasaIsm->ism_dir_is_edited[dir] ) + { + vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism_edited_fx[dir], hMasaIsm->elevation_ism_edited_fx[dir], 1 ); + } +#else IF( hMasaIsm->ism_is_edited[dir] ) { vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism_edited[dir], hMasaIsm->elevation_ism_edited[dir], 1 ); } +#endif ELSE { - vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism[dir][md_idx], hMasaIsm->elevation_ism[dir][md_idx], 1 ); + vbap_determine_gains_fx( hVBAPdata, direct_response_temp_fx, hMasaIsm->azimuth_ism_fx[dir][md_idx], hMasaIsm->elevation_ism_fx[dir][md_idx], 1 ); } Word32 tmp = 0; move32(); diff --git a/lib_rend/ivas_objectRenderer_fx.c b/lib_rend/ivas_objectRenderer_fx.c index 641af4624c3128e173060ae301a437d15eed9590..2f950061a39068b7bcafbe4c65443e51f687d995 100644 --- a/lib_rend/ivas_objectRenderer_fx.c +++ b/lib_rend/ivas_objectRenderer_fx.c @@ -677,6 +677,12 @@ ivas_error TDREND_Update_object_positions_fx( return error; } #endif +#ifdef OBJ_EDITING_INTERFACE + if ( ( error = TDREND_MIX_SRC_SetGain( hBinRendererTd, nS, hIsmMetaData[nS]->gain_fx ) ) != IVAS_ERR_OK ) // TODO: Check Gain has correct Q-value + { + return error; + } +#endif IF( hIsmMetaData[nS]->non_diegetic_flag ) { @@ -983,6 +989,9 @@ ivas_error ivas_td_binaural_renderer_ext_fx( move32(); hIsmMetaData[0]->radius_fx = currentPos->radius_fx; move32(); +#ifdef OBJ_EDITING_INTERFACE + hIsmMetaData[0]->gain_fx = ONE_IN_Q29; // TODO: check Q value +#endif hIsmMetaData[0]->non_diegetic_flag = currentPos->non_diegetic_flag; move16(); } diff --git a/lib_rend/ivas_objectRenderer_sources_fx.c b/lib_rend/ivas_objectRenderer_sources_fx.c index f4f57fde545dde59cc1e5ec403d15008dcad8530..781fe52ce2b4627fd4c535553f2db81497c18cee 100644 --- a/lib_rend/ivas_objectRenderer_sources_fx.c +++ b/lib_rend/ivas_objectRenderer_sources_fx.c @@ -49,6 +49,9 @@ static Word16 TDREND_SRC_SPATIAL_GetDirGain_fx( const TDREND_DirAtten_t *DirAtte static Word16 TDREND_SRC_SPATIAL_GetDistGain_fx( const TDREND_DistAtten_t *DistAtten_p, const Word32 Dist_fx, const Word16 Dist_e ); static void TDREND_SRC_SPATIAL_SetDirAtten_fx( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DirAtten_t *DirAtten_p ); static void TDREND_SRC_SPATIAL_SetDistAtten( TDREND_SRC_SPATIAL_t *SrcSpatial_p, const TDREND_DistAtten_t *DistAtten_p ); +#ifdef OBJ_EDITING_INTERFACE +static void TDREND_SRC_SPATIAL_SetGain( const TDREND_SRC_t *Src_p, const Word32 Gain ); +#endif static ivas_error TDREND_SRC_REND_Alloc( TDREND_SRC_REND_t **SrcRend_pp ); static void TDREND_SRC_SPATIAL_Dealloc( TDREND_SRC_SPATIAL_t *SrcSpatial_p ); @@ -129,6 +132,24 @@ ivas_error TDREND_MIX_SRC_SetDir_fx( return IVAS_ERR_OK; } +#ifdef OBJ_EDITING_INTERFACE +/*-------------------------------------------------------------------* + * TDREND_MIX_SRC_SetSourceGain() + * + * Set source gain + --------------------------------------------------------------------*/ + +ivas_error TDREND_MIX_SRC_SetGain( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const Word16 SrcInd, /* i : Source index */ + const Word32 Gain /* i : Gain */ +) +{ + TDREND_SRC_SPATIAL_SetGain( hBinRendererTd->Sources[SrcInd], Gain ); + + return IVAS_ERR_OK; +} +#endif /*-------------------------------------------------------------------* * TDREND_MIX_SRC_SetDirAtten() @@ -671,6 +692,21 @@ static void TDREND_SRC_SPATIAL_SetDistAtten( return; } +#ifdef OBJ_EDITING_INTERFACE +/*-------------------------------------------------------------------* + * TDREND_SRC_SPATIAL_SetGain() + * + * Set the object gain + --------------------------------------------------------------------*/ + +static void TDREND_SRC_SPATIAL_SetGain( + const TDREND_SRC_t *Src_p, /* i : Directional attenuation specification */ + const Word32 Gain /* i : Front-pointing vector */ +) +{ + Src_p->SrcRend_p->SrcGain_p_fx[0] = shl_sat( extract_h( Gain ), Q1 ); // TODO: Check incoming Q-value and fix this +} +#endif /*-------------------------------------------------------------------* * TDREND_SRC_SPATIAL_GetDirGain() diff --git a/lib_rend/ivas_prot_rend_fx.h b/lib_rend/ivas_prot_rend_fx.h index c695138da5bcb22863df3e25983c94dbe407c554..dc9a2e5b080bae68c9adc270338c2b30002d3bec 100644 --- a/lib_rend/ivas_prot_rend_fx.h +++ b/lib_rend/ivas_prot_rend_fx.h @@ -750,6 +750,14 @@ ivas_error TDREND_MIX_SRC_SetDir_fx( const Word16 Vec_p_q /* i : Direction vector q */ ); +#ifdef OBJ_EDITING_INTERFACE +ivas_error TDREND_MIX_SRC_SetGain( + BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ + const Word16 SrcInd, + const Word32 Gain /* i : Gain */ +); +#endif + ivas_error TDREND_MIX_SRC_SetDirAtten_fx( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ const Word16 SrcInd, /* i : Source index */ @@ -768,6 +776,13 @@ ivas_error TDREND_MIX_SRC_SetPlayState( const TDREND_PlayStatus_t PlayStatus /* i : Play state */ ); +#ifdef OBJ_EDITING_API +// ivas_error TDREND_SRC_SPATIAL_SetGain( +// BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ +// const Word32 SrcGain_p /* i : Source gain */ +// ); +#endif + void TDREND_SRC_REND_UpdateFiltersFromSpatialParams_fx( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd, /* i/o: TD renderer handle */ TDREND_SRC_REND_t *SrcRend_p, /* i/o: Source object */ diff --git a/lib_util/ism_file_reader.c b/lib_util/ism_file_reader.c index f3d782aeb7484e7c38b80c103fba546c8f57e216..f27e346344bf80cb37583eba213d5a8fd59060f4 100644 --- a/lib_util/ism_file_reader.c +++ b/lib_util/ism_file_reader.c @@ -160,7 +160,7 @@ ivas_error IsmFileReader_readNextFrame( ismMetadata->elevation_fx = floatToFixed( meta_prm[1], Q22 ); ismMetadata->radius_fx = (Word16) floatToFixed( meta_prm[2], Q9 ); ismMetadata->spread_fx = floatToFixed( meta_prm[3], Q22 ); - ismMetadata->gainFactor_fx = floatToFixed( meta_prm[4], Q31 ); + ismMetadata->gainFactor_fx = floatToFixed( meta_prm[4], Q31 ); // TODO: Check correct Q value ismMetadata->yaw_fx = floatToFixed( meta_prm[5], Q22 ); ismMetadata->pitch_fx = floatToFixed( meta_prm[6], Q22 ); diff --git a/lib_util/ism_file_writer.c b/lib_util/ism_file_writer.c index 94bab6dd279ae62eed74ef6a52dd6df614dcb667..34fb9ae8d22bf9df92620a4b9310156ce686b08b 100644 --- a/lib_util/ism_file_writer.c +++ b/lib_util/ism_file_writer.c @@ -118,7 +118,7 @@ ivas_error IsmFileWriter_writeFrame( ismMetadata.elevation = fixedToFloat( ismMetadata.elevation_fx, Q22 ); ismMetadata.radius = fix16_to_float( ismMetadata.radius_fx, Q9 ); ismMetadata.spread = fixedToFloat( ismMetadata.spread_fx, Q22 ); - ismMetadata.gainFactor = fixedToFloat( ismMetadata.gainFactor_fx, Q31 ); + ismMetadata.gainFactor = fixedToFloat( ismMetadata.gainFactor_fx, Q29 ); // TODO: Change to Q28 or Q12? ismMetadata.yaw = fixedToFloat( ismMetadata.yaw_fx, Q22 ); ismMetadata.pitch = fixedToFloat( ismMetadata.pitch_fx, Q22 );