From 651757ef17eb9e13b31998ca6519768fc130bcc2 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Tue, 27 Feb 2024 18:43:25 +0530 Subject: [PATCH] Converted rotateFrameMc() [x] MC to binaural cases are affected by the changes. Test results - 107 failed, 551 passed, 136 skipped with highest max abs difference of 570 --- apps/renderer.c | 6 +- lib_com/ivas_rom_com_fx.c | 3 + lib_com/ivas_rom_com_fx.h | 3 + lib_rend/ivas_prot_rend.h | 9 + lib_rend/ivas_rotation.c | 86 ++++++- lib_rend/ivas_stat_rend.h | 25 +- lib_rend/lib_rend.c | 491 ++++++++++++++++++++++++++++++++++++-- 7 files changed, 590 insertions(+), 33 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 632df8ef3..232506c6c 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1312,12 +1312,16 @@ int main( exit( -1 ); } IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, numChannels ); - +#ifdef IVAS_FLOAT_FIXED + if ( ( error = IVAS_REND_FeedInputAudio_fx( hIvasRend, mcIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); exit( -1 ); } + } for ( i = 0; i < args.inConfig.numAudioObjects; ++i ) diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index e10ce9db2..ffdeb37be 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -518,6 +518,9 @@ const UWord16 cum_n_for_id_th[122] = { /*----------------------------------------------------------------------------------* * Multi-channel LS setups *----------------------------------------------------------------------------------*/ +/*Azimuth and elevation LS Tables in Q22*/ +const Word32 ls_azimuth_CICP1_fx[1] = { 0 }; +const Word32 ls_elevation_CICP1_fx[1] = { 0 }; const Word32 ls_azimuth_CICP2_fx[2] = { 125829120, -125829120 }; const Word32 ls_elevation_CICP2_fx[2] = { 0, 0 }; diff --git a/lib_com/ivas_rom_com_fx.h b/lib_com/ivas_rom_com_fx.h index 165e148fe..b441430a5 100644 --- a/lib_com/ivas_rom_com_fx.h +++ b/lib_com/ivas_rom_com_fx.h @@ -65,6 +65,9 @@ extern const Word32 ism_elevation_borders_fx[4]; extern const UWord16 cum_n_for_id_th[122]; /* Multi-channel input and output setups */ + +extern const Word32 ls_azimuth_CICP1_fx[1]; +extern const Word32 ls_elevation_CICP1_fx[1]; extern const Word32 ls_azimuth_CICP2_fx[2]; extern const Word32 ls_elevation_CICP2_fx[2]; extern const Word32 ls_azimuth_CICP6_fx[5]; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index e3cf3e791..7acd0d9ac 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1690,6 +1690,15 @@ void rotateAziEle_fx( Word32 Rmat[3][3], /* i : real-space rotation matrix */ const Word16 isPlanar /* i : is roation planar and elevation meaningless? */ ); + +void rotateAziEle_fixed( + Word16 azi_in, /* i : output elevation */ + Word16 ele_in, /* i : input elevation */ + Word32 *azi, /* o : rotated azimuth */ + Word32 *ele, /* o : rotated elevation */ + Word32 Rmat[3][3], /* i : real-space rotation matrix */ + const Word16 isPlanar /* i : is roation planar and elevation meaningless? */ +); void SHrotmatgen_fx( Word16 SHrotmat[SBA_NHARM_HOA3][SBA_NHARM_HOA3], /* o : SHD rotation matrix */ Word32 Rmat[3][3], /* i : real-space rotation matrix */ diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 235caa56c..f0e39920a 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -340,7 +340,7 @@ void rotateAziEle_fx( for ( n = 0; n < 3; n++ ) { temp = L_add( Mpy_32_32( dv_fx[0], Rmat_fx[n][0] ), Mpy_32_32( dv_fx[1], Rmat_fx[n][1] ) ); - dv_r_fx[n] = L_add( Mpy_32_32( dv_fx[2], Rmat_fx[n][2] ), temp ); // q15 + dv_r_fx[n] = L_add( Mpy_32_32( dv_fx[2], Rmat_fx[n][2] ), temp ); // Q30 } /*Conversion cartesian to spherical coordinates*/ @@ -408,6 +408,85 @@ void rotateAziEle_fx( return; } + +/*------------------------------------------------------------------------- + * rotateAziEle() + * + * Apply rotation to direction parameters azimuth and elevation + *------------------------------------------------------------------------*/ + +void rotateAziEle_fixed( + Word16 azi_in, /* i : output elevation */ + Word16 ele_in, /* i : input elevation */ + Word32 *azi, /* o : rotated azimuth */ + Word32 *ele, /* o : rotated elevation */ + Word32 Rmat_fx[3][3], /* i : real-space rotation matrix */ + const Word16 isPlanar /* i : is rotation planar and elevation meaningless? */ +) +{ + Word16 n,radian,temp_16; + Word32 dv_fx[3], dv_r_fx[3]; + Word32 w_fx; + Word32 temp; + Word32 y, x, sqrt_fx; + Word32 angle; + /*Conversion spherical to cartesian coordinates*/ + if ( abs( azi_in ) > 180 ) + { + azi_in = ( azi_in > 0 ) ? ( azi_in - 360 ) : ( azi_in + 360 ); + } + temp_16 = ele_in; + w_fx = cosine_table_Q31[abs( temp_16 )]; + temp_16 = azi_in; + dv_fx[0] = Mpy_32_32( w_fx, cosine_table_Q31[abs( temp_16 )] ); + temp_16 = azi_in; + dv_fx[1] = Mpy_32_32( w_fx, sine_table_Q31[temp_16 + 180] ); + temp_16 = ele_in; + dv_fx[2] = sine_table_Q31[temp_16 + 180]; + + /*Rotation mtx multiplication*/ + for ( n = 0; n < 3; n++ ) + { + temp = L_add( Mpy_32_32( dv_fx[0], Rmat_fx[n][0] ), Mpy_32_32( dv_fx[1], Rmat_fx[n][1] ) ); + dv_r_fx[n] = L_add( Mpy_32_32( dv_fx[2], Rmat_fx[n][2] ), temp ); // Q30 + } + + /*Conversion cartesian to spherical coordinates*/ + y = dv_r_fx[1]; + x = dv_r_fx[0]; + radian = BASOP_util_atan2( y , x, 0 );//Q13 + + angle = ( Mpy_32_16_1( _180_OVER_PI_Q25, radian ) >> 1);//Q22 + + + *azi = (Word32) ( max( L_shl(-180,22), min( L_shl(180,22), angle ) ) );//Q22 + if ( abs(*azi)<=ONE_IN_Q22 ) + { + *azi = 0; + } + if ( isPlanar == 0 ) + { + sqrt_fx = L_Frac_sqrtQ31( L_add( Mpy_32_32( dv_r_fx[0], dv_r_fx[0] ), Mpy_32_32( dv_r_fx[1], dv_r_fx[1] ) ) ); + y = dv_r_fx[2]; + x = sqrt_fx; + radian = BASOP_util_atan2( y , x ,0); + + angle = ( Mpy_32_16_1( _180_OVER_PI_Q25, radian ) >> 1 );//Q22 + + + *ele = (Word32) ( max( L_shl( -90, 22 ), min( L_shl( 90, 22 ), angle ) ) ); // Q22 + if ( abs( *ele ) < ONE_IN_Q22 ) + { + *ele = 0; + } + } + else + { + *ele = 0; + } + + return; +} #endif /*------------------------------------------------------------------------- * rotateAziEle() @@ -439,7 +518,10 @@ void rotateAziEle( { dv_r[n] = Rmat[n][0] * dv[0] + Rmat[n][1] * dv[1] + Rmat[n][2] * dv[2]; } - + float inter,inter1,inter2; + inter = atan2f( dv_r[1], dv_r[0] ); + inter1 = min( 180.0f, atan2f( dv_r[1], dv_r[0] ) * _180_OVER_PI ); + inter2 = max( -180.0f, min( 180.0f, atan2f( dv_r[1], dv_r[0] ) * _180_OVER_PI ) ); /*Conversion cartesian to spherical coordinates*/ *azi = (int16_t) roundf( max( -180.0f, min( 180.0f, atan2f( dv_r[1], dv_r[0] ) * _180_OVER_PI ) ) ); if ( isPlanar == 0 ) diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 1b4b9e331..247512485 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1968,25 +1968,36 @@ typedef struct ivas_mono_downmix_renderer_struct /*----------------------------------------------------------------------------------* * Custom Loudspeaker configuration structure *----------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +typedef struct ivas_LS_setup_custom +{ + Word16 is_planar_setup; /* flag to indicate if setup is planar or not */ + Word16 num_spk; /* number of custom loudspeakers */ + float ls_azimuth[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker azimuths */ + float ls_elevation[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker elevations */ + Word32 ls_azimuth_fx[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker azimuths */ + Word32 ls_elevation_fx[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker elevations */ + Word16 num_lfe; /* number of LFE channels */ + Word16 lfe_idx[MAX_OUTPUT_CHANNELS]; /* index for LFE channel insertion */ + Word16 separate_ch_found; /* flag to indicate if a center channel was found */ + float separate_ch_gains[MAX_OUTPUT_CHANNELS]; /* gains to pan McMASA separateChannel in case no center channel is present */ + + Word16 separate_ch_gains_fx[MAX_OUTPUT_CHANNELS]; /* gains to pan McMASA separateChannel in case no center channel is present */ +} LSSETUP_CUSTOM_STRUCT, *LSSETUP_CUSTOM_HANDLE; +#else typedef struct ivas_LS_setup_custom { int16_t is_planar_setup; /* flag to indicate if setup is planar or not */ int16_t num_spk; /* number of custom loudspeakers */ float ls_azimuth[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker azimuths */ float ls_elevation[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker elevations */ -#ifdef IVAS_FLOAT_FIXED - Word32 ls_azimuth_fx[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker azimuths */ - Word32 ls_elevation_fx[MAX_OUTPUT_CHANNELS]; /* custom loudspeaker elevations */ -#endif int16_t num_lfe; /* number of LFE channels */ int16_t lfe_idx[MAX_OUTPUT_CHANNELS]; /* index for LFE channel insertion */ int16_t separate_ch_found; /* flag to indicate if a center channel was found */ float separate_ch_gains[MAX_OUTPUT_CHANNELS]; /* gains to pan McMASA separateChannel in case no center channel is present */ - - Word16 separate_ch_gains_fx[MAX_OUTPUT_CHANNELS]; /* gains to pan McMASA separateChannel in case no center channel is present */ } LSSETUP_CUSTOM_STRUCT, *LSSETUP_CUSTOM_HANDLE; - +#endif /* Channel types in a channel-based config */ typedef enum diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 6939d4e32..18af1b3c0 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -45,6 +45,7 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED +#include "ivas_rom_com_fx.h" #include "ivas_prot_fx.h" #include "prot_fx1.h" #include "prot_fx2.h" @@ -80,6 +81,8 @@ typedef float rotation_gains[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS]; #ifdef IVAS_FLOAT_FIXED typedef Word32 pan_matrix_fx[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS]; typedef Word16 rotation_gains_fx[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS]; +typedef Word32 rotation_gains_Word32[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS]; +typedef Word32 rotation_matrix_fx[3][3]; #endif typedef float rotation_matrix[3][3]; @@ -170,7 +173,32 @@ typedef struct float lfeOutputElevation; IVAS_REND_LfePanMtx lfePanMtx; } lfe_routing; +#ifdef IVAS_FLOAT_FIXED +typedef struct +{ + input_base base; + + /* Full panning matrix. 1st index is input channel, 2nd index is output channel. + All LFE channels should be included, both for inputs and outputs */ + pan_matrix panGains; + LSSETUP_CUSTOM_STRUCT customLsInput; + EFAP_WRAPPER efapInWrapper; + TDREND_WRAPPER tdRendWrapper; + CREND_WRAPPER_HANDLE crendWrapper; + REVERB_HANDLE hReverb; + rotation_gains rot_gains_prev; + rotation_gains_Word32 rot_gains_prev_fx; + int16_t nonDiegeticPan; + float nonDiegeticPanGain; + lfe_routing lfeRouting; + float *bufferData; + Word32 *bufferData_fx; + int16_t binauralDelaySmp; + float *lfeDelayBuffer; + MCMASA_ANA_HANDLE hMcMasa; +} input_mc; +#else typedef struct { input_base base; @@ -193,6 +221,7 @@ typedef struct float *lfeDelayBuffer; MCMASA_ANA_HANDLE hMcMasa; } input_mc; +#endif #ifdef IVAS_FLOAT_FIXED typedef struct { @@ -808,7 +837,7 @@ ivas_error getAudioConfigNumChannels( const AUDIO_CONFIG config, Word16 *numChannels ) { - SWITCH ( config ) + SWITCH( config ) { case IVAS_AUDIO_CONFIG_MONO: case IVAS_AUDIO_CONFIG_OBA: @@ -988,6 +1017,41 @@ static LSSETUP_CUSTOM_STRUCT defaultCustomLs( return ls; } +#ifdef IVAS_FLOAT_FIXED +static ivas_error getSpeakerAzimuths_fx( + AUDIO_CONFIG config, + const Word32 **azimuths ) +{ + SWITCH( config ) + { + case IVAS_AUDIO_CONFIG_MONO: + *azimuths = ls_azimuth_CICP1_fx; + BREAK; + case IVAS_AUDIO_CONFIG_STEREO: + *azimuths = ls_azimuth_CICP2_fx; + BREAK; + case IVAS_AUDIO_CONFIG_5_1: + *azimuths = ls_azimuth_CICP6_fx; + BREAK; + case IVAS_AUDIO_CONFIG_7_1: + *azimuths = ls_azimuth_CICP12_fx; + BREAK; + case IVAS_AUDIO_CONFIG_5_1_2: + *azimuths = ls_azimuth_CICP14_fx; + BREAK; + case IVAS_AUDIO_CONFIG_5_1_4: + *azimuths = ls_azimuth_CICP16_fx; + BREAK; + case IVAS_AUDIO_CONFIG_7_1_4: + *azimuths = ls_azimuth_CICP19_fx; + BREAK; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" ); + } + + return IVAS_ERR_OK; +} +#endif static ivas_error getSpeakerAzimuths( AUDIO_CONFIG config, @@ -1022,8 +1086,41 @@ static ivas_error getSpeakerAzimuths( return IVAS_ERR_OK; } +#ifdef IVAS_FLOAT_FIXED +static ivas_error getSpeakerElevations_fx( + AUDIO_CONFIG config, + const Word32 **elevations ) +{ + SWITCH( config ) + { + case IVAS_AUDIO_CONFIG_MONO: + *elevations = ls_elevation_CICP1_fx; + BREAK; + case IVAS_AUDIO_CONFIG_STEREO: + *elevations = ls_elevation_CICP2_fx; + BREAK; + case IVAS_AUDIO_CONFIG_5_1: + *elevations = ls_elevation_CICP6_fx; + BREAK; + case IVAS_AUDIO_CONFIG_7_1: + *elevations = ls_elevation_CICP12_fx; + BREAK; + case IVAS_AUDIO_CONFIG_5_1_2: + *elevations = ls_elevation_CICP14_fx; + BREAK; + case IVAS_AUDIO_CONFIG_5_1_4: + *elevations = ls_elevation_CICP16_fx; + BREAK; + case IVAS_AUDIO_CONFIG_7_1_4: + *elevations = ls_elevation_CICP19_fx; + BREAK; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" ); + } - + return IVAS_ERR_OK; +} +#endif static ivas_error getSpeakerElevations( AUDIO_CONFIG config, const float **elevations ) @@ -1155,7 +1252,73 @@ static ivas_error getNumNonLfeChannelsInSpeakerLayout( return IVAS_ERR_OK; } +#ifdef IVAS_FLOAT_FIXED +static ivas_error getMcConfigValues_fx( + AUDIO_CONFIG inConfig, + const LSSETUP_CUSTOM_STRUCT *pInCustomLs, + const Word32 **azimuth, + const Word32 **elevation, + Word16 *lfe_idx, + Word16 *is_planar ) +{ + Word16 i; + ivas_error error; + *lfe_idx = -1; + *is_planar = 1; + SWITCH( inConfig ) + { + case IVAS_AUDIO_CONFIG_LS_CUSTOM: + *azimuth = (const Word32 *) &pInCustomLs->ls_azimuth_fx; + *elevation = (const Word32 *) &pInCustomLs->ls_azimuth_fx; + IF( GT_16( pInCustomLs->num_lfe, 0 ) ) + { + *lfe_idx = pInCustomLs->lfe_idx[0]; + } + FOR( i = 0; i < pInCustomLs->num_spk; i++ ) + { + IF( NE_32( pInCustomLs->ls_elevation_fx[i], 0 ) ) + { + *is_planar = 0; + BREAK; + } + } + BREAK; + case IVAS_AUDIO_CONFIG_MONO: + case IVAS_AUDIO_CONFIG_STEREO: + if ( ( error = getSpeakerAzimuths_fx( inConfig, azimuth ) ) != IVAS_ERR_OK ) + { + return error; + } + if ( ( error = getSpeakerElevations_fx( inConfig, elevation ) ) != IVAS_ERR_OK ) + { + return error; + } + BREAK; + case IVAS_AUDIO_CONFIG_5_1: + case IVAS_AUDIO_CONFIG_7_1: + case IVAS_AUDIO_CONFIG_5_1_2: + case IVAS_AUDIO_CONFIG_5_1_4: + case IVAS_AUDIO_CONFIG_7_1_4: + IF( ( error = getSpeakerAzimuths_fx( inConfig, azimuth ) ) != IVAS_ERR_OK ) + { + return error; + } + IF( ( error = getSpeakerElevations_fx( inConfig, elevation ) ) != IVAS_ERR_OK ) + { + return error; + } + *lfe_idx = LFE_CHANNEL; + *is_planar = ( inConfig == IVAS_AUDIO_CONFIG_5_1 || inConfig == IVAS_AUDIO_CONFIG_7_1 ) ? 1 : 0; + BREAK; + default: + assert( !"Invalid speaker config" ); + return IVAS_ERR_WRONG_PARAMS; + } + + return IVAS_ERR_OK; +} +#endif static ivas_error getMcConfigValues( AUDIO_CONFIG inConfig, const LSSETUP_CUSTOM_STRUCT *pInCustomLs, @@ -1393,9 +1556,9 @@ static ivas_error initHeadRotation( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" ); } - IF((error = ivas_orient_trk_Init_fx(hIvasRend->headRotData.hOrientationTracker)) != IVAS_ERR_OK) + IF( ( error = ivas_orient_trk_Init_fx( hIvasRend->headRotData.hOrientationTracker ) ) != IVAS_ERR_OK ) { - return error; + return error; } #else IF( ( error = ivas_orient_trk_Init( hIvasRend->headRotData.hOrientationTracker ) ) != IVAS_ERR_OK ) @@ -1494,6 +1657,21 @@ static void initRotGains_fx( return; } + +static void initRotGainsWord32_fx( + rotation_gains_Word32 rot_gains ) +{ + Word16 i; + + /* Set gains to passthrough */ + FOR( i = 0; i < MAX_INPUT_CHANNELS; i++ ) + { + set_val_Word32( rot_gains[i], 0, MAX_INPUT_CHANNELS ); + rot_gains[i][i] = ONE_IN_Q30; + } + + return; +} #endif static void initRotGains( rotation_gains rot_gains ) @@ -2606,7 +2784,7 @@ static lfe_routing defaultLfeRouting( return routing; } - +#ifdef IVAS_FLOAT_FIXED static ivas_error setRendInputActiveMc( void *input, const AUDIO_CONFIG inConfig, @@ -2636,9 +2814,15 @@ static ivas_error setRendInputActiveMc( { return error; } + if ( ( error = allocateInputBaseBufferData_fx( &inputMc->bufferData_fx, MAX_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) + { + return error; + } initRendInputBase( &inputMc->base, inConfig, id, rendCtx, inputMc->bufferData, MAX_BUFFER_LENGTH ); + initRendInputBase_fx( &inputMc->base, inConfig, id, rendCtx, inputMc->bufferData_fx, MAX_BUFFER_LENGTH ); setZeroPanMatrix( inputMc->panGains ); + inputMc->customLsInput = defaultCustomLs(); inputMc->tdRendWrapper = defaultTdRendWrapper(); inputMc->crendWrapper = NULL; @@ -2646,6 +2830,7 @@ static ivas_error setRendInputActiveMc( inputMc->hMcMasa = NULL; initRotGains( inputMc->rot_gains_prev ); + initRotGainsWord32_fx( inputMc->rot_gains_prev_fx ); inputMc->lfeRouting = defaultLfeRouting( inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ); set_zero( inputMc->lfeDelayBuffer, MAX_BIN_DELAY_SAMPLES ); inputMc->binauralDelaySmp = 0; @@ -2673,8 +2858,75 @@ static ivas_error setRendInputActiveMc( return IVAS_ERR_OK; } +#else +static ivas_error setRendInputActiveMc( + void *input, + const AUDIO_CONFIG inConfig, + const IVAS_REND_InputId id, + RENDER_CONFIG_DATA *hRendCfg ) +{ + ivas_error error; + rendering_context rendCtx; + AUDIO_CONFIG outConfig; + input_mc *inputMc; + + inputMc = (input_mc *) input; + rendCtx = inputMc->base.ctx; + outConfig = *rendCtx.pOutConfig; + + if ( !isIoConfigPairSupported( inConfig, outConfig ) ) + { + return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; + } + + if ( ( error = allocateMcLfeDelayBuffer( &inputMc->lfeDelayBuffer, MAX_BIN_DELAY_SAMPLES ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( ( error = allocateInputBaseBufferData( &inputMc->bufferData, MAX_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) + { + return error; + } + initRendInputBase( &inputMc->base, inConfig, id, rendCtx, inputMc->bufferData, MAX_BUFFER_LENGTH ); + + setZeroPanMatrix( inputMc->panGains ); + inputMc->customLsInput = defaultCustomLs(); + inputMc->tdRendWrapper = defaultTdRendWrapper(); + inputMc->crendWrapper = NULL; + inputMc->hReverb = NULL; + inputMc->hMcMasa = NULL; + + initRotGains( inputMc->rot_gains_prev ); + inputMc->lfeRouting = defaultLfeRouting( inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ); + set_zero( inputMc->lfeDelayBuffer, MAX_BIN_DELAY_SAMPLES ); + inputMc->binauralDelaySmp = 0; + + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + { + if ( ( error = initMcBinauralRendering( inputMc, inConfig, outConfig, hRendCfg, FALSE ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( outConfig == IVAS_AUDIO_CONFIG_MASA1 || outConfig == IVAS_AUDIO_CONFIG_MASA2 ) + { + if ( ( error = initMcMasaRendering( inputMc, inConfig, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + if ( ( error = updateMcPanGains( inputMc, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + return IVAS_ERR_OK; +} +#endif +#ifdef IVAS_FLOAT_FIXED static void clearInputMc( input_mc *inputMc ) { @@ -2684,7 +2936,9 @@ static void clearInputMc( freeMcLfeDelayBuffer( &inputMc->lfeDelayBuffer ); freeInputBaseBufferData( &inputMc->bufferData ); + freeInputBaseBufferData_fx( &inputMc->bufferData_fx ); initRendInputBase( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); + initRendInputBase_fx( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); /* Free input's internal handles */ if ( inputMc->efapInWrapper.hEfap != NULL ) @@ -2707,7 +2961,40 @@ static void clearInputMc( return; } +#else +static void clearInputMc( + input_mc *inputMc ) +{ + rendering_context rendCtx; + rendCtx = inputMc->base.ctx; + + freeMcLfeDelayBuffer( &inputMc->lfeDelayBuffer ); + freeInputBaseBufferData( &inputMc->bufferData ); + initRendInputBase( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); + + /* Free input's internal handles */ + if ( inputMc->efapInWrapper.hEfap != NULL ) + { + efap_free_data( &inputMc->efapInWrapper.hEfap ); + } + + ivas_rend_closeCrend( &inputMc->crendWrapper ); + + ivas_reverb_close( &inputMc->hReverb ); + + if ( inputMc->tdRendWrapper.hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &inputMc->tdRendWrapper.hBinRendererTd ); + inputMc->tdRendWrapper.hHrtfTD = NULL; + } + + + ivas_mcmasa_ana_close( &( inputMc->hMcMasa ) ); + + return; +} +#endif static ivas_error initSbaPanGainsForMcOut( input_sba *inputSba, @@ -3305,6 +3592,7 @@ ivas_error IVAS_REND_Open( hIvasRend->inputsMc[i].hReverb = NULL; hIvasRend->inputsMc[i].tdRendWrapper.hBinRendererTd = NULL; hIvasRend->inputsMc[i].bufferData = NULL; + hIvasRend->inputsMc[i].bufferData_fx = NULL; hIvasRend->inputsMc[i].lfeDelayBuffer = NULL; hIvasRend->inputsMc[i].nonDiegeticPan = nonDiegeticPan; hIvasRend->inputsMc[i].nonDiegeticPanGain = nonDiegeticPanGain; @@ -4758,9 +5046,9 @@ ivas_error IVAS_REND_SetHeadRotation( } #ifdef IVAS_FLOAT_FIXED - if ((error = ivas_orient_trk_Process_fx(hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[sf_idx])) != IVAS_ERR_OK) + if ( ( error = ivas_orient_trk_Process_fx( hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[sf_idx] ) ) != IVAS_ERR_OK ) { - return error; + return error; } #else if ( ( error = ivas_orient_trk_Process( hIvasRend->headRotData.hOrientationTracker, rotQuat, FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES, &hIvasRend->headRotData.headPositions[sf_idx] ) ) != IVAS_ERR_OK ) @@ -4862,20 +5150,20 @@ ivas_error IVAS_REND_SetReferenceRotation( IVAS_QUATERNION_FX refRot_fx; refRot_fx.w_qfact = refRot_fx.x_qfact = refRot_fx.y_qfact = refRot_fx.z_qfact = Q29; - refRot_fx.w_fx = (Word32)float_to_fix( refRot.w, refRot_fx.w_qfact ); - refRot_fx.x_fx = (Word32)float_to_fix( refRot.x, refRot_fx.x_qfact ); - refRot_fx.y_fx = (Word32)float_to_fix( refRot.y, refRot_fx.y_qfact ); - refRot_fx.z_fx = (Word32)float_to_fix( refRot.z, refRot_fx.z_qfact ); + refRot_fx.w_fx = (Word32) float_to_fix( refRot.w, refRot_fx.w_qfact ); + refRot_fx.x_fx = (Word32) float_to_fix( refRot.x, refRot_fx.x_qfact ); + refRot_fx.y_fx = (Word32) float_to_fix( refRot.y, refRot_fx.y_qfact ); + refRot_fx.z_fx = (Word32) float_to_fix( refRot.z, refRot_fx.z_qfact ); error = ivas_orient_trk_SetReferenceRotation_fx( hIvasRend->headRotData.hOrientationTracker_fx, refRot_fx ); hIvasRend->headRotData.hOrientationTracker->refRot.w = me2f( hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.w_fx, 31 - hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.w_qfact ); hIvasRend->headRotData.hOrientationTracker->refRot.x = me2f( hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.x_fx, 31 - hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.x_qfact ); hIvasRend->headRotData.hOrientationTracker->refRot.y = me2f( hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.y_fx, 31 - hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.y_qfact ); hIvasRend->headRotData.hOrientationTracker->refRot.z = me2f( hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.z_fx, 31 - hIvasRend->headRotData.hOrientationTracker_fx->refRot_fx.z_qfact ); - if (error != IVAS_ERR_OK) + if ( error != IVAS_ERR_OK ) { - return error; + return error; } #else if ( ( error = ivas_orient_trk_SetReferenceRotation( hIvasRend->headRotData.hOrientationTracker, refRot ) ) != IVAS_ERR_OK ) @@ -5314,6 +5602,151 @@ static ivas_error chooseCrossfade_fx( } #endif +#ifdef IVAS_FLOAT_FIXED +static ivas_error rotateFrameMc_fx( + IVAS_REND_AudioBuffer inAudio, /* i : Input Audio buffer */ + AUDIO_CONFIG inConfig, /* i : Input Audio config */ + const LSSETUP_CUSTOM_STRUCT *pInCustomLs, /* i : Input Custom LS setup */ + const IVAS_REND_HeadRotData *headRotData, /* i : Head rotation data */ + const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i : Combined head and external orientations */ + rotation_gains_Word32 gains_prev, /* i/o: Previous frame rotation gains */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP structure */ + IVAS_REND_AudioBuffer outAudio /* o : Output Audio buffer */ +) +{ + Word16 i; + Word16 j; + const Word32 *crossfade; + Word16 num_subframes; + Word16 subframe_idx, subframe_len; + Word32 azimuth_fx, elevation_fx; + Word16 is_planar_setup, lfe_idx; + Word16 nchan; + Word16 ch_in, ch_out; + Word16 ch_in_woLFE, ch_out_woLFE; + Word32 *readPtr, *writePtr; + const Word32 *ls_azimuth, *ls_elevation; + rotation_matrix_fx Rmat_fx; + rotation_gains_Word32 gains; + Word32 tmp_gains[MAX_INPUT_CHANNELS]; + ivas_error error; + push_wmops( "rotateFrameMc_fx" ); + IF( ( error = chooseCrossfade_fx( headRotData, &crossfade ) ) != IVAS_ERR_OK ) // Q31 + { + return error; + } + num_subframes = ( hCombinedOrientationData != NULL ) ? ( *hCombinedOrientationData )->num_subframes : MAX_PARAM_SPATIAL_SUBFRAMES; + + IF( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM ) + { + IF( ( error = getAudioConfigNumChannels( inConfig, &nchan ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + nchan = pInCustomLs->num_spk + pInCustomLs->num_lfe; + } + + IF( ( error = getMcConfigValues_fx( inConfig, pInCustomLs, &ls_azimuth, &ls_elevation, &lfe_idx, &is_planar_setup ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* initialize gains to passthrough */ + FOR( ch_in = 0; ch_in < nchan; ch_in++ ) + { + set_val_Word32( gains[ch_in], 0, nchan ); + gains[ch_in][ch_in] = ONE_IN_Q30; + } + + /* subframe loop */ + + subframe_len = inAudio.config.numSamplesPerChannel / num_subframes; + FOR( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ ) + { + FOR( i = 0; i < 3; i++ ) + { + IF( hCombinedOrientationData != NULL ) + { + FOR( j = 0; j < 3; j++ ) + { + Rmat_fx[i][j] = ( *hCombinedOrientationData )->Rmat_fx[subframe_idx][i][j]; + } + } + ELSE + { + /* Set to identity */ + set_val_Word32( Rmat_fx[i], 0, 3 ); + Rmat_fx[i][i] = ONE_IN_Q30; + } + } + + FOR( ch_in = 0; ch_in < nchan; ch_in++ ) + { + /* skip LFE */ + if ( EQ_16( ch_in, lfe_idx ) ) + { + CONTINUE; + } + + /* input channel index without LFE */ + ch_in_woLFE = ( ( lfe_idx > 0 ) && ( ch_in >= lfe_idx ) ) ? ch_in - 1 : ch_in; + + /* gains for current subframe rotation */ + rotateAziEle_fixed( (Word16) L_shr( ls_azimuth[ch_in_woLFE], 22 ), (Word16) L_shr( ls_elevation[ch_in_woLFE], 22 ), &azimuth_fx, &elevation_fx, Rmat_fx, is_planar_setup ); + + IF( hEFAPdata != NULL && ( NE_32( ls_azimuth[ch_in_woLFE], azimuth_fx ) || NE_32( ls_elevation[ch_in_woLFE], elevation_fx ) ) ) + { + efap_determine_gains_fixed( hEFAPdata, tmp_gains, azimuth_fx, elevation_fx, EFAP_MODE_EFAP ); + + FOR( ch_out = 0; ch_out < nchan; ch_out++ ) + { + /* skip LFE */ + IF( EQ_16( ch_out, lfe_idx ) ) + { + CONTINUE; + } + + /* output channel index without LFE */ + ch_out_woLFE = ( ( lfe_idx > 0 ) && ( ch_out >= lfe_idx ) ) ? ch_out - 1 : ch_out; + + gains[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; // Q30 + } + } + } + + /* apply panning gains by mtx multiplication */ + FOR( ch_out = 0; ch_out < nchan; ch_out++ ) + { + FOR( ch_in = 0; ch_in < nchan; ch_in++ ) + { + writePtr = getSmplPtr_fx( outAudio, ch_out, subframe_idx * subframe_len ); + readPtr = getSmplPtr_fx( inAudio, ch_in, subframe_idx * subframe_len ); + /* crossfade with previous rotation gains */ + FOR( i = 0; i < subframe_len; i++ ) + { + *writePtr++ = + L_add( *writePtr, L_add( Mpy_32_32( ( *readPtr ), Mpy_32_32( ( ONE_IN_Q31 - crossfade[i] ), gains_prev[ch_in][ch_out] ) ), + Mpy_32_32( ( *readPtr ), Mpy_32_32( crossfade[i], gains[ch_in][ch_out] ) ) ) ); // Qinp -1 + readPtr++; + } + } + } + + /* move gains to gains_prev */ + FOR( i = 0; i < nchan; i++ ) + { + mvr2r_Word32( gains[i], gains_prev[i], nchan ); + } + } + + pop_wmops(); + return IVAS_ERR_OK; +} +#endif + static ivas_error rotateFrameMc( IVAS_REND_AudioBuffer inAudio, /* i : Input Audio buffer */ AUDIO_CONFIG inConfig, /* i : Input Audio config */ @@ -5341,7 +5774,6 @@ static ivas_error rotateFrameMc( rotation_gains gains; float tmp_gains[MAX_INPUT_CHANNELS]; ivas_error error; - push_wmops( "rotateFrameMc" ); if ( ( error = chooseCrossfade( headRotData, &crossfade ) ) != IVAS_ERR_OK ) { @@ -5457,6 +5889,7 @@ static ivas_error rotateFrameMc( pop_wmops(); return IVAS_ERR_OK; } + #ifdef IVAS_FLOAT_FIXED static ivas_error rotateFrameSba_fx( @@ -6495,7 +6928,7 @@ static ivas_error renderMcToBinaural( int8_t combinedOrientationEnabled; int16_t subframe_idx; float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; - int16_t i; + int16_t i, j; for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) { @@ -6536,22 +6969,31 @@ static ivas_error renderMcToBinaural( { tmpRotBuffer = mcInput->base.inputBuffer; tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); + set_val_Word32( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); - if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) { return error; } + for ( i = 0; i < tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels; i++ ) + { + + + tmpRotBuffer.data[i] = (float) tmpRotBuffer.data_fx[i] / ( 1 << ( *outAudio.pq_fact - 2 ) ); + } copyBufferTo2dArray( tmpRotBuffer, tmpRendBuffer ); free( tmpRotBuffer.data ); + free( tmpRotBuffer.data_fx ); } else { copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); } // Porting Crend_process function - Word16 j, nchan_out = 2, nchan_in = 12, subframe_len; + Word16 nchan_out = 2, nchan_in = 12, subframe_len; CREND_HANDLE hCrend; Word32 output_buffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; Word32 *output_fx[MAX_OUTPUT_CHANNELS]; @@ -7299,7 +7741,9 @@ static ivas_error renderInputMc( /* Apply input gain to new audio */ v_multc( inAudio.data, mcInput->base.gain, inAudio.data, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); - +#ifdef IVAS_FLOAT_FIXED + v_multc_fixed( inAudio.data_fx, mcInput->base.gain_fx, inAudio.data_fx, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); +#endif /* set combined orientation subframe info to start info */ ivas_combined_orientation_set_to_start_index( *( mcInput->base.ctx.pCombinedOrientationData ) ); @@ -8286,7 +8730,7 @@ static ivas_error renderActiveInputsMasa( { for ( i = 0; i < outAudio.config.numChannels * outAudio.config.numSamplesPerChannel; i++ ) { - outAudio.data[i] = (float) outAudio.data_fx[i] / ( 1 << *outAudio .pq_fact); + outAudio.data[i] = (float) outAudio.data_fx[i] / ( 1 << *outAudio.pq_fact ); } } #endif @@ -8308,7 +8752,7 @@ static ivas_error renderActiveInputsMasa( { for ( i = 0; i < outAudio.config.numChannels * outAudio.config.numSamplesPerChannel; i++ ) { - outAudio.data_fx[i] = (Word32) outAudio.data[i] *(1<< *outAudio.pq_fact ); + outAudio.data_fx[i] = (Word32) outAudio.data[i] * ( 1 << *outAudio.pq_fact ); } } #endif @@ -8903,8 +9347,9 @@ static ivas_error ivas_masa_ext_rend_dirac_rend_init( Word16 *frequency_axis_fx = (Word16 *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( Word16 ) ); ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, hSpatParamRendCom->num_freq_bands ); - FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++) { - hDirACRend->frequency_axis[i] = (float)frequency_axis_fx[i]; + FOR( i = 0; i < hSpatParamRendCom->num_freq_bands; i++ ) + { + hDirACRend->frequency_axis[i] = (float) frequency_axis_fx[i]; } #else ivas_dirac_dec_get_frequency_axis( hDirACRend->frequency_axis, output_Fs, hSpatParamRendCom->num_freq_bands ); @@ -9522,7 +9967,7 @@ static void freeMasaExtRenderer( #ifdef IVAS_FLOAT_FIXED vbap_free_data_fx( &hMasaExtRend->hVBAPdata ); #else - vbap_free_data(&hMasaExtRend->hVBAPdata); + vbap_free_data( &hMasaExtRend->hVBAPdata ); #endif } -- GitLab