diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index cb3dea6ff435fb43479e3b6c19b62a1edd211668..29b612680d3434fd517473ae416e7bfa1ba43b2d 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -1155,14 +1155,14 @@ static Word32 wrap_azi_fixed( Word32 azi = azi_deg; /* Wrap azimuth value */ - WHILE( azi > ANGLE_180_DEG_Q22 ) + WHILE( GT_32( azi, ANGLE_180_DEG_Q22 ) ) { - azi -= ANGLE_360_DEG_Q22; + azi = L_sub( azi, ANGLE_360_DEG_Q22 ); } - WHILE( azi <= -ANGLE_180_DEG_Q22 ) + WHILE( LE_32( azi, -ANGLE_180_DEG_Q22 ) ) { - azi += ANGLE_360_DEG_Q22; + azi = L_add( azi, ANGLE_360_DEG_Q22 ); } return azi; diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 54d1e312f836c48c3059359b438dc3fcd7d42b5c..d827fe3cd93e9179693621e899d209de17dd8c6a 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -5071,7 +5071,7 @@ void lsf_dec_fx( Word16 maximum_l( const Word32 *vec, /* i : input vector */ const Word16 lvec, /* i : length of input vector */ - Word32 *max /* o : maximum value in the input vector */ + Word32 *max_val /* o : maximum value in the input vector */ ); /*! r: index of the minimum value in the input vector */ diff --git a/lib_com/tools.c b/lib_com/tools.c index b00ea6b213b9851d9b2e946f491f1701234d606e..40996701c195c58fd53ebda30b70988a41f10464 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -568,7 +568,7 @@ int16_t maximum_s( Word16 maximum_l( const Word32 *vec, /* i : input vector */ const Word16 lvec, /* i : length of input vector */ - Word32 *max /* o : maximum value in the input vector */ + Word32 *max_val /* o : maximum value in the input vector */ ) { Word16 i, ind; @@ -579,16 +579,16 @@ Word16 maximum_l( FOR ( i = 1; i < lvec; i++ ) { - IF ( vec[i] > tmp ) + IF( GT_32( vec[i], tmp ) ) { ind = i; tmp = vec[i]; } } - IF ( max != NULL ) + IF( max_val != NULL ) { - *max = tmp; + *max_val = tmp; } return ind; @@ -722,7 +722,7 @@ Word16 minimum_l( for ( i = 1; i < lvec; i++ ) { - if ( vec[i] < tmp ) + if ( LT_32( vec[i], tmp ) ) { ind = i; tmp = vec[i]; @@ -836,7 +836,7 @@ Word32 dotp_fixed( FOR ( i = 1; i < n; i++ ) { - suma += Mpy_32_32( x[i], y[i] ); + suma = L_add( suma, Mpy_32_32( x[i], y[i] ) ); } return suma; @@ -1006,7 +1006,7 @@ void v_sub_fixed( FOR ( i = 0; i < N; i++ ) { - y[i] = L_sub( ( x1[i] >> hdrm ), ( x2[i] >> hdrm ) ); + y[i] = L_sub( L_shr( x1[i], hdrm ), L_shr( x2[i], hdrm ) ); } return; @@ -1840,11 +1840,11 @@ double anint( *-------------------------------------------------------------------*/ Word32 anint_fixed( Word32 x, Word16 exp ) { - IF ( x == 0 ) + IF( EQ_32( x, 0 ) ) { return 0; } - return ( x ) >= 0 ? L_add( x, ( 1 << ( exp - 1 ) ) ) : L_sub( x, ( 1 << ( exp - 1 ) ) ); + return GE_32( x, 0 ) ? L_add( x, L_shl( 1, exp - 1 ) ) : L_sub( x, L_shl( 1, exp - 1 ) ); } /*-------------------------------------------------------------------* @@ -1854,12 +1854,12 @@ Word32 anint_fixed( Word32 x, Word16 exp ) *-------------------------------------------------------------------*/ Word32 ceil_fixed(Word32 x, Word16 exp) { Word32 step; - step = x / ( 1 << exp ); - IF ( x % ( 1 << exp ) > 0 ) + step = x / L_shl( 1, exp ); + IF( GT_32( x % L_shl( 1, exp ), 0 ) ) { step++; } - return (step << exp); + return L_shl( step, exp ); } /*-------------------------------------------------------------------* diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 3818e6f386c4b1d539fab8836a6eb6511c6f7825..7b71eb3283d95dd760471ed4a350461a2cedc20d 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1064,11 +1064,7 @@ ivas_error ivas_binRenderer_open( } ELSE IF ( st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) { -#ifndef IVAS_FLOAT_FIXED IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 92525bfd3a60475cb0f18489ac97863184d25a14..6715d956c2b34ad1d4278fe182e6d2e3b5476de5 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -989,11 +989,7 @@ ivas_error ivas_init_decoder( /* init EFAP for custom LS output and set hTransSetup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { -#ifndef IVAS_FLOAT_FIXED IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hOutSetup.ls_azimuth, st_ivas->hOutSetup.ls_elevation, st_ivas->hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hOutSetup.ls_azimuth, st_ivas->hOutSetup.ls_elevation, st_ivas->hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -1423,11 +1419,7 @@ ivas_error ivas_init_decoder( /* init EFAP for custom LS setup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { -#ifndef IVAS_FLOAT_FIXED IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -1462,11 +1454,7 @@ ivas_error ivas_init_decoder( /* init EFAP for custom LS setup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { -#ifndef IVAS_FLOAT_FIXED IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -1506,11 +1494,7 @@ ivas_error ivas_init_decoder( /* init EFAP for custom LS setup */ IF ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { -#ifndef IVAS_FLOAT_FIXED IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF ( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hLsSetupCustom->ls_azimuth, st_ivas->hLsSetupCustom->ls_elevation, st_ivas->hLsSetupCustom->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -1734,11 +1718,7 @@ ivas_error ivas_init_decoder( { IF ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM && st_ivas->ivas_format == MC_FORMAT && ( st_ivas->hDecoderConfig->Opt_Headrotation || st_ivas->hDecoderConfig->Opt_ExternalOrientation ) ) { -#ifndef IVAS_FLOAT_FIXED IF ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF ( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index cf79d1fe8ff98851bc5a0743c75819ada45103df..8e11418b1030a8eb5f209d50e350d19b7c12075e 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -544,11 +544,7 @@ ivas_error ivas_param_ism_dec_open( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) ) { /* Initialize efap handle */ -#ifndef IVAS_FLOAT_FIXED if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF ( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index a728110f762930cc2975521346d94d18685ad606..1f51e9f19a16cb47b9a9c77ae55931b33e923f9a 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -65,11 +65,7 @@ ivas_error ivas_ism_renderer_open( if ( st_ivas->hIntSetup.is_loudspeaker_setup && st_ivas->hIntSetup.ls_azimuth != NULL && st_ivas->hIntSetup.ls_elevation != NULL && st_ivas->hEFAPdata == NULL ) { -#ifndef IVAS_FLOAT_FIXED if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - IF ( ( error = efap_init_data_fixed( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_rend/ivas_allrad_dec.c b/lib_rend/ivas_allrad_dec.c index b176e2d62334a16a5a74a2006dcc0dacf4844bdd..d4bafb471235cc29a6687bd724997449a76a8e85 100644 --- a/lib_rend/ivas_allrad_dec.c +++ b/lib_rend/ivas_allrad_dec.c @@ -213,7 +213,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( ELSE IF ( hOutSetup.is_loudspeaker_setup ) { /* init EFIP */ - IF ( ( error = efap_init_data_fixed( &( hEFAP ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, num_spk, EFAP_MODE_EFIP ) ) != IVAS_ERR_OK ) + IF ( ( error = efap_init_data( &( hEFAP ), hOutSetup.ls_azimuth, hOutSetup.ls_elevation, num_spk, EFAP_MODE_EFIP ) ) != IVAS_ERR_OK ) { return error; } @@ -239,7 +239,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( } /* t-design to real LS panning gains */ - efap_determine_gains_fixed( hEFAP, G_td_int, t_design_azi[i], t_design_ele[i] , EFAP_MODE_EFIP ); + efap_determine_gains_fixed( hEFAP, G_td_int, t_design_azi[i], t_design_ele[i] , EFAP_MODE_EFIP ); // G_td_int Q30 p_dec_mtx = *hoa_dec_mtx; FOR ( j = 0; j < num_spk; j++ ) @@ -247,8 +247,8 @@ ivas_error ivas_sba_get_hoa_dec_matrix( Word32 dec_mtx_temp = 0; FOR ( k = 0; k < num_harm; k++ ) { - dec_mtx_temp = Mpy_32_32( G_td_int[j], Y_td_int[k] ); - *( p_dec_mtx++ ) += ( (float) dec_mtx_temp ) / ( 1 << 25 ); + dec_mtx_temp = Mpy_32_32( G_td_int[j], Y_td_int[k] ); // Q27 + *( p_dec_mtx++ ) += ( (float) dec_mtx_temp ) / ( 1 << Q27 ); } p_dec_mtx += ( SBA_NHARM_HOA3 - num_harm ); } @@ -262,7 +262,7 @@ ivas_error ivas_sba_get_hoa_dec_matrix( FOR ( j = 0; j < num_harm; j++ ) { dec_mtx_temp_scale = Mpy_32_32( tmp_val, norm_sn3d_hoa3_int[j] ); - *( p_dec_mtx++ ) *= ((float)dec_mtx_temp_scale) / (1<<29); + *( p_dec_mtx++ ) *= ( (float) dec_mtx_temp_scale ) / ( 1 << Q29 ); } p_dec_mtx += ( SBA_NHARM_HOA3 - num_harm ); } diff --git a/lib_rend/ivas_efap.c b/lib_rend/ivas_efap.c index 7679cc2135c1b6dc15bf2a8ee014e974895457ed..39127bf9fe25c51a3d7ac339e05756933522ccc2 100644 --- a/lib_rend/ivas_efap.c +++ b/lib_rend/ivas_efap.c @@ -51,12 +51,17 @@ #ifndef IVAS_FLOAT_FIXED #define POLY_THRESH 1e-4f #else -#define POLY_THRESH 53687 //Q29 +#define POLY_THRESH_Q29 53687 // Q29 +#define POLY_THRESH_Q28 26843 // Q28 #endif #ifdef IVAS_FLOAT_FIXED +#define Q22_1 4194304 +#define Q22_45_DEG 188743680 #define Q22_90_DEG 377487360 #define Q22_180_DEG 754974720 #define Q22_360_DEG 1509949440 +#define Q22_120_DEG 503316480 +#define Q22_240_DEG 1006632960 #endif /*-----------------------------------------------------------------------* @@ -65,58 +70,35 @@ static ivas_error poly_init( EFAP *efap, const int16_t efip_flag ); -static ivas_error sphere_triangulation( const int16_t numSpk, EFAP_VERTEX_DATA *vtxData, EFAP_POLYSET_DATA *polyData, float ***dmTranspose, int16_t *numTot, const int16_t efip_flag ); - #ifndef IVAS_FLOAT_FIXED +static ivas_error sphere_triangulation( const int16_t numSpk, EFAP_VERTEX_DATA *vtxData, EFAP_POLYSET_DATA *polyData, float ***dmTranspose, int16_t *numTot, const int16_t efip_flag ); static void initial_polyeder( EFAP_VERTEX_DATA *vtxData, EFAP_LS_TRIANGLE *triArray, int16_t *numTri, int16_t *vtxInHull ); -#else -static void initial_polyeder_fixed( EFAP_VERTEX_DATA *vtxData, EFAP_LS_TRIANGLE *triArray, Word16 *numTri, Word16 *vtxInHull ); -#endif - -#ifndef IVAS_FLOAT_FIXED static void add_ghost_speakers( EFAP_VERTEX *vertexArray, int16_t *numVtx, const int16_t efip_flag ); +static void add_vertex_to_convex_hull( const EFAP_VERTEX_DATA *vtxData, const int16_t vtxIdx, int16_t *vtxInHull, EFAP_LS_TRIANGLE *triArray, int16_t *szTri ); #else +static ivas_error sphere_triangulation( const int16_t numSpk, EFAP_VERTEX_DATA *vtxData, EFAP_POLYSET_DATA *polyData, Word32 ***dmTranspose, int16_t *numTot, const int16_t efip_flag ); +static void initial_polyeder_fixed( EFAP_VERTEX_DATA *vtxData, EFAP_LS_TRIANGLE *triArray, Word16 *numTri, Word16 *vtxInHull ); static void add_ghost_speakers_fixed( EFAP_VERTEX *vertexArray, Word16 *numVtx, const Word16 efip_flag ); +static void add_vertex_to_convex_hull_fixed( const EFAP_VERTEX_DATA *vtxData, const Word16 vtxIdx, Word16 *vtxInHull, EFAP_LS_TRIANGLE *triArray, Word16 *szTri ); #endif static void sort_vertices( const EFAP_VERTEX *vertexArray, const int16_t *numVtx, int16_t *order ); -#ifndef IVAS_FLOAT_FIXED -static void add_vertex_to_convex_hull( const EFAP_VERTEX_DATA *vtxData, const int16_t vtxIdx, int16_t *vtxInHull, EFAP_LS_TRIANGLE *triArray, int16_t *szTri ); -#else -static void add_vertex_to_convex_hull_fixed( const EFAP_VERTEX_DATA *vtxData, const Word16 vtxIdx, Word16 *vtxInHull, EFAP_LS_TRIANGLE *triArray, Word16 *szTri ); -#endif - static void visible_edges( const EFAP_LS_TRIANGLE *triArray, const Word16 *visible, const Word16 numSurface, Word16 *numEdges, Word16 *edges ); #ifndef IVAS_FLOAT_FIXED static void flip_plane( const EFAP_VERTEX *vtxArray, int16_t *surface, const float centroid[3] ); -#else -static void flip_plane_fixed( const EFAP_VERTEX *vtxArray, Word16 *surface, const Word32 centroid[3] ); -#endif - -#ifndef IVAS_FLOAT_FIXED static void remap_ghosts( EFAP_VERTEX *vtxArray, EFAP_LS_TRIANGLE *triArray, int16_t numSpk, int16_t *numVertex, int16_t numTri, float **downmixMatrix ); -#else -static void remap_ghosts_fixed( EFAP_VERTEX *vtxArray, EFAP_LS_TRIANGLE *triArray, Word16 numSpk, Word16 *numVertex, Word16 numTri, float **downmixMatrix ); -#endif - -#ifndef IVAS_FLOAT_FIXED static void vertex_init( const float *aziSpk, const float *eleSpk, EFAP_VERTEX_DATA *efapVtxData ); -#else -static void vertex_init_fixed( const Word32 *aziSpk, const Word32 *eleSpk, EFAP_VERTEX_DATA *efapVtxData ); -#endif - static void efap_panning( const float azi, const float ele, const EFAP_POLYSET_DATA *polyData, float *bufferL ); -#ifdef IVAS_FLOAT_FIXED -static void efap_panning_fixed( const Word32 azi, const Word32 ele, const EFAP_POLYSET_DATA *polyData, float *bufferL ); -#endif static void get_poly_gains( const float azi, const float ele, const float aziPoly[EFAP_MAX_CHAN_NUM], const float elePoly[EFAP_MAX_CHAN_NUM], const int16_t numChan, float *buffer ); -#ifdef IVAS_FLOAT_FIXED -static void get_poly_gains_fixed( const Word32 azi, const Word32 ele, const Word32 aziPoly[EFAP_MAX_CHAN_NUM], const Word32 elePoly[EFAP_MAX_CHAN_NUM], const Word16 numChan, Word32 *buffer ); -#endif static float get_tri_gain( const float A[2], const float B[2], const float C[2], const float P_minus_A[2] ); -#ifdef IVAS_FLOAT_FIXED +#else +static void flip_plane_fixed( const EFAP_VERTEX *vtxArray, Word16 *surface, const Word32 centroid[3] ); +static void remap_ghosts_fixed( EFAP_VERTEX *vtxArray, EFAP_LS_TRIANGLE *triArray, Word16 numSpk, Word16 *numVertex, Word16 numTri, Word32 **downmixMatrix ); +static void vertex_init_fixed( const Word32 *aziSpk, const Word32 *eleSpk, EFAP_VERTEX_DATA *efapVtxData ); +static void efap_panning_fixed( const Word32 azi, const Word32 ele, const EFAP_POLYSET_DATA *polyData, Word32 *bufferL ); +static void get_poly_gains_fixed( const Word32 azi, const Word32 ele, const Word32 aziPoly[EFAP_MAX_CHAN_NUM], const Word32 elePoly[EFAP_MAX_CHAN_NUM], const Word16 numChan, Word32 *buffer ); static Word32 get_tri_gain_fixed( const Word32 A[2], const Word32 B[2], const Word32 C[2], const Word32 P_minus_A[2] ); #endif @@ -134,22 +116,16 @@ static void efap_sort_s( int16_t *x, int16_t *idx, const int16_t len ); #ifndef IVAS_FLOAT_FIXED static float vertex_distance( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE tri, const int16_t vtxIdx ); +static float point_plane_distance( const float P1[3], const float P2[3], const float P3[3], const float X[3] ); +static float point_poly_distance( const EFAP_POLYSET poly, const float X[3] ); +static void efap_crossp( const float *v1, const float *v2, float *v ); #else static Word32 vertex_distance_fixed( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE tri, const Word16 vtxIdx ); -#endif - -static float point_plane_distance( const float P1[3], const float P2[3], const float P3[3], const float X[3] ); -#ifdef IVAS_FLOAT_FIXED static Word32 point_plane_distance_fixed( const Word32 P1[3], const Word32 P2[3], const Word32 P3[3], const Word32 X[3] ); -#endif -static float point_poly_distance( const EFAP_POLYSET poly, const float X[3] ); -#ifdef IVAS_FLOAT_FIXED static Word32 point_poly_distance_fixed( const EFAP_POLYSET poly, const Word32 X[3] ); -#endif -static void efap_crossp( const float *v1, const float *v2, float *v ); -#ifdef IVAS_FLOAT_FIXED static void efap_crossp_fixed( const Word32 *v1, const Word32 *v2, Word32 *v ); #endif + static int16_t find_int_in_tri( const EFAP_LS_TRIANGLE *tri, const int16_t n, const int16_t r, int16_t *pos ); static void remove_vertex( EFAP_VERTEX *vtxArray, const int16_t idx, const int16_t L ); @@ -158,7 +134,7 @@ static int16_t get_neighbours( const EFAP_LS_TRIANGLE *triArray, const int16_t v #ifndef IVAS_FLOAT_FIXED static void matrix_times_row( float mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], const float *vec, const int16_t L, float *out ); #else -static void matrix_times_row_int( Word32 mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], const Word32 *vec, const Word16 L, Word32 *out ); +static void matrix_times_row_fixed( Word32 mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], const Word32 *vec, const Word16 L, Word32 *out ); #endif static void tri_to_poly( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, const int16_t numVtx, const int16_t numTri, int16_t sortedChan[EFAP_MAX_POLY_SET][EFAP_MAX_CHAN_NUM], int16_t *outLengthPS, int16_t outLengthSorted[EFAP_MAX_POLY_SET] ); @@ -166,41 +142,31 @@ static int16_t compare_poly( int16_t *old, int16_t lenOld, int16_t *new, int16_t #ifndef IVAS_FLOAT_FIXED static void sort_channels_vertex( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, int16_t channels[EFAP_MAX_CHAN_NUM], const int16_t lengthChannels, int16_t idxTri ); -#else -static void sort_channels_vertex_fixed( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, Word16 channels[EFAP_MAX_CHAN_NUM], const Word16 lengthChannels, Word16 idxTri ); -#endif -#ifndef IVAS_FLOAT_FIXED static float efap_fmodf( const float x, const float y ); +static int16_t get_poly_num( const float P[2], const EFAP_POLYSET_DATA *polyData ); +static int16_t in_poly( const float P[2], const EFAP_POLYSET poly ); +static int16_t in_tri( float A[2], float B[2], float C[2], float P_minus_A[2] ); +static void sph2cart( const float azi, const float ele, float *pos ); #else +static void sort_channels_vertex_fixed( const EFAP_VERTEX *vtxArray, const EFAP_LS_TRIANGLE *triArray, Word16 channels[EFAP_MAX_CHAN_NUM], const Word16 lengthChannels, Word16 idxTri ); static Word32 efap_lmodl( const Word32 x, const Word32 y ); -#endif -static int16_t get_poly_num( const float P[2], const EFAP_POLYSET_DATA *polyData ); -#ifdef IVAS_FLOAT_FIXED static Word16 get_poly_num_fixed( const Word32 P[2], const EFAP_POLYSET_DATA *polyData ); -#endif -static int16_t in_poly( const float P[2], const EFAP_POLYSET poly ); -#ifdef IVAS_FLOAT_FIXED static Word16 in_poly_fixed( const Word32 P[2], const EFAP_POLYSET poly ); -#endif -static int16_t in_tri( float A[2], float B[2], float C[2], float P_minus_A[2] ); -#ifdef IVAS_FLOAT_FIXED static Word16 in_tri_fixed( Word32 A[2], Word32 B[2], Word32 C[2], Word32 P_minus_A[2] ); -#endif -static void sph2cart( const float azi, const float ele, float *pos ); -#ifdef IVAS_FLOAT_FIXED static void sph2cart_fixed( const Word32 azi, const Word32 ele, Word32 *pos ); #endif + /*-----------------------------------------------------------------------* * Global function definitions *-----------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------* * efap_init_data() * * Wrap the internal functions to initialize the EFAP data structure *-------------------------------------------------------------------------*/ -#ifndef IVAS_FLOAT_FIXED ivas_error efap_init_data( EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ @@ -209,6 +175,7 @@ ivas_error efap_init_data( const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ ) { +#ifndef IVAS_FLOAT_FIXED /* Handle instance declaration */ EFAP *efap; ivas_error error; @@ -284,8 +251,18 @@ ivas_error efap_init_data( *hEFAPdata = efap; return error; -} #else + /* Following conversion should be removed once all inputs are converted to Word32 azi and ele angles */ + Word32 azi_inp[MAX_OUTPUT_CHANNELS], ele_inp[MAX_OUTPUT_CHANNELS]; + FOR( int spk_idx = 0; spk_idx < num_speaker_nodes; spk_idx++ ) + { + azi_inp[spk_idx] = (Word32) ( speaker_node_azi_deg[spk_idx] * Q22_1 ); + ele_inp[spk_idx] = (Word32) ( speaker_node_ele_deg[spk_idx] * Q22_1 ); + } + return efap_init_data_fixed( hEFAPdata, azi_inp, ele_inp, num_speaker_nodes, efap_mode ); +#endif +} +#ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * efap_init_data_fixed() * @@ -294,8 +271,8 @@ ivas_error efap_init_data( ivas_error efap_init_data_fixed( EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ - const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ - const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ + const Word32 *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) (Q22) */ + const Word32 *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) (Q22) */ const Word16 num_speaker_nodes, /* i : number of speaker nodes in the set */ const Word16 efap_mode /* i : indicates whether EFAP or EFIP is used */ ) @@ -340,7 +317,7 @@ ivas_error efap_init_data_fixed( } /* Memory allocation for the tmp buffer short */ - IF( ( efap->bufferShort = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) + IF( ( efap->bufferShort_fx = (Word32 *) malloc( num_speaker_nodes * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); } @@ -355,13 +332,8 @@ ivas_error efap_init_data_fixed( efap->vtxData.numVtx = num_speaker_nodes; /* Loudspeaker configuration */ - // mvr2r( speaker_node_azi_deg, efap->aziSpk, num_speaker_nodes ); - // mvr2r( speaker_node_ele_deg, efap->eleSpk, num_speaker_nodes ); - FOR ( int spk_idx = 0; spk_idx < num_speaker_nodes; spk_idx++ ) - { - efap->aziSpk[spk_idx] = (Word32) ( speaker_node_azi_deg[spk_idx] * ( 1 << Q22 ) ); - efap->eleSpk[spk_idx] = (Word32) ( speaker_node_ele_deg[spk_idx] * ( 1 << Q22 ) ); - } + mvl2l( speaker_node_azi_deg, efap->aziSpk, num_speaker_nodes ); + mvl2l( speaker_node_ele_deg, efap->eleSpk, num_speaker_nodes ); /* Initialization of the vertex */ vertex_init_fixed( efap->aziSpk, efap->eleSpk, &efap->vtxData ); @@ -373,7 +345,7 @@ ivas_error efap_init_data_fixed( } /* Memory allocation for the tmp buffer long */ - IF( ( efap->bufferLong = (float *) malloc( efap->vtxData.numVtx * sizeof( float ) ) ) == NULL ) + IF( ( efap->bufferLong_fx = (Word32 *) malloc( efap->vtxData.numVtx * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferL\n" ) ); } @@ -398,6 +370,7 @@ void efap_determine_gains( const int16_t efap_mode /* i : indicates whether EFAP or EFIP is used */ ) { +#ifndef IVAS_FLOAT_FIXED int16_t i, j; float azi_wrap, ele_wrap; float normBuffer; @@ -457,6 +430,17 @@ void efap_determine_gains( mvr2r( hEFAPdata->bufferShort, gains, hEFAPdata->numSpk ); return; +#else + /* block to be removed once efap_determine_gains_fixed() is integrated into all calling places */ + const Word32 azi_fx = (Word32) ( azi_deg * Q22_1 ); + const Word32 ele_fx = (Word32) ( ele_deg * Q22_1 ); + Word32 gains_fx[MAX_OUTPUT_CHANNELS]; + efap_determine_gains_fixed( hEFAPdata, gains_fx, azi_fx, ele_fx, efap_mode ); + FOR( Word32 i = 0; i < hEFAPdata->numSpk; i++ ) + { + gains[i] = ( (float) gains_fx[i] ) / L_shl( 1, Q30 ); + } +#endif } #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* @@ -479,65 +463,66 @@ void efap_determine_gains_fixed( { Word16 i, j; Word32 azi_wrap_int, ele_wrap_int; - float normBuffer, gain_temp[MAX_OUTPUT_CHANNELS]; + Word32 normBuffer; /* Resetting bufferShort and bufferLong */ - set_zero( hEFAPdata->bufferShort, hEFAPdata->numSpk ); - set_zero( hEFAPdata->bufferLong, hEFAPdata->vtxData.numVtx ); + set_l( hEFAPdata->bufferShort_fx, 0, hEFAPdata->numSpk ); + set_l( hEFAPdata->bufferLong_fx, 0, hEFAPdata->vtxData.numVtx ); /* Wrap angles to correct range */ panning_wrap_angles_fixed( azi_deg, ele_deg, &azi_wrap_int, &ele_wrap_int ); /* Panning */ - efap_panning_fixed( azi_wrap_int, ele_wrap_int, &hEFAPdata->polyData, hEFAPdata->bufferLong ); + efap_panning_fixed( azi_wrap_int, ele_wrap_int, &hEFAPdata->polyData, hEFAPdata->bufferLong_fx ); IF( efap_mode == EFAP_MODE_EFAP ) { - normBuffer = 0.f; + normBuffer = 0; FOR( j = 0; j < hEFAPdata->numSpk; ++j ) { - hEFAPdata->bufferShort[j] = 0.f; + hEFAPdata->bufferShort_fx[j] = 0; /* Multiplying by the downmixMatrix */ FOR( i = 0; i < hEFAPdata->vtxData.numVtx; ++i ) { - hEFAPdata->bufferShort[j] += hEFAPdata->bufferLong[i] * hEFAPdata->dmTranspose[i][j]; + hEFAPdata->bufferShort_fx[j] = L_add_sat( hEFAPdata->bufferShort_fx[j], L_shr( Mpy_32_32( hEFAPdata->bufferLong_fx[i], hEFAPdata->dmTranspose_fx[i][j] ), Q1 ) ); // Q30 } - normBuffer = normBuffer + hEFAPdata->bufferShort[j] * hEFAPdata->bufferShort[j]; + normBuffer = L_add_sat( normBuffer, Mpy_32_32( hEFAPdata->bufferShort_fx[j], hEFAPdata->bufferShort_fx[j] ) ); // Q29 } - normBuffer = inv_sqrt( normBuffer ); + Word16 exp = 2; + normBuffer = ISqrt32( normBuffer, &exp ); FOR( j = 0; j < hEFAPdata->numSpk; ++j ) { - hEFAPdata->bufferShort[j] *= normBuffer; + hEFAPdata->bufferShort_fx[j] = Mpy_32_32( hEFAPdata->bufferShort_fx[j], normBuffer ); + hEFAPdata->bufferShort_fx[j] = L_shl( hEFAPdata->bufferShort_fx[j], exp ); // Q30 } } ELSE { - normBuffer = 0.f; + normBuffer = 0; FOR( j = 0; j < hEFAPdata->numSpk; ++j ) { - hEFAPdata->bufferShort[j] = 0.f; + hEFAPdata->bufferShort_fx[j] = 0; /* Multiplying by the downmixMatrix */ FOR( i = 0; i < hEFAPdata->vtxData.numVtx; ++i ) { - hEFAPdata->bufferShort[j] += hEFAPdata->bufferLong[i] * hEFAPdata->dmTranspose[i][j]; + hEFAPdata->bufferShort_fx[j] = L_add_sat( hEFAPdata->bufferShort_fx[j], L_shr( Mpy_32_32( hEFAPdata->bufferLong_fx[i], hEFAPdata->dmTranspose_fx[i][j] ), Q1 ) ); // Q30 } - normBuffer = normBuffer + hEFAPdata->bufferShort[j]; + normBuffer = L_add_sat( normBuffer, L_shr( hEFAPdata->bufferShort_fx[j], Q1 ) ); // Q29 } - normBuffer = 1.f / normBuffer; + Word16 exp = 2; + normBuffer = Inv16( (Word16) L_shr( normBuffer, Q16 ), &exp ); FOR( j = 0; j < hEFAPdata->numSpk; ++j ) { - hEFAPdata->bufferShort[j] = sqrtf( hEFAPdata->bufferShort[j] * normBuffer ); + Word16 exp_temp = exp + 1; + hEFAPdata->bufferShort_fx[j] = Sqrt32( Mpy_32_16_1( hEFAPdata->bufferShort_fx[j], (Word16) normBuffer ), &exp_temp ); + hEFAPdata->bufferShort_fx[j] = L_shl( hEFAPdata->bufferShort_fx[j], exp_temp - 1 ); // Q30 } } /* Copy gains to output */ - mvr2r( hEFAPdata->bufferShort, gain_temp, hEFAPdata->numSpk ); - FOR( i = 0; i < hEFAPdata->numSpk; i++ ) - { - gains[i] = (Word32) ( gain_temp[i] * ( 1 << Q28 ) ); - } + mvl2l( hEFAPdata->bufferShort_fx, gains, hEFAPdata->numSpk ); return; } @@ -555,7 +540,7 @@ void efap_free_data( int16_t i, dim1; void **p_dmTranspose; - if ( hEFAPdata == NULL || *hEFAPdata == NULL ) + IF( hEFAPdata == NULL || *hEFAPdata == NULL ) { return; } @@ -574,7 +559,7 @@ void efap_free_data( free( ( *hEFAPdata )->vtxData.vtxOrder ); ( *hEFAPdata )->vtxData.vtxOrder = NULL; - +#ifndef IVAS_FLOAT_FIXED free( ( *hEFAPdata )->bufferLong ); ( *hEFAPdata )->bufferLong = NULL; @@ -582,7 +567,16 @@ void efap_free_data( ( *hEFAPdata )->bufferShort = NULL; p_dmTranspose = (void **) ( *hEFAPdata )->dmTranspose; - for ( i = 0; i < dim1; i++ ) +#else + free( ( *hEFAPdata )->bufferLong_fx ); + ( *hEFAPdata )->bufferLong_fx = NULL; + + free( ( *hEFAPdata )->bufferShort_fx ); + ( *hEFAPdata )->bufferShort_fx = NULL; + + p_dmTranspose = (void **) ( *hEFAPdata )->dmTranspose_fx; +#endif + FOR( i = 0; i < dim1; i++ ) { free( p_dmTranspose[i] ); } @@ -629,26 +623,30 @@ static ivas_error poly_init( /* Safety Check */ assert( efap != NULL && "EFAP: efap == NULL" ); - FOR ( n = 0; n < EFAP_MAX_POLY_SET; n++ ) + FOR( n = 0; n < EFAP_MAX_POLY_SET; n++ ) { set_s( sortedChan[n], 0, EFAP_MAX_CHAN_NUM ); } /* Computing the different ghost vertex, the downmix matrix and the triangle array */ - IF ( ( error = sphere_triangulation( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) +#ifndef IVAS_FLOAT_FIXED + IF( ( error = sphere_triangulation( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) +#else + IF( ( error = sphere_triangulation( efap->numSpk, &efap->vtxData, &efap->polyData, &efap->dmTranspose_fx, &efap->numTot, efip_flag ) ) != IVAS_ERR_OK ) +#endif { return error; } /* set isNaN for ghost loudspeakers */ - FOR ( n = 0; n < efap->vtxData.numVtx; ++n ) + FOR( n = 0; n < efap->vtxData.numVtx; ++n ) { #ifndef IVAS_FLOAT_FIXED - IF ( efap->vtxData.vertexArray[n].ele > 90.0 - 1e-6 || - efap->vtxData.vertexArray[n].ele < 1e-6 - 90.0 ) + IF( efap->vtxData.vertexArray[n].ele > 90.0 - 1e-6 || + efap->vtxData.vertexArray[n].ele < 1e-6 - 90.0 ) #else - IF ( efap->vtxData.vertexArray[n].ele > Q22_90_DEG - 4 || - efap->vtxData.vertexArray[n].ele < 4 - Q22_90_DEG ) + IF( GT_32( efap->vtxData.vertexArray[n].ele, L_sub( Q22_90_DEG, 4 ) ) || + LT_32( efap->vtxData.vertexArray[n].ele, L_sub( 4, Q22_90_DEG ) ) ) #endif { efap->vtxData.vertexArray[n].isNaN = 1; @@ -661,12 +659,12 @@ static ivas_error poly_init( /* Completing the polyData Structure */ finalLength = -1; - FOR ( n = 0; n < lengthTri2PolyPS; ++n ) + FOR( n = 0; n < lengthTri2PolyPS; ++n ) { m = finalLength + 1; /* Complete the fields of the polygon */ - FOR ( j = 0; j < lengthTri2PolySorted[n]; ++j ) + FOR( j = 0; j < lengthTri2PolySorted[n]; ++j ) { efap->polyData.polysetArray[m].chan[j] = sortedChan[n][j]; efap->polyData.polysetArray[m].polyAzi[j] = efap->vtxData.vertexArray[sortedChan[n][j]].azi; @@ -688,10 +686,10 @@ static ivas_error poly_init( #ifndef IVAS_FLOAT_FIXED if ( ( tmpMax - tmpMin ) > 180 ) #else - IF ( ( tmpMax - tmpMin ) > Q22_180_DEG /*180 in Q22*/ ) + IF( GT_32( L_sub( tmpMax, tmpMin ), Q22_180_DEG ) /*180 in Q22*/ ) #endif { - FOR ( j = 0; j < lengthTri2PolySorted[n]; ++j ) + FOR( j = 0; j < lengthTri2PolySorted[n]; ++j ) { assert( ( m + 2 < EFAP_MAX_POLY_SET ) && "EFAP: maximum polygons exceeded!" ); @@ -701,7 +699,7 @@ static ivas_error poly_init( efap->polyData.polysetArray[m + 2].polyAzi[j] = efap->polyData.polysetArray[m + 1].polyAzi[j] - 360; #else efap->polyData.polysetArray[m + 1].polyAzi[j] = efap_lmodl( efap->polyData.polysetArray[m].polyAzi[j], Q22_360_DEG ); - efap->polyData.polysetArray[m + 2].polyAzi[j] = efap->polyData.polysetArray[m + 1].polyAzi[j] - Q22_360_DEG; + efap->polyData.polysetArray[m + 2].polyAzi[j] = L_sub( efap->polyData.polysetArray[m + 1].polyAzi[j], Q22_360_DEG ); #endif /* Copy the rest of the fields */ @@ -739,9 +737,13 @@ static ivas_error sphere_triangulation( const int16_t numSpk, /* i : Number of speakers */ EFAP_VERTEX_DATA *vtxData, /* i/o: Vertex data structure */ EFAP_POLYSET_DATA *polyData, /* o : Polygon data structure */ - float ***dmTranspose, /* o : Transpose of the downmix matrix */ - int16_t *numTot, /* o : Number of speakers (real + ghost) */ - const int16_t efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ +#ifndef IVAS_FLOAT_FIXED + float ***dmTranspose, /* o : Transpose of the downmix matrix */ +#else + Word32 ***dmTranspose_fx, /* o : Transpose of the downmix matrix */ +#endif + int16_t *numTot, /* o : Number of speakers (real + ghost) */ + const int16_t efip_flag /* i : flag to indicate whether initialization is for EFIP (used for ALLRAD) */ ) { int16_t i; @@ -758,7 +760,7 @@ static ivas_error sphere_triangulation( #endif /* Sort the vertices according to their index */ - IF ( ( vtxData->vtxOrder = (int16_t *) malloc( vtxData->numVtx * sizeof( int16_t ) ) ) == NULL ) + IF( ( vtxData->vtxOrder = (int16_t *) malloc( vtxData->numVtx * sizeof( int16_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Order\n" ) ); } @@ -773,7 +775,7 @@ static ivas_error sphere_triangulation( #endif /* Add the vertex to the convex hull */ - FOR ( i = 0; i < vtxData->numVtx; ++i ) + FOR( i = 0; i < vtxData->numVtx; ++i ) { #ifndef IVAS_FLOAT_FIXED add_vertex_to_convex_hull( vtxData, vtxData->vtxOrder[i], &vtxInHull[0], polyData->triArray, &polyData->numTri ); @@ -785,7 +787,11 @@ static ivas_error sphere_triangulation( assert( polyData->numTri != 0 && "EFAP: failed to construct convex hull!" ); /* Allocate the DM matrix transpose */ - IF ( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( float * ) ) ) == NULL ) +#ifndef IVAS_FLOAT_FIXED + IF( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( float * ) ) ) == NULL ) +#else + IF( ( p_dmTranspose = malloc( vtxData->numVtx * sizeof( Word32 * ) ) ) == NULL ) +#endif { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); } @@ -793,20 +799,28 @@ static ivas_error sphere_triangulation( /* Store the value of numVtx to be used for freeing later (numVtx will change after remap_ghosts() ) */ *numTot = vtxData->numVtx; - FOR ( i = 0; i < vtxData->numVtx; i++ ) + FOR( i = 0; i < vtxData->numVtx; i++ ) { - IF ( ( p_dmTranspose[i] = malloc( numSpk * sizeof( float ) ) ) == NULL ) +#ifndef IVAS_FLOAT_FIXED + IF( ( p_dmTranspose[i] = malloc( numSpk * sizeof( float ) ) ) == NULL ) +#else + IF( ( p_dmTranspose[i] = malloc( numSpk * sizeof( Word32 ) ) ) == NULL ) +#endif { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "EFAP: can not allocate memory for dmTranspose\n" ) ); } } +#ifndef IVAS_FLOAT_FIXED *dmTranspose = (float **) p_dmTranspose; +#else + *dmTranspose_fx = (Word32 **) p_dmTranspose; +#endif /* Remap Ghosts */ #ifndef IVAS_FLOAT_FIXED remap_ghosts( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose ); #else - remap_ghosts_fixed( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose ); + remap_ghosts_fixed( vtxData->vertexArray, polyData->triArray, numSpk, &vtxData->numVtx, polyData->numTri, *dmTranspose_fx ); #endif return IVAS_ERR_OK; @@ -975,14 +989,14 @@ static void initial_polyeder_fixed( numVtx = vtxData->numVtx; /* seed vertices */ - FOR ( i = 0; i < 4; i++ ) + FOR( i = 0; i < 4; i++ ) { tetrahedron[i] = i; } /* 1. attempt to create an edge with nonzero length */ - WHILE ( ( vtxData->vertexArray[tetrahedron[0]].azi == vtxData->vertexArray[tetrahedron[1]].azi ) && - ( vtxData->vertexArray[tetrahedron[0]].ele == vtxData->vertexArray[tetrahedron[1]].ele ) ) + WHILE( EQ_32( vtxData->vertexArray[tetrahedron[0]].azi, vtxData->vertexArray[tetrahedron[1]].azi ) && + EQ_32( vtxData->vertexArray[tetrahedron[0]].ele, vtxData->vertexArray[tetrahedron[1]].ele ) ) { tetrahedron[1]++; assert( tetrahedron[1] < numVtx && "EFAP: convex hull construction failed, vertices are coincident!" ); @@ -991,15 +1005,15 @@ static void initial_polyeder_fixed( /* 2. attempt to create a triangle with nonzero area */ tmp = 0; v_sub_fixed( vtxData->vertexArray[tetrahedron[1]].pos, vtxData->vertexArray[tetrahedron[0]].pos, tmp1, 3, 1 ); - WHILE ( tetrahedron[2] < numVtx ) + WHILE( LT_16( tetrahedron[2], numVtx ) ) { v_sub_fixed( vtxData->vertexArray[tetrahedron[2]].pos, vtxData->vertexArray[tetrahedron[0]].pos, tmp2, 3, 1 ); - efap_crossp_fixed( tmp1, tmp2, tmpCross ); //tmpCross Q29 - FOR ( i = 0; i < 3; i++ ) + efap_crossp_fixed( tmp1, tmp2, tmpCross ); // tmpCross Q29 + FOR( i = 0; i < 3; i++ ) { - tmp += Mpy_32_32( tmpCross[i], tmpCross[i] ); //tmp Q27 + tmp = L_add( tmp, Mpy_32_32( tmpCross[i], tmpCross[i] ) ); // tmp Q27 } - IF ( L_abs( tmp << 2 ) > Mpy_32_32( ( POLY_THRESH << 1 ), ( POLY_THRESH << 1 ) ) ) /* compare tmp against POLY_THRESH^2 instead of sqrtf(tmp) */ + IF( GT_32( L_abs( tmp ), Mpy_32_32( POLY_THRESH_Q29, POLY_THRESH_Q29 ) ) ) /* compare tmp against POLY_THRESH^2 instead of sqrtf(tmp) */ { break; } @@ -1009,11 +1023,11 @@ static void initial_polyeder_fixed( /* 3. attempt to create a tetrahedron with nonzero volume */ tmp = 0; - WHILE ( tetrahedron[3] < numVtx ) + WHILE( LT_16( tetrahedron[3], numVtx ) ) { - v_sub_fixed( vtxData->vertexArray[tetrahedron[3]].pos, vtxData->vertexArray[tetrahedron[0]].pos, tmp3, 3, 1 ); //tmp3 Q30 - tmp = dotp_fixed( tmp3, tmpCross, 3 ); //tmp Q28 - IF ( L_abs( tmp ) > ( POLY_THRESH >> Q1 ) ) + v_sub_fixed( vtxData->vertexArray[tetrahedron[3]].pos, vtxData->vertexArray[tetrahedron[0]].pos, tmp3, 3, 1 ); // tmp3 Q30 + tmp = dotp_fixed( tmp3, tmpCross, 3 ); // tmp Q28 + IF( GT_32( L_abs( tmp ), POLY_THRESH_Q28 ) ) { break; } @@ -1022,12 +1036,12 @@ static void initial_polyeder_fixed( assert( tetrahedron[3] < numVtx && "EFAP: convex hull construction failed, vertices are coplanar!" ); /* 4. compute the centroid of the initial tetrahedron */ - FOR ( i = 0; i < 4; i++ ) + FOR( i = 0; i < 4; i++ ) { vtxInHull[tetrahedron[i]] = 1; /* set vertex as added to hull*/ - centroid[0] += vtxData->vertexArray[tetrahedron[i]].pos[0] >> 2; - centroid[1] += vtxData->vertexArray[tetrahedron[i]].pos[1] >> 2; - centroid[2] += vtxData->vertexArray[tetrahedron[i]].pos[2] >> 2; + centroid[0] = L_add( centroid[0], L_shr( vtxData->vertexArray[tetrahedron[i]].pos[0], Q2 ) ); + centroid[1] = L_add( centroid[1], L_shr( vtxData->vertexArray[tetrahedron[i]].pos[1], Q2 ) ); + centroid[2] = L_add( centroid[2], L_shr( vtxData->vertexArray[tetrahedron[i]].pos[2], Q2 ) ); } /* Executed below float operation centroid[0] /= 4; @@ -1263,7 +1277,7 @@ static void add_ghost_speakers_fixed( maxAngle = 13421773; //(1.f / 160.0f) in Q31 /* Extracting Azi and Ele for computation purposes */ - FOR ( i = 0; i < numVertex; ++i ) + FOR( i = 0; i < numVertex; ++i ) { ele[i] = vertexArray[i].ele; } @@ -1273,11 +1287,11 @@ static void add_ghost_speakers_fixed( maximum_l( ele, numVertex, &tmpEle ); lengthVertGhst = 0; - IF ( tmpEle < Q22_90_DEG ) + IF( LT_32( tmpEle, Q22_90_DEG ) ) { - IF ( efip_flag ) + IF( efip_flag ) { - IF ( tmpEle > ( Q22_90_DEG >> Q1 ) ) + IF( GT_32( tmpEle, Q22_45_DEG ) ) { vtxDmxType = EFAP_DMX_NONE; } @@ -1293,11 +1307,11 @@ static void add_ghost_speakers_fixed( /* ADD VOH IF NECESSERAY (i.e. if the elevation of the lowest LS is > -90 deg) */ minimum_l( ele, numVertex, &tmpEle ); - IF ( tmpEle > -Q22_90_DEG ) + IF( GT_32( tmpEle, -Q22_90_DEG ) ) { - IF ( efip_flag ) + IF( efip_flag ) { - IF ( tmpEle < -( Q22_90_DEG >> Q1 ) ) + IF( LT_32( tmpEle, -Q22_45_DEG ) ) { vtxDmxType = EFAP_DMX_NONE; } @@ -1316,9 +1330,9 @@ static void add_ghost_speakers_fixed( /* LIST ALL SURROUNDING loudspeakers */ k = 0; - FOR ( i = 0; i < numVertex; ++i ) + FOR( i = 0; i < numVertex; ++i ) { - IF ( L_abs( vertexArray[i].ele ) < ( Q22_90_DEG >> Q1 ) ) + IF( LT_32( L_abs( vertexArray[i].ele ), Q22_45_DEG ) ) { tmpAzi[k] = vertexArray[i].azi; ++k; @@ -1326,18 +1340,18 @@ static void add_ghost_speakers_fixed( } lengthHorGhst = 0; - IF ( k == 0 ) /* no speakers found: add a triangle of ghost speakers */ + IF( EQ_16( k, 0 ) ) /* no speakers found: add a triangle of ghost speakers */ { add_vertex_fixed( vertexArray, 0, 0, numVertex + a, EFAP_DMX_INTENSITY ); - add_vertex_fixed( vertexArray, 120 << Q22, 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); - add_vertex_fixed( vertexArray, 240 << Q22, 0, numVertex + a + 2, EFAP_DMX_INTENSITY ); + add_vertex_fixed( vertexArray, Q22_120_DEG, 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); + add_vertex_fixed( vertexArray, Q22_240_DEG, 0, numVertex + a + 2, EFAP_DMX_INTENSITY ); a += 3; lengthHorGhst += 3; } - ELSE IF ( k == 1 ) /* only one speaker found: add two ghost speakers to complete a triangle */ + ELSE IF( EQ_16( k, 1 ) ) /* only one speaker found: add two ghost speakers to complete a triangle */ { - add_vertex_fixed( vertexArray, tmpAzi[0] + ( 120 << Q22 ), 0, numVertex + a, EFAP_DMX_INTENSITY ); - add_vertex_fixed( vertexArray, tmpAzi[0] + ( 240 << Q22 ), 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); + add_vertex_fixed( vertexArray, L_add( tmpAzi[0], Q22_120_DEG ), 0, numVertex + a, EFAP_DMX_INTENSITY ); + add_vertex_fixed( vertexArray, L_add( tmpAzi[0], Q22_240_DEG ), 0, numVertex + a + 1, EFAP_DMX_INTENSITY ); a += 2; lengthHorGhst += 2; } @@ -1347,41 +1361,41 @@ static void add_ghost_speakers_fixed( sort_l( tmpAzi, k ); /* The next lines correspond to angle_diff = [azi(2:end), azi(1) + 360] - azi; in Matlab */ - FOR ( i = 0; i < k - 1; ++i ) + FOR( i = 0; i < k - 1; ++i ) { - tmpAngleDiff[i] = tmpAzi[i + 1] - tmpAzi[i]; + tmpAngleDiff[i] = L_sub( tmpAzi[i + 1], tmpAzi[i] ); sectors[i] = ceil_fixed( Mpy_32_32( tmpAngleDiff[i], maxAngle ), Q22 ); - IF ( sectors[i] > ( 1 << Q22 ) ) + IF( GT_32( sectors[i], Q22_1 ) ) { ++lengthHorGhst; } } - tmpAngleDiff[k - 1] = tmpAzi[0] + Q22_360_DEG - tmpAzi[k - 1]; + tmpAngleDiff[k - 1] = L_sub( L_add( tmpAzi[0], Q22_360_DEG ), tmpAzi[k - 1] ); sectors[k - 1] = ceil_fixed( Mpy_32_32( tmpAngleDiff[k - 1], maxAngle ), Q22 ); - IF ( sectors[k - 1] > ( 1 << Q22 ) ) + IF( GT_32( sectors[k - 1], Q22_1 ) ) { ++lengthHorGhst; } /* Adding new virtual speakers */ - FOR ( i = 0; i < k; ++i ) + FOR( i = 0; i < k; ++i ) { - IF ( sectors[i] > ( 1 << Q22 ) ) + IF( GT_32( sectors[i], Q22_1 ) ) { newDiff = tmpAngleDiff[i] / sectors[i]; - num_new = (Word16) ( L_sub( sectors[i], ( 1 << Q22 ) ) >> Q22 ); + num_new = (Word16) L_shr( L_sub( sectors[i], Q22_1 ), Q22 ); - FOR ( j = 0; j < num_new; ++j ) + FOR( j = 0; j < num_new; ++j ) { - newAzi = tmpAzi[i] + ( ( ( j + 1 ) * newDiff ) << Q22 ); + newAzi = L_add( tmpAzi[i], L_shl( ( j + 1 ) * newDiff, Q22 ) ); add_vertex_fixed( vertexArray, newAzi, 0, numVertex + a, EFAP_DMX_INTENSITY ); ++a; - IF ( j > 0 ) + IF( GT_16( j, 0 ) ) { ++lengthHorGhst; } @@ -1411,7 +1425,7 @@ static void sort_vertices( int16_t i; /* Initializing tmpIdx */ - for ( i = 0; i < *numVtx; ++i ) + FOR( i = 0; i < *numVtx; ++i ) { tmpIdx[i] = vertexArray[i].idx; } @@ -1539,12 +1553,12 @@ static void add_vertex_to_convex_hull_fixed( Word16 surface[3]; Word32 numHullVtx; Word32 centroid[3]; - const Word32 threshold = -67; + const Word32 threshold = -268; // -1e-6f in Q28 Word32 tmpDist; EFAP_LS_TRIANGLE triArrayNew[EFAP_MAX_POLY_SET]; /* If the vertex is already part of the hull, nothing must be done */ - IF ( vtxInHull[vtxIdx] ) + IF( vtxInHull[vtxIdx] ) { return; } @@ -1552,14 +1566,14 @@ static void add_vertex_to_convex_hull_fixed( /* Compute the centroid of the current convex hull */ numHullVtx = 0; set_l( centroid, 0, 3 ); - FOR ( i = 0; i < vtxData->numVtx; i++ ) + FOR( i = 0; i < vtxData->numVtx; i++ ) { - IF ( vtxInHull[i] ) + IF( vtxInHull[i] ) { numHullVtx++; - centroid[0] += vtxData->vertexArray[i].pos[0] >> 4; - centroid[1] += vtxData->vertexArray[i].pos[1] >> 4; - centroid[2] += vtxData->vertexArray[i].pos[2] >> 4; + centroid[0] = L_add( centroid[0], L_shr( vtxData->vertexArray[i].pos[0], Q4 ) ); + centroid[1] = L_add( centroid[1], L_shr( vtxData->vertexArray[i].pos[1], Q4 ) ); + centroid[2] = L_add( centroid[2], L_shr( vtxData->vertexArray[i].pos[2], Q4 ) ); } } // Multiplying with 1 / numHullVtx; @@ -1568,18 +1582,18 @@ static void add_vertex_to_convex_hull_fixed( centroid[1] /= numHullVtx; centroid[2] /= numHullVtx; - centroid[0] <<= 4; - centroid[1] <<= 4; - centroid[2] <<= 4; + centroid[0] = L_shl( centroid[0], 4 ); + centroid[1] = L_shl( centroid[1], 4 ); + centroid[2] = L_shl( centroid[2], 4 ); /* Processing */ k = 0; l = 0; - FOR ( i = 0; i < *szTri; ++i ) + FOR( i = 0; i < *szTri; ++i ) { - tmpDist = vertex_distance_fixed( vtxData->vertexArray, triArray[i], vtxIdx ); // Q26 - IF ( tmpDist > threshold ) + tmpDist = vertex_distance_fixed( vtxData->vertexArray, triArray[i], vtxIdx ); // Q28 + IF( GT_32( tmpDist, threshold ) ) { visible[k] = i; ++k; @@ -1593,7 +1607,7 @@ static void add_vertex_to_convex_hull_fixed( visible_edges( triArray, visible, k, numEdges, edges ); - FOR ( i = 0; i < numEdges[0]; i += 2 ) + FOR( i = 0; i < numEdges[0]; i += 2 ) { surface[0] = edges[i]; surface[1] = edges[i + 1]; @@ -1606,7 +1620,7 @@ static void add_vertex_to_convex_hull_fixed( } /* Outputs */ - FOR ( i = 0; i < l; i++ ) + FOR( i = 0; i < l; i++ ) { mvs2s( triArrayNew[i].LS, triArray[i].LS, 3 ); } @@ -1645,21 +1659,21 @@ static void visible_edges( #endif /* Set counter and counterTranspose to 0 */ - FOR ( i = 0; i < EFAP_MAX_SIZE_TMP_BUFF; i++ ) + FOR( i = 0; i < EFAP_MAX_SIZE_TMP_BUFF; i++ ) { set_s( counter[i], 0, EFAP_MAX_SIZE_TMP_BUFF ); set_s( counterTranspose[i], 0, EFAP_MAX_SIZE_TMP_BUFF ); } /* Finding the max vertex */ - FOR ( i = 0; i < numSurface; ++i ) + FOR( i = 0; i < numSurface; ++i ) { #ifndef IVAS_FLOAT_FIXED tmpMax[i] = (float) triArray[visible[i]].LS[0]; #else tmpMax[i] = triArray[visible[i]].LS[0]; #endif - FOR ( j = 1; j < 3; ++j ) + FOR( j = 1; j < 3; ++j ) { IF( tmpMax[i] < triArray[visible[i]].LS[j] ) { @@ -1676,14 +1690,14 @@ static void visible_edges( #else maxVertex = tmpMax[maximum_s( tmpMax, numSurface, NULL )]; #endif - FOR ( i = 0; i < numSurface; ++i ) + FOR( i = 0; i < numSurface; ++i ) { tmpSurface[0] = triArray[visible[i]].LS[0]; tmpSurface[1] = triArray[visible[i]].LS[1]; tmpSurface[2] = triArray[visible[i]].LS[2]; tmpSurface[3] = triArray[visible[i]].LS[0]; - FOR ( j = 0; j < 3; ++j ) + FOR( j = 0; j < 3; ++j ) { a = tmpSurface[j]; b = tmpSurface[j + 1]; @@ -1692,9 +1706,9 @@ static void visible_edges( } } - FOR ( i = 0; i < maxVertex + 1; ++i ) + FOR( i = 0; i < maxVertex + 1; ++i ) { - FOR ( j = 0; j < maxVertex + 1; ++j ) + FOR( j = 0; j < maxVertex + 1; ++j ) { counter[i][j] = counterTranspose[i][j] + counterTranspose[j][i]; } @@ -1703,11 +1717,11 @@ static void visible_edges( /* Finding the edges */ k = 0; - FOR ( a = 0; a < maxVertex; ++a ) + FOR( a = 0; a < maxVertex; ++a ) { - FOR ( b = a + 1; b < maxVertex + 1; ++b ) + FOR( b = a + 1; b < maxVertex + 1; ++b ) { - IF ( counter[a][b] == 1 ) + IF( counter[a][b] == 1 ) { edges[k] = a; edges[k + 1] = b; @@ -1775,7 +1789,7 @@ static void flip_plane_fixed( vtxArray[surface[2]].pos, centroid ); - IF ( dist > 0 ) + IF( GT_32( dist, 0 ) ) { /*efap_flipLeftRight( surface, 3 );*/ tmp = surface[0]; @@ -1945,12 +1959,12 @@ static void remap_ghosts( *-------------------------------------------------------------------------*/ static void remap_ghosts_fixed( - EFAP_VERTEX *vtxArray, /* i/o: Vertex array */ - EFAP_LS_TRIANGLE *triArray, /* i/o: Triangle array */ - Word16 numSpk, /* i : Number of speakers */ - Word16 *numVertex, /* i/o: Size of vertex array */ - Word16 numTri, /* i : Size of triangle array */ - float **downmixMatrixTranspose /* o : Transpose of downmix matrix */ + EFAP_VERTEX *vtxArray, /* i/o: Vertex array */ + EFAP_LS_TRIANGLE *triArray, /* i/o: Triangle array */ + Word16 numSpk, /* i : Number of speakers */ + Word16 *numVertex, /* i/o: Size of vertex array */ + Word16 numTri, /* i : Size of triangle array */ + Word32 **downmixMatrixTranspose /* o : Transpose of downmix matrix */ ) { Word16 numGhst = 0; @@ -1973,18 +1987,18 @@ static void remap_ghosts_fixed( set_l( tmpVec2, 0, EFAP_MAX_SIZE_TMP_BUFF ); /* Finding unused ghosts (i.e. ghost speakers that aren't used for triangulation */ - FOR ( g = numVtx - 1; g > numSpk - 1; --g ) + FOR( g = numVtx - 1; g > numSpk - 1; --g ) { /* find(triangle_mat == ghost, 1, 'first') */ - IF ( find_int_in_tri( triArray, g, numTri, posFound ) == 0 ) + IF( EQ_16( find_int_in_tri( triArray, g, numTri, posFound ), 0 ) ) { remove_vertex( vtxArray, g, numVtx ); --numVtx; - FOR ( i = 0; i < numTri; ++i ) + FOR( i = 0; i < numTri; ++i ) { - FOR ( j = 0; j < 3; ++j ) + FOR( j = 0; j < 3; ++j ) { - IF ( triArray[i].LS[j] > g ) + IF( GT_16( triArray[i].LS[j], g ) ) { triArray[i].LS[j] = g - 1; } @@ -2001,7 +2015,7 @@ static void remap_ghosts_fixed( numTot = numSpk + numGhst; /* Initializing tmpMat as the identity matrix */ - FOR ( i = 0; i < numTot; ++i ) + FOR( i = 0; i < numTot; ++i ) { set_l( tmpMat[i], 0, numTot ); set_l( tmpNewMat[i], 0, numTot ); @@ -2011,12 +2025,12 @@ static void remap_ghosts_fixed( } /* Generate initial sound energy distribution matrix */ - FOR ( i = numSpk; i < numTot; ++i ) + FOR( i = numSpk; i < numTot; ++i ) { tmpL = get_neighbours( triArray, i, numTri, neighbours ); /* Initializing the column to 0 */ - FOR ( j = 0; j < numTot; ++j ) + FOR( j = 0; j < numTot; ++j ) { tmpMat[j][i] = 0; tmpNewMat[j][i] = 0; @@ -2024,7 +2038,7 @@ static void remap_ghosts_fixed( /* The neighbours are set to 1.0/tmpL */ inv_tmpL = 0x7fffffff / tmpL; - FOR ( j = 0; j < tmpL; ++j ) + FOR( j = 0; j < tmpL; ++j ) { tmpMat[neighbours[j]][i] = inv_tmpL; tmpNewMat[neighbours[j]][i] = inv_tmpL; @@ -2032,23 +2046,23 @@ static void remap_ghosts_fixed( } /* Redistributing sound energy */ - FOR ( i = 0; i < numTot; ++i ) + FOR( i = 0; i < numTot; ++i ) { - FOR ( j = 0; j < numTot; ++j ) + FOR( j = 0; j < numTot; ++j ) { tmpNewMat[i][j] = tmpMat[j][i]; } } - FOR ( i = numSpk; i < numTot; ++i ) + FOR( i = numSpk; i < numTot; ++i ) { mvl2l( tmpNewMat[i], tmpVec, numTot ); tmpDist = sum_l( &tmpVec[numSpk], numTot - numSpk ); - WHILE ( tmpDist > thresh ) + WHILE( GT_32( tmpDist, thresh ) ) { - matrix_times_row_int( tmpMat, tmpVec, numTot, tmpVec2 ); + matrix_times_row_fixed( tmpMat, tmpVec, numTot, tmpVec2 ); mvl2l( tmpVec2, tmpVec, numTot ); set_l( tmpVec2, 0, numTot ); tmpDist = sum_l( &tmpVec[numSpk], numTot - numSpk ); @@ -2056,65 +2070,46 @@ static void remap_ghosts_fixed( mvl2l( tmpVec, tmpNewMat[i], numTot ); } - FOR ( i = 0; i < numSpk; ++i ) + FOR( i = 0; i < numSpk; ++i ) { /* Applying a sqrt(2) coeff and obtaining the dmMatrix*/ - FOR ( j = 0; j < numSpk; ++j ) + FOR( j = 0; j < numSpk; ++j ) { - IF ( tmpNewMat[j][i] == 0 ) - { - downmixMatrixTranspose[j][i] = 0; - } - ELSE IF ( tmpNewMat[j][i] == 0x7fffffff ) + IF( EQ_32( tmpNewMat[j][i], 0 ) || EQ_32( tmpNewMat[j][i], 0x7fffffff ) ) { - downmixMatrixTranspose[j][i] = 1; + downmixMatrixTranspose[j][i] = tmpNewMat[j][i]; } ELSE { Word16 exp = 0; Word32 tmp_sqrt = Sqrt32( tmpNewMat[j][i], &exp ); tmp_sqrt = L_shl( tmp_sqrt, exp ); - downmixMatrixTranspose[j][i] = ( (float) tmp_sqrt ) / 0x7fffffff; + downmixMatrixTranspose[j][i] = tmp_sqrt; } } /* Downmix ghost loudspeakers according to dmxType */ - FOR ( ; j < numTot; ++j ) + FOR( ; j < numTot; ++j ) { - SWITCH ( vtxArray[j].dmxType ) + SWITCH( vtxArray[j].dmxType ) { case EFAP_DMX_NONE: - downmixMatrixTranspose[j][i] = 0.f; + downmixMatrixTranspose[j][i] = 0; break; case EFAP_DMX_AMPLITUDE: - IF ( tmpNewMat[j][i] == 0 ) - { - downmixMatrixTranspose[j][i] = 0; - } - ELSE IF ( tmpNewMat[j][i] == 0x7fffffff ) - { - downmixMatrixTranspose[j][i] = 1; - } - ELSE - { - downmixMatrixTranspose[j][i] = ( (float) tmpNewMat[j][i] ) / 0x7fffffff; - } + downmixMatrixTranspose[j][i] = tmpNewMat[j][i]; break; case EFAP_DMX_INTENSITY: default: - IF ( tmpNewMat[j][i] == 0 ) + IF( EQ_32( tmpNewMat[j][i], 0 ) || EQ_32( tmpNewMat[j][i], 0x7fffffff ) ) { - downmixMatrixTranspose[j][i] = 0; - } - ELSE IF ( tmpNewMat[j][i] == 0x7fffffff ) - { - downmixMatrixTranspose[j][i] = 1; + downmixMatrixTranspose[j][i] = tmpNewMat[j][i]; } ELSE { Word16 exp = 0; Word32 tmp_sqrt = Sqrt32( tmpNewMat[j][i], &exp ); tmp_sqrt = L_shl( tmp_sqrt, exp ); - downmixMatrixTranspose[j][i] = ( (float) tmp_sqrt ) / 0x7fffffff; + downmixMatrixTranspose[j][i] = tmp_sqrt; } break; } @@ -2167,7 +2162,7 @@ static void vertex_init_fixed( Word16 i; /* Main Processing */ - FOR ( i = 0; i < efapVtxData->numVtx; i++ ) + FOR( i = 0; i < efapVtxData->numVtx; i++ ) { add_vertex_fixed( efapVtxData->vertexArray, aziSpk[i], eleSpk[i], i, EFAP_DMX_INTENSITY ); } @@ -2176,6 +2171,7 @@ static void vertex_init_fixed( } #endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * efap_panning() * @@ -2214,22 +2210,14 @@ static void efap_panning( for ( i = 0; i < numChan; ++i ) { chan[i] = polyData->polysetArray[polyIdx].chan[i]; -#ifndef IVAS_FLOAT_FIXED aziPoly[i] = polyData->polysetArray[polyIdx].polyAzi[i]; -#else - aziPoly[i] = ( (float) polyData->polysetArray[polyIdx].polyAzi[i] ) / ( 1 << Q22 ); -#endif if ( polyData->polysetArray[polyIdx].isNaN[i] == 1 ) { aziPoly[i] = P[0]; } -#ifndef IVAS_FLOAT_FIXED elePoly[i] = polyData->polysetArray[polyIdx].polyEle[i]; -#else - elePoly[i] = ( (float) polyData->polysetArray[polyIdx].polyEle[i] ) / ( 1 << Q22 ); -#endif } /* Computing the gain for the polygon */ @@ -2248,7 +2236,7 @@ static void efap_panning( return; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * efap_panning_fixed() * @@ -2259,7 +2247,7 @@ static void efap_panning_fixed( const Word32 azi, /* i : Value of the azimuth */ const Word32 ele, /* i : Value of the elevation */ const EFAP_POLYSET_DATA *polyData, /* i : Polygon data */ - float *bufferL /* o : 1D array of length numSpk that will contain the tmp values */ + Word32 *bufferL /* o : 1D array of length numSpk that will contain the tmp values */ ) { Word16 i; @@ -2288,7 +2276,7 @@ static void efap_panning_fixed( chan[i] = polyData->polysetArray[polyIdx].chan[i]; aziPoly[i] = polyData->polysetArray[polyIdx].polyAzi[i]; - IF( polyData->polysetArray[polyIdx].isNaN[i] == 1 ) + IF( EQ_16( polyData->polysetArray[polyIdx].isNaN[i], 1 ) ) { aziPoly[i] = P[0]; } @@ -2307,13 +2295,15 @@ static void efap_panning_fixed( /* Updating the buffer structure */ FOR( i = 0; i < numChan; ++i ) { - bufferL[chan[i]] = ( (float) Mpy_32_32( tmpBuff[i], normTmpBuff ) ) / ( 1 << ( Q31 - exp ) ); + bufferL[chan[i]] = Mpy_32_32( tmpBuff[i], normTmpBuff ); + bufferL[chan[i]] = L_shl( bufferL[chan[i]], exp ); // Q31 } return; } #endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * get_poly_gains() * @@ -2367,7 +2357,7 @@ static void get_poly_gains( return; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * get_poly_gains_fixed() * @@ -2422,6 +2412,8 @@ static void get_poly_gains_fixed( return; } #endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * get_tri_gain() * @@ -2460,7 +2452,7 @@ static float get_tri_gain( } return gain; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * get_tri_gain_fixed() * @@ -2480,8 +2472,8 @@ static Word32 get_tri_gain_fixed( Word32 gain; /* Processing */ - tmpN[0] = B[1] - C[1]; - tmpN[1] = C[0] - B[0]; + tmpN[0] = L_sub( B[1], C[1] ); + tmpN[1] = L_sub( C[0], B[0] ); v_sub_fixed( B, A, tmpSub1, 2, 0 ); @@ -2490,14 +2482,14 @@ static Word32 get_tri_gain_fixed( Word16 exp = Q13; Word32 inv_tmpDot2 = L_shl( tmpDot1, norm_l( tmpDot1 ) ); exp = exp - norm_l( tmpDot1 ); - Word16 inv_tmpDot1 = Inv16( inv_tmpDot2 >> Q16, &exp ); + Word16 inv_tmpDot1 = Inv16( (Word16) L_shr( inv_tmpDot2, Q16 ), &exp ); v_multc_fixed( tmpN, L_shl( inv_tmpDot1, Q16 + exp ), N, 2 ); tmpDot2 = dotp_fixed( P_minus_A, N, 2 ); // Q18 - gain = 0x00040000 - tmpDot2; + gain = L_sub( 0x00040000, tmpDot2 ); /* Set gains <= -60dB to 0 to avoid problems in SVD */ - IF( L_abs( gain ) < 1 ) + IF( LT_32( L_abs( gain ), 1 ) ) { gain = 0; } @@ -2592,7 +2584,7 @@ static void add_vertex_fixed( /* IdxAziTmp */ tmp = L_abs( L_sub( Q22_90_DEG, L_abs( vtxArray[pos].azi ) ) ); // Q22 - idxAziTmp = anint_fixed( tmp, Q22 ) >> Q22; + idxAziTmp = L_shr( anint_fixed( tmp, Q22 ), Q22 ); /* IdxEleTmp */ tmp = L_abs( vtxArray[pos].ele ); @@ -2628,16 +2620,16 @@ static void efap_sort_s( int16_t i, j; int16_t tempr, tempi; - for ( i = 0; i < len; i++ ) + FOR( i = 0; i < len; i++ ) { idx[i] = i; } - for ( i = len - 2; i >= 0; i-- ) + FOR( i = len - 2; i >= 0; i-- ) { tempr = x[i]; tempi = idx[i]; - for ( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) + FOR( j = i + 1; ( j < len ) && ( tempr > x[j] ); j++ ) { x[j - 1] = x[j]; idx[j - 1] = idx[j]; @@ -2694,7 +2686,7 @@ static Word32 vertex_distance_fixed( Word16 i; /* Assigning the coordinates to the vector */ - FOR ( i = 0; i < 3; ++i ) + FOR( i = 0; i < 3; ++i ) { A[i] = vtxArray[tri.LS[0]].pos[i]; B[i] = vtxArray[tri.LS[1]].pos[i]; @@ -2707,6 +2699,7 @@ static Word32 vertex_distance_fixed( } #endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * point_poly_distance() * @@ -2720,18 +2713,12 @@ static float point_poly_distance( { float P1[3], P2[3], P3[3]; -#ifndef IVAS_FLOAT_FIXED sph2cart( poly.polyAzi[0], poly.polyEle[0], &P1[0] ); sph2cart( poly.polyAzi[1], poly.polyEle[1], &P2[0] ); sph2cart( poly.polyAzi[2], poly.polyEle[2], &P3[0] ); -#else - sph2cart( ( (float) poly.polyAzi[0] ) / ( 1 << Q22 ), ( (float) poly.polyEle[0] ) / ( 1 << Q22 ), &P1[0] ); - sph2cart( ( (float) poly.polyAzi[1] ) / ( 1 << Q22 ), ( (float) poly.polyEle[1] ) / ( 1 << Q22 ), &P2[0] ); - sph2cart( ( (float) poly.polyAzi[2] ) / ( 1 << Q22 ), ( (float) poly.polyEle[2] ) / ( 1 << Q22 ), &P3[0] ); -#endif return point_plane_distance( P1, P2, P3, X ); } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * point_poly_distance_fixed() * @@ -2752,6 +2739,8 @@ static Word32 point_poly_distance_fixed( return point_plane_distance_fixed( P1, P2, P3, X ); } #endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * point_plane_distance() * @@ -2795,14 +2784,14 @@ static float point_plane_distance( return dist; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * point_plane_distance_fixed() * * Compute the signed distance between a point and a given plane *-------------------------------------------------------------------------*/ -static Word32 point_plane_distance_fixed( // returns output in Q26 +static Word32 point_plane_distance_fixed( // returns output in Q28 const Word32 P1[3], /* i : First point of the triangle that defines the planes */ const Word32 P2[3], /* i : Second point of the triangle */ const Word32 P3[3], /* i : Third point of the triangle */ @@ -2816,9 +2805,9 @@ static Word32 point_plane_distance_fixed( // returns output in Q26 Word32 dist; /* Check if the point already matches a triangle vertex */ - IF( ( X[0] == P1[0] && X[1] == P1[1] && X[2] == P1[2] ) || - ( X[0] == P2[0] && X[1] == P2[1] && X[2] == P2[2] ) || - ( X[0] == P3[0] && X[1] == P3[1] && X[2] == P3[2] ) ) + IF( ( EQ_32( X[0], P1[0] ) && EQ_32( X[1], P1[1] ) && EQ_32( X[2], P1[2] ) ) || + ( EQ_32( X[0], P2[0] ) && EQ_32( X[1], P2[1] ) && EQ_32( X[2], P2[2] ) ) || + ( EQ_32( X[0], P3[0] ) && EQ_32( X[1], P3[1] ) && EQ_32( X[2], P3[2] ) ) ) { return 0; } @@ -2828,20 +2817,20 @@ static Word32 point_plane_distance_fixed( // returns output in Q26 v_sub_fixed( P1, P3, tmpCross2, 3, 1 ); /* resultCross = cross(P1-P2,P1-P3) */ - efap_crossp_fixed( tmpCross1, tmpCross2, resultCross ); //Q29 + efap_crossp_fixed( tmpCross1, tmpCross2, resultCross ); // Q29 /* Dot Product */ - tmpNorm = dotp_fixed( resultCross, resultCross, 3 ); //Q27 + tmpNorm = dotp_fixed( resultCross, resultCross, 3 ); // Q27 Word16 exp = 4; - tmpNorm = ISqrt32( tmpNorm, &exp ); // Q29 - //tmpNorm = L_shl( tmpNorm, exp ); //Q31 - v_sub_fixed( X, P1, tmpDot1, 3, 1 ); //Q30 - v_multc_fixed( resultCross, tmpNorm, tmpDot2, 3 ); //Q29 - exp - dist = dotp_fixed( tmpDot1, tmpDot2, 3 ); //Q28 - exp - - return L_shr( dist, ( 2 - exp ) ); + tmpNorm = ISqrt32( tmpNorm, &exp ); // Q29 + v_sub_fixed( X, P1, tmpDot1, 3, 1 ); // Q30 + v_multc_fixed( resultCross, tmpNorm, tmpDot2, 3 ); // Q29 - exp + dist = L_shl( dotp_fixed( tmpDot1, tmpDot2, 3 ), exp ); // Q28 + return dist; } #endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * efap_crossp() * @@ -2860,7 +2849,7 @@ static void efap_crossp( return; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * efap_crossp_fixed() * @@ -2897,11 +2886,11 @@ static int16_t find_int_in_tri( int16_t i, j; /* Find the first element equal to n */ - for ( i = 0; i < r; ++i ) + FOR( i = 0; i < r; ++i ) { - for ( j = 0; j < 3; ++j ) + FOR( j = 0; j < 3; ++j ) { - if ( tri[i].LS[j] == n ) + IF( EQ_16( tri[i].LS[j], n ) ) { pos[0] = i; pos[1] = j; @@ -2931,7 +2920,7 @@ static void remove_vertex( assert( idx < L && "EFAP: index out of bounds" ); /* Shift all vertex of one position, so vtxArray[i] will be vtxArray[i+1] and so on */ - for ( i = idx; i < L - 1; ++i ) + FOR( i = idx; i < L - 1; ++i ) { #ifndef IVAS_FLOAT_FIXED add_vertex( vtxArray, vtxArray[i + 1].azi, vtxArray[i + 1].ele, i, EFAP_DMX_INTENSITY ); @@ -2971,19 +2960,19 @@ static int16_t get_neighbours( EFAP_LS_TRIANGLE tmpTriArray[EFAP_MAX_POLY_SET]; /* Processing */ - for ( i = 0; i < numTri; ++i ) + FOR( i = 0; i < numTri; ++i ) { mvs2s( triArray[i].LS, tmpTriArray[i].LS, 3 ); } k = 0; - while ( 1 ) + WHILE( 1 ) { - if ( find_int_in_tri( tmpTriArray, vtxIdx, numTri, tmpPos ) == 0 ) + IF( EQ_16( find_int_in_tri( tmpTriArray, vtxIdx, numTri, tmpPos ), 0 ) ) { break; } - else + ELSE { tmpNeighbours[k] = tmpTriArray[tmpPos[0]].LS[0]; tmpNeighbours[k + 1] = tmpTriArray[tmpPos[0]].LS[1]; @@ -2992,7 +2981,7 @@ static int16_t get_neighbours( tmpTriArray[tmpPos[0]].LS[tmpPos[1]] = -1; } - if ( k > 3 * numTri ) + IF( GT_16( k, 3 * numTri ) ) { break; } @@ -3005,10 +2994,10 @@ static int16_t get_neighbours( neighbours[0] = tmpNeighbours[0]; j = 1; - for ( i = 1; i < k; ++i ) + FOR( i = 1; i < k; ++i ) { - if ( ( tmpNeighbours[i] != tmpNeighbours[i - 1] ) && - ( tmpNeighbours[i] != vtxIdx ) ) + IF( NE_16( tmpNeighbours[i], tmpNeighbours[i - 1] ) && + NE_16( tmpNeighbours[i], vtxIdx ) ) { neighbours[j] = tmpNeighbours[i]; ++j; @@ -3047,12 +3036,12 @@ static void matrix_times_row( } #else /*-------------------------------------------------------------------------* - * matrix_times_row_int() + * matrix_times_row_fixed() * * Computes the product of a matrix and a row vector *-------------------------------------------------------------------------*/ -static void matrix_times_row_int( +static void matrix_times_row_fixed( Word32 mat[EFAP_MAX_SIZE_TMP_BUFF][EFAP_MAX_SIZE_TMP_BUFF], /* i : The input matrix */ const Word32 *vec, /* i : The input row vector */ const Word16 L, /* i : Row length */ @@ -3061,11 +3050,11 @@ static void matrix_times_row_int( { int16_t i, j; - FOR ( i = 0; i < L; ++i ) + FOR( i = 0; i < L; ++i ) { - FOR ( j = 0; j < L; ++j ) + FOR( j = 0; j < L; ++j ) { - out[i] += Mpy_32_32( mat[i][j], vec[j] ); + out[i] = L_add( out[i], Mpy_32_32( mat[i][j], vec[j] ) ); } } @@ -3108,11 +3097,11 @@ static void tri_to_poly( lenPolySet = 0; /* Sorting the polygons */ - FOR ( i = 0; i < numTri; ++i ) + FOR( i = 0; i < numTri; ++i ) { /* search for coplanar vertices and add them to the polygon */ lenPoly = 0; - FOR ( j = 0; j < numVtx; ++j ) + FOR( j = 0; j < numVtx; ++j ) { #ifndef IVAS_FLOAT_FIXED dist = fabsf( point_plane_distance( @@ -3125,13 +3114,13 @@ static void tri_to_poly( vtxArray[triArray[i].LS[0]].pos, vtxArray[triArray[i].LS[1]].pos, vtxArray[triArray[i].LS[2]].pos, - vtxArray[j].pos ) ); // Q26 + vtxArray[j].pos ) ); // Q28 #endif #ifndef IVAS_FLOAT_FIXED IF( dist < 1e-3f ) #else - IF ( dist < 67109 /* 1e-3f in Q26 */ ) + IF( LT_32( dist, 268435 ) /* 1e-3f in Q28 */ ) #endif { assert( lenPoly < EFAP_MAX_CHAN_NUM && "EFAP: exceeded max polygon vertices!" ); @@ -3143,21 +3132,21 @@ static void tri_to_poly( /* search existing polygons to determine whether the new one already exists/is a subset or is a superset */ found = 0; replaceIdx = -1; - FOR ( j = 0; j < lenPolySet; ++j ) + FOR( j = 0; j < lenPolySet; ++j ) { found = compare_poly( sortedChan[j], sortedLengths[j], poly, lenPoly ); - IF ( found > 0 ) + IF( GT_16( found, 0 ) ) { break; } - ELSE IF ( found < 0 ) + ELSE IF( LT_16( found, 0 ) ) { replaceIdx = j; } } - IF ( found == 0 ) + IF( EQ_16( found, 0 ) ) { /* append new poly */ mvs2s( poly, sortedChan[lenPolySet], lenPoly ); @@ -3165,7 +3154,7 @@ static void tri_to_poly( sortedLengths[lenPolySet] = lenPoly; ++lenPolySet; } - ELSE IF ( found == -1 ) + ELSE IF( EQ_16( found, -1 ) ) { /* replace with superset */ mvs2s( poly, sortedChan[replaceIdx], lenPoly ); @@ -3175,7 +3164,7 @@ static void tri_to_poly( } /* Sorting the vertex */ - FOR ( i = 0; i < lenPolySet; ++i ) + FOR( i = 0; i < lenPolySet; ++i ) { #ifndef IVAS_FLOAT_FIXED sort_channels_vertex( vtxArray, triArray, sortedChan[i], sortedLengths[i], sortedTri[i] ); @@ -3209,11 +3198,11 @@ static int16_t compare_poly( count = 0; - for ( i = 0; i < lenOld; ++i ) + FOR( i = 0; i < lenOld; ++i ) { - for ( j = count; j < lenNew; ++j ) + FOR( j = count; j < lenNew; ++j ) { - if ( old[i] == new[j] ) + IF( old[i] == new[j] ) { ++count; break; @@ -3221,17 +3210,17 @@ static int16_t compare_poly( } } - if ( count == lenOld && lenOld < lenNew ) + IF( count == lenOld && lenOld < lenNew ) { /* new polygon is a superset */ return -1; } - else if ( count == lenNew && lenOld >= lenNew ) + ELSE IF( count == lenNew && lenOld >= lenNew ) { /* found as subset or identical */ return 1; } - else + ELSE { /* not found */ return 0; @@ -3337,8 +3326,8 @@ static void sort_channels_vertex( *-------------------------------------------------------------------------*/ static void sort_channels_vertex_fixed( - const EFAP_VERTEX *vtxArray, /* i : Vertex array */ - const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ + const EFAP_VERTEX *vtxArray, /* i : Vertex array */ + const EFAP_LS_TRIANGLE *triArray, /* i : Triangle array */ Word16 channels[EFAP_MAX_CHAN_NUM], /* o : Channels array to be modified */ const Word16 lengthChannels, /* i : Length of the channels array */ Word16 idxTri /* i : Index of the considered triangle */ @@ -3363,63 +3352,63 @@ static void sort_channels_vertex_fixed( /* Initializing coordinates with the vertices of the considered triangle */ - FOR ( i = 0; i < 3; ++i ) + FOR( i = 0; i < 3; ++i ) { - P1[i] = vtxArray[triArray[idxTri].LS[0]].pos[i]; //Q31 - P2[i] = vtxArray[triArray[idxTri].LS[1]].pos[i]; //Q31 - P3[i] = vtxArray[triArray[idxTri].LS[2]].pos[i]; //Q31 + P1[i] = vtxArray[triArray[idxTri].LS[0]].pos[i]; // Q31 + P2[i] = vtxArray[triArray[idxTri].LS[1]].pos[i]; // Q31 + P3[i] = vtxArray[triArray[idxTri].LS[2]].pos[i]; // Q31 } /* First Base Vector */ - v_sub_fixed( P2, P1, tmpU, 3, 1 ); //tmpU Q30 + v_sub_fixed( P2, P1, tmpU, 3, 1 ); // tmpU Q30 Word16 exp1 = 2; normU = ISqrt32( dotp_fixed( tmpU, tmpU, 3 ), &exp1 ); - //normU = L_shl_sat( normU, exp ); //normU Q31 - v_multc_fixed( tmpU, normU, U, 3 ); //U Q30 - exp1 + // normU = L_shl_sat( normU, exp ); //normU Q31 + v_multc_fixed( tmpU, normU, U, 3 ); // U Q30 - exp1 /* Second Base Vector */ - v_sub_fixed( P3, P2, tmpV1, 3, 1 ); //tmpV1 Q30 - v_multc_fixed( U, dotp_fixed( U, tmpV1, 3 ), tmpV2, 3 ); // tmpV2 Q28 - exp1 + v_sub_fixed( P3, P2, tmpV1, 3, 1 ); // tmpV1 Q30 + v_multc_fixed( U, dotp_fixed( U, tmpV1, 3 ), tmpV2, 3 ); // tmpV2 Q28 - 2*exp1 - FOR ( i = 0; i < 3; i++ ) + FOR( i = 0; i < 3; i++ ) { - tmpV2[i] <<= 2; + tmpV2[i] = L_shl( tmpV2[i], Q2 + ( 2 * exp1 ) ); } v_sub_fixed( tmpV1, tmpV2, tmpV3, 3, 0 ); // tmpV3 Q30 Word16 exp2 = 2; normV = ISqrt32( dotp_fixed( tmpV3, tmpV3, 3 ), &exp2 ); - v_multc_fixed( tmpV3, normV, V, 3 ); //V Q30 - exp2 + v_multc_fixed( tmpV3, normV, V, 3 ); // V Q30 - exp2 /* Center of the first Triangle */ - FOR ( i = 0; i < 3; ++i ) + FOR( i = 0; i < 3; ++i ) { - MC[i] = ( ( ( P1[i] >> 2 ) + ( P2[i] >> 2 ) + ( P3[i] >> 2 ) ) / 3 ) << 2; + MC[i] = L_shl( L_add( L_add( L_shr( P1[i], Q2 ), L_shr( P2[i], Q2 ) ), L_shr( P3[i], Q2 ) ) / 3, Q2 ); } /* Sort Vertices */ - FOR ( i = 0; i < lengthChannels; ++i ) + FOR( i = 0; i < lengthChannels; ++i ) { - FOR ( j = 0; j < 3; ++j ) + FOR( j = 0; j < 3; ++j ) { tmpP[j] = vtxArray[channels[i]].pos[j]; } v_sub_fixed( tmpP, MC, P, 3, 1 ); // P Q30 - x = dotp_fixed( P, U, 3 ); //x Q29 - exp1 - y = dotp_fixed( P, V, 3 ); //y Q29 - exp2 + x = dotp_fixed( P, U, 3 ); // x Q29 - exp1 + y = dotp_fixed( P, V, 3 ); // y Q29 - exp2 // Executing azi[i] = atan2f( y, x ); - azi[i] = ( (Word32) BASOP_util_atan2( y, x, exp2 - exp1 ) ) << 16; // azi 2Q29 + azi[i] = L_shl( (Word32) BASOP_util_atan2( y, x, exp2 - exp1 ), Q16 ); // azi 2Q29 } /* Sorting the azi vec */ v_sort_ind_fixed( azi, order, lengthChannels ); /* Updating the channel array */ - FOR ( i = 0; i < lengthChannels; ++i ) + FOR( i = 0; i < lengthChannels; ++i ) { newChannels[i] = channels[order[i]]; } @@ -3459,10 +3448,11 @@ static Word32 efap_lmodl( ) { Word32 result = x % y; - return result >= 0 ? result : result + y; + return GE_32( result, 0 ) ? result : L_add( result, y ); } #endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * get_poly_num() * @@ -3524,7 +3514,7 @@ static int16_t get_poly_num( return found_poly; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * get_poly_num() * @@ -3555,11 +3545,11 @@ static Word16 get_poly_num_fixed( { /* select only polygons which are visible from the point */ dist_tmp = point_poly_distance_fixed( polyData->polysetArray[i], pos ); - IF( dist_tmp == 0 ) + IF( EQ_32( dist_tmp, 0 ) ) { return i; } - ELSE IF( dist_tmp > 0 ) + ELSE IF( GT_32( dist_tmp, 0 ) ) { poly_tmp[num_poly] = i; poly_dist[num_poly] = dist_tmp; @@ -3567,7 +3557,7 @@ static Word16 get_poly_num_fixed( } } } - IF( num_poly == 0 ) + IF( EQ_16( num_poly, 0 ) ) { return -1; } @@ -3577,7 +3567,7 @@ static Word16 get_poly_num_fixed( dist_tmp = poly_dist[0]; FOR( i = 1; i < num_poly; i++ ) { - IF( poly_dist[i] < dist_tmp ) + IF( LT_32( poly_dist[i], dist_tmp ) ) { found_poly = poly_tmp[i]; dist_tmp = poly_dist[i]; @@ -3588,6 +3578,7 @@ static Word16 get_poly_num_fixed( } #endif +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * in_poly() * @@ -3621,17 +3612,9 @@ static int16_t in_poly( } else { -#ifndef IVAS_FLOAT_FIXED A[0] = poly.polyAzi[0]; -#else - A[0] = ( (float) poly.polyAzi[0] ) / ( 1 << Q22 ); -#endif } -#ifndef IVAS_FLOAT_FIXED A[1] = poly.polyEle[0]; -#else - A[1] = ( (float) poly.polyEle[0] ) / ( 1 << Q22 ); -#endif v_sub( P, A, P_minus_A, 2 ); /* Precalculate value of (P-A) */ @@ -3643,17 +3626,9 @@ static int16_t in_poly( } else { -#ifndef IVAS_FLOAT_FIXED B[0] = poly.polyAzi[n]; -#else - B[0] = ( (float) poly.polyAzi[n] ) / ( 1 << Q22 ); -#endif } -#ifndef IVAS_FLOAT_FIXED B[1] = poly.polyEle[n]; -#else - B[1] = ( (float) poly.polyEle[n] ) / ( 1 << Q22 ); -#endif if ( poly.isNaN[n + 1] ) { @@ -3661,17 +3636,9 @@ static int16_t in_poly( } else { -#ifndef IVAS_FLOAT_FIXED C[0] = poly.polyAzi[n + 1]; -#else - C[0] = ( (float) poly.polyAzi[n + 1] ) / ( 1 << Q22 ); -#endif } -#ifndef IVAS_FLOAT_FIXED C[1] = poly.polyEle[n + 1]; -#else - C[1] = ( (float) poly.polyEle[n + 1] ) / ( 1 << Q22 ); -#endif if ( in_tri( A, B, C, P_minus_A ) ) { @@ -3681,7 +3648,7 @@ static int16_t in_poly( return 0; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * in_poly_fixed() * @@ -3702,7 +3669,7 @@ static Word16 in_poly_fixed( /* Angles are in Q22 */ /* Safety check */ - IF( numVertices < 3 ) + IF( LT_16( numVertices, 3 ) ) { return 0; } @@ -3752,6 +3719,8 @@ static Word16 in_poly_fixed( /* Angles are in Q22 */ return 0; } #endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * in_tri() * @@ -3809,7 +3778,7 @@ static int16_t in_tri( return 1; } } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * in_tri_fixed() * @@ -3826,8 +3795,9 @@ static Word16 in_tri_fixed( Word32 tmpDot1[2], tmpDot2[2]; Word32 matInv[2][2]; Word32 invFactor; + Word64 invFactor_w64; Word64 S[2]; - Word64 thresh_int = 4295; // 1e-6f in Q32 + Word64 thresh_int = 21475; // 1e-6f in Q32 /* Not a Valid Triangle : Colinear edges @@ -3840,14 +3810,18 @@ static Word16 in_tri_fixed( v_sub_fixed( C, A, tmpDot2, 2, 0 ); /* Verification of the non-colinearity : Q22 * Q22 = Q13 */ - invFactor = L_shr( L_sub( Mpy_32_32( tmpDot1[0], tmpDot2[1] ), Mpy_32_32( tmpDot1[1], tmpDot2[0] ) ), Q5 ); + invFactor = L_sub( Mpy_32_32( tmpDot1[0], tmpDot2[1] ), Mpy_32_32( tmpDot1[1], tmpDot2[0] ) ); - IF( invFactor == 0 ) + IF( EQ_32( invFactor, 0 ) ) { return 0; } - invFactor = L_shl( ( 0x7FFFFFFF / invFactor ), Q8 ); + invFactor_w64 = ( ( (Word64) 0x7FFFFFFFFFFFFFFF ) / ( (Word64) invFactor ) ) >> Q19; // Q31 + invFactor = (Word32) invFactor_w64; + + Word16 invFactor_exp = norm_l( invFactor ); + invFactor = L_shl( invFactor, invFactor_exp ); // Q22 = Q22 * Q31 matInv[0][0] = Mpy_32_32( tmpDot2[1], invFactor ); @@ -3855,13 +3829,54 @@ static Word16 in_tri_fixed( matInv[1][0] = Mpy_32_32( L_negate( tmpDot1[1] ), invFactor ); matInv[1][1] = Mpy_32_32( tmpDot1[0], invFactor ); - /* Computing S (Q13) = matInv (Q22) *(P-A) (Q22) */ - S[0] = L_add( Mpy_32_32( matInv[0][0], P_minus_A[0] ), Mpy_32_32( matInv[0][1], P_minus_A[1] ) ); - S[1] = L_add( Mpy_32_32( matInv[1][0], P_minus_A[0] ), Mpy_32_32( matInv[1][1], P_minus_A[1] ) ); + /* Computing S (Q13 + matInv_exp_final[i] + P_minus_A_exp_final + invFactor_exp - 1 ) = + matInv (Q22 + matInv_exp_final[i] + invFactor_exp) *(P-A) (Q22 + P_minus_A_exp_final) */ + Word16 matInv_exp[2][2], P_minus_A_exp[2]; + Word16 matInv_exp_final[2], P_minus_A_exp_final; + FOR( Word32 i = 0; i < 2; i++ ) + { + FOR( Word32 j = 0; j < 2; j++ ) + { + matInv_exp[i][j] = 31; + IF( NE_32( matInv[i][j], 0 ) ) + { + matInv_exp[i][j] = norm_l( matInv[i][j] ); + } + } + matInv_exp_final[i] = min( matInv_exp[i][0], matInv_exp[i][1] ); + P_minus_A_exp[i] = 31; + IF( NE_32( P_minus_A[i], 0 ) ) + { + P_minus_A_exp[i] = norm_l( P_minus_A[i] ); + } + } + P_minus_A_exp_final = min( P_minus_A_exp[0], P_minus_A_exp[1] ); + + S[0] = L_add( L_shr( Mpy_32_32( L_shl( matInv[0][0], matInv_exp_final[0] ), L_shl( P_minus_A[0], P_minus_A_exp_final ) ), Q1 ), + L_shr( Mpy_32_32( L_shl( matInv[0][1], matInv_exp_final[0] ), L_shl( P_minus_A[1], P_minus_A_exp_final ) ), Q1 ) ); + S[1] = L_add( L_shr( Mpy_32_32( L_shl( matInv[1][0], matInv_exp_final[1] ), L_shl( P_minus_A[0], P_minus_A_exp_final ) ), Q1 ), + L_shr( Mpy_32_32( L_shl( matInv[1][1], matInv_exp_final[1] ), L_shl( P_minus_A[1], P_minus_A_exp_final ) ), Q1 ) ); /* Checking if we are in the triangle; For the theory, check Christian Borss article, section 3.2 */ - IF( ( S[0] << Q19 ) < -thresh_int || ( S[1] << Q19 ) < -thresh_int || - ( ( S[0] + S[1] ) << Q19 ) > ( ( ( (Word64) 1 ) << 32 ) + thresh_int ) ) + // Q32 S + IF( LT_16( ( Q20 - matInv_exp_final[0] - P_minus_A_exp_final - invFactor_exp ), 0 ) ) + { + S[0] = S[0] >> ( matInv_exp_final[0] + P_minus_A_exp_final + invFactor_exp - Q20 ); + } + ELSE + { + S[0] = S[0] << ( Q20 - matInv_exp_final[0] - P_minus_A_exp_final - invFactor_exp ); + } + IF( LT_16( ( Q20 - matInv_exp_final[1] - P_minus_A_exp_final - invFactor_exp ), 0 ) ) + { + S[1] = S[1] >> ( matInv_exp_final[1] + P_minus_A_exp_final + invFactor_exp - Q20 ); + } + ELSE + { + S[1] = S[1] << ( Q20 - matInv_exp_final[1] - P_minus_A_exp_final - invFactor_exp ); + } + + IF( LT_64( S[0], -thresh_int ) || LT_64( S[1], -thresh_int ) || GT_64( ( S[0] + S[1] ), ( ( (Word64) 1 ) << 32 ) + thresh_int ) ) { return 0; } @@ -3871,6 +3886,8 @@ static Word16 in_tri_fixed( } } #endif + +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------------* * sph2cart() * @@ -3889,7 +3906,7 @@ static void sph2cart( return; } -#ifdef IVAS_FLOAT_FIXED +#else /*-------------------------------------------------------------------------* * sph2cart_fixed() * @@ -3903,28 +3920,28 @@ static void sph2cart_fixed( ) { Word16 azi_temp, ele_temp; - IF( azi >= 0 ) + IF( GE_32( azi, 0 ) ) { - azi_temp = div_l( ( azi >> Q6 ), 360 ); + azi_temp = div_l( L_shr( azi, Q6 ), 360 ); } ELSE { - azi_temp = div_l( L_negate( azi >> Q6 ), 360 ); + azi_temp = div_l( L_negate( L_shr( azi, Q6 ) ), 360 ); azi_temp = negate( azi_temp ); } - IF( ele >= 0 ) + IF( GE_32( ele, 0 ) ) { - ele_temp = div_l( ( ele >> Q6 ), 360 ); + ele_temp = div_l( L_shr( ele, Q6 ), 360 ); } ELSE { - ele_temp = div_l( L_negate( ele >> Q6 ), 360 ); + ele_temp = div_l( L_negate( L_shr( ele, Q6 ) ), 360 ); ele_temp = negate( ele_temp ); } pos[0] = Mpy_32_16( getCosWord16R2( azi_temp ), 0, getCosWord16R2( ele_temp ) ); pos[1] = Mpy_32_16( getSineWord16R2( azi_temp ), 0, getCosWord16R2( ele_temp ) ); - pos[2] = getSineWord16R2( ele_temp ) << Q16; + pos[2] = L_shl( getSineWord16R2( ele_temp ), Q16 ); return; } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index bc14bd292a223a8aa7b72a7fae5ab41b18a59637..e19ab76f35649779803406cee306cfc33aa90454 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -189,8 +189,8 @@ ivas_error efap_init_data( #ifdef IVAS_FLOAT_FIXED ivas_error efap_init_data_fixed( EFAP_HANDLE *hEFAPdata, /* i/o: handle for EFAP data structure that will be initialized */ - const float *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ - const float *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ + const Word32 *speaker_node_azi_deg, /* i : vector of speaker node azimuths (positive left) */ + const Word32 *speaker_node_ele_deg, /* i : vector of speaker node elevations (positive up) */ const Word16 num_speaker_nodes, /* i : number of speaker nodes in the set */ const Word16 efap_mode /* i : indicates whether EFAP or EFIP is used */ ); diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 8014215be17d2e4d659e36207465407223b7c695..8062670b25fff053878560e1024b3bed108f5264 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -706,9 +706,15 @@ typedef struct EFAP #endif EFAP_VERTEX_DATA vtxData; /* Vertex Data, contains all the data concerning the vertex */ EFAP_POLYSET_DATA polyData; /* Polygon data */ +#ifndef IVAS_FLOAT_FIXED float **dmTranspose; /* Downmix Matrix used for redistributing the energy of ghosts LS and its transpose */ float *bufferLong; /* tmp buffer that will be given as a parameter for computing the gain; this is a 1D array of length numVtx */ float *bufferShort; /* tmp buffer that will be given as a parameter for computing the gain; this is the result of downMixMatrix*bufferLong, length is numSpk */ +#else + Word32 **dmTranspose_fx; /* Downmix Matrix used for redistributing the energy of ghosts LS and its transpose */ + Word32 *bufferLong_fx; /* tmp buffer that will be given as a parameter for computing the gain; this is a 1D array of length numVtx */ + Word32 *bufferShort_fx; /* tmp buffer that will be given as a parameter for computing the gain; this is the result of downMixMatrix*bufferLong, length is numSpk */ +#endif int16_t numTot; /* Total number of real + ghost loudspeakers, used later for freeing memory */ } EFAP, *EFAP_HANDLE; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 752dd2034322b487c9742a35f137a5936568aebb..2f5afba06861675417fd7834975776c3de8824ea 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -953,11 +953,7 @@ static ivas_error initEfap( if ( outConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { -#ifndef IVAS_FLOAT_FIXED if ( ( error = efap_init_data( &pEfapWrapper->hEfap, pCustomLsOut->ls_azimuth, pCustomLsOut->ls_elevation, pCustomLsOut->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - if ( ( error = efap_init_data_fixed( &pEfapWrapper->hEfap, pCustomLsOut->ls_azimuth, pCustomLsOut->ls_elevation, pCustomLsOut->num_spk, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -979,11 +975,7 @@ static ivas_error initEfap( return error; } -#ifndef IVAS_FLOAT_FIXED if ( ( error = efap_init_data( &pEfapWrapper->hEfap, azimuths, elevations, numNonLfeChannels, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#else - if ( ( error = efap_init_data_fixed( &pEfapWrapper->hEfap, azimuths, elevations, numNonLfeChannels, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) -#endif { return error; }