diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 6a50483e5761c1ee1a36653e49f0f977ede2f7cf..b9985a11da6c798343e70f692558d1c15df23598 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1131,9 +1131,17 @@ enum #define MASA_TRANSP_BITS 1 #define NO_BITS_MASA_ISM_NO_OBJ 2 +#ifdef IVAS_FLOAT_FIXED +#define MASA2TOTAL_THR 0.979965f // Temporary +//Maximum error in float to fixed conversion : 0.005% +//Assuming the accuracy of 99.995% +//New value = 99.995 / 100 * 0.98 = 0.979951 +#else #define MASA2TOTAL_THR 0.98f +#endif #define BITS_MASA2TOTTAL_DCT0 6 #define STEP_M2T 0.1f +#define STEP_M2T_FX 214748364 #define MASA_HEADER_BITS 2 #define MASA_SUBFRAME_BITS 1 #define MASA_LOWBITRATE_MODE_BITS 1 diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index a490858c8c964867bd423a45b53e72673695e13f..27e3b83939a19144a54d468fcc0e59b6b7e3c9c7 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -48,6 +48,9 @@ static uint16_t deindex_sph_idx_general( const int16_t idx_sph, const int16_t no_bits, float *theta_dec, float *phi_dec, uint16_t *p_id_phi, const MC_LS_SETUP mc_format ); +#ifdef IVAS_FLOAT_FIXED +static UWord16 deindex_sph_idx_general_fx( const Word16 idx_sph, const Word16 no_bits, Word32 *theta_dec_fx, Word32 *phi_dec_fx, UWord16 *p_id_phi, const MC_LS_SETUP mc_format ); +#endif /*------------------------------------------------------------------------- * ivas_get_hodirac_flag() @@ -162,10 +165,8 @@ ivas_error ivas_dirac_config( hConfig->dec_param_estim = FALSE; if ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) /* skip for MASA decoder */ { - if ( ( error = ivas_dirac_sba_config( hQMetaData, element_mode, ivas_total_brate, sba_order, hConfig->nbands - spar_dirac_split_band - , - ivas_format - ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_dirac_sba_config( hQMetaData, element_mode, ivas_total_brate, sba_order, hConfig->nbands - spar_dirac_split_band, + ivas_format ) ) != IVAS_ERR_OK ) { return error; } @@ -322,10 +323,8 @@ void ivas_get_dirac_sba_max_md_bits( int16_t *bits_frame_nominal, int16_t *metadata_max_bits, int16_t *qmetadata_max_bit_req, - const int16_t nbands - , - IVAS_FORMAT ivas_format -) + const int16_t nbands, + IVAS_FORMAT ivas_format ) { if ( sba_total_brate <= IVAS_13k2 ) { @@ -402,8 +401,7 @@ ivas_error ivas_dirac_sba_config( const int16_t sba_order, /* i : Ambisonic (SBA) order */ const int16_t nbands /* i : number of frequency bands */ , - IVAS_FORMAT ivas_format -) + IVAS_FORMAT ivas_format ) { int16_t nbands_coded; int16_t hodirac_flag; @@ -465,10 +463,8 @@ ivas_error ivas_dirac_sba_config( } } - ivas_get_dirac_sba_max_md_bits( sba_total_brate, &hQMetaData->bits_frame_nominal, &hQMetaData->metadata_max_bits, &hQMetaData->qmetadata_max_bit_req, hQMetaData->q_direction[0].cfg.nbands - , - ivas_format - ); + ivas_get_dirac_sba_max_md_bits( sba_total_brate, &hQMetaData->bits_frame_nominal, &hQMetaData->metadata_max_bits, &hQMetaData->qmetadata_max_bit_req, hQMetaData->q_direction[0].cfg.nbands, + ivas_format ); return error; } @@ -648,10 +644,60 @@ float deindex_azimuth( { phi_hat = companding_azimuth( phi_hat, mc_format, ( id_th * delta_theta_masa[no_bits - 3] > MC_MASA_THR_ELEVATION ), -1 ); } - return phi_hat; } +#ifdef IVAS_FLOAT_FIXED +Word32 deindex_azimuth_fx( + Word16 id_phi, /* i : index */ + const Word16 no_bits, /* i : number of bits for the spherical grid */ + const Word16 id_th, /* i : elevation index */ + const Word16 remap, /* i : remapping flag */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +) +{ + Word16 flag_delta; + Word32 dd_fx, delta_phi_fx; + Word32 phi_hat_fx; + IF( ( mc_format != MC_LS_SETUP_INVALID ) && ( no_bits == 2 ) ) + { + IF( id_phi % 2 == 0 ) + { + phi_hat_fx = cb_azi_chan_fx[id_phi / 2]; + } + ELSE + { + phi_hat_fx = -cb_azi_chan_fx[( id_phi + 1 ) / 2]; + } + return phi_hat_fx; + } + flag_delta = ( id_th % 2 == 1 ); + + IF( remap ) + { + id_phi = ivas_qmetadata_dereorder_generic( id_phi ) + ( no_phi_masa[no_bits - 1][id_th] >> 1 ); + } + + delta_phi_fx = Mpy_32_32( 1509949440, no_phi_masa_inv_fx[no_bits - 1][id_th] ); // q = 22 + IF( ( flag_delta == 1 ) && ( no_phi_masa[no_bits - 1][id_th] > 2 ) && mc_format == MC_LS_SETUP_INVALID ) + { + dd_fx = Mpy_32_32( delta_phi_fx, 1073741824 ); // q = 22 + } + ELSE + { + dd_fx = 0; + } + + id_phi -= ( ( no_phi_masa[no_bits - 1][id_th] ) >> 1 ); + phi_hat_fx = L_add( id_phi * delta_phi_fx, dd_fx ); + IF( mc_format != MC_LS_SETUP_INVALID ) + { + phi_hat_fx = companding_azimuth_fx( phi_hat_fx, mc_format, ( id_th * delta_theta_masa[no_bits - 3] > MC_MASA_THR_ELEVATION ), -1 ); + } + return phi_hat_fx; +} +#endif + /*---------------------------------------------------------------- * deindex_spherical_component() @@ -698,6 +744,50 @@ void deindex_spherical_component( return; } +#ifdef IVAS_FLOAT_FIXED +void deindex_spherical_component_fx( + const UWord16 sph_idx, /* i : spherical index */ + Word32 *az_fx, /* o : decoded azimuth value */ + Word32 *el_fx, /* o : decoded elevation value */ + UWord16 *az_idx, /* o : azimuth index */ + UWord16 *el_idx, /* o : elevation index */ + const UWord16 no_bits, /* i : number of bits for the spherical grid */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +) +{ + Word32 az_idx_fx; + Word16 q_az_idx; + assert( sph_idx < ( 1 << no_bits ) ); + SWITCH( no_bits ) + { + case 0: + *az_fx = 0; + *el_fx = 0; + *az_idx = 0; + *el_idx = 0; + BREAK; + case 1: + *az_idx = sph_idx; + q_az_idx = norm_l( *az_idx ); + az_idx_fx = L_shl( *az_idx, q_az_idx ); + *az_fx = L_shl( Mpy_32_32( az_idx_fx, L_shl( -180, 22 ) ), 31 - q_az_idx ); + *el_fx = 0; + *el_idx = 0; + BREAK; + case 2: + *el_fx = 0; + *el_idx = 0; + *az_idx = sph_idx; + *az_fx = deindex_azimuth_fx( *az_idx, no_bits, 0, 0, mc_format ); + BREAK; + default: + *el_idx = deindex_sph_idx_general_fx( sph_idx, no_bits, el_fx, az_fx, az_idx, mc_format ); + BREAK; + } + + return; +} +#endif /*---------------------------------------------------------------- * calculate_hodirac_sector_parameters() @@ -1022,3 +1112,121 @@ static uint16_t deindex_sph_idx_general( return id_th; } + +#ifdef IVAS_FLOAT_FIXED +static UWord16 deindex_sph_idx_general_fx( + const Word16 idx_sph, /* i : spherical index */ + const Word16 no_bits, /* i : number of bits in the spherical grid*/ + Word32 *theta_dec_fx, /* o : decoded elevation value */ + Word32 *phi_dec_fx, /* o : decoded azimuth value */ + UWord16 *p_id_phi, /* o : decoded azimuth index */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +) +{ + Word16 i; + UWord16 id_th; + Word16 q_id_th; + Word32 id_th_fx; + Word16 sign_theta; + Word16 id_phi; + Word16 cum_n[250]; + Word16 no_th; + const Word16 *n; + + id_th = 0; + id_phi = 0; + sign_theta = 1; + + no_th = no_theta_masa[no_bits - 3]; + n = no_phi_masa[no_bits - 1]; + IF( mc_format != MC_LS_SETUP_INVALID ) + { + /* indexing */ + + cum_n[0] = n[0]; + IF( idx_sph >= cum_n[0] ) + { + FOR( i = 1; i < no_th; i++ ) + { + cum_n[i] = cum_n[i - 1] + n[i]; + IF( idx_sph < cum_n[i] ) + { + id_th = i; + id_phi = idx_sph - cum_n[i - 1]; + BREAK; + } + } + } + } + ELSE + { + /* Starting from Equator, alternating positive and negative */ + cum_n[0] = n[0]; + IF( idx_sph >= cum_n[0] ) + { + FOR( i = 1; i < no_th; i++ ) + { + cum_n[2 * i - 1] = cum_n[2 * i - 2] + n[i]; + + IF( idx_sph < cum_n[2 * i - 1] ) + { + id_th = i; + sign_theta = 1; + id_phi = idx_sph - cum_n[2 * i - 2]; + BREAK; + } + + cum_n[2 * i] = cum_n[2 * i - 1] + n[i]; + + IF( idx_sph < cum_n[2 * i] ) + { + id_th = i; + sign_theta = -1; + id_phi = idx_sph - cum_n[2 * i - 1]; + BREAK; + } + + IF( i == ( no_th - 1 ) ) + { + id_th = i; + sign_theta = -1; + id_phi = 0; /* idx_sph - cum_n[2*i-1]; */ + BREAK; + } + } + } + } + + IF( id_th == 0 ) + { + id_phi = idx_sph; + } + ELSE + { + IF( ( id_th == no_th - 1 ) && ( no_bits > 4 ) ) + { + id_phi = 0; + } + } + + q_id_th = norm_l( id_th ); + id_th_fx = L_shl( id_th, q_id_th ); + *theta_dec_fx = L_shl( Mpy_32_32( id_th_fx, delta_theta_masa_fx[no_bits - 3] ), 31 - q_id_th ); + + IF( *theta_dec_fx >= L_shl( 90, 22 ) ) + { + *theta_dec_fx = L_shl( 90, 22 ) * sign_theta; + *phi_dec_fx = 0; + *p_id_phi = 0; + } + ELSE + { + *theta_dec_fx *= sign_theta; + + *phi_dec_fx = deindex_azimuth_fx( id_phi, no_bits, id_th, 0, mc_format ); + *p_id_phi = id_phi; + } + + return id_th; +} +#endif \ No newline at end of file diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index abb4dbd552c9c4ed956ce146329474da464e679b..6a5f2529a9864b9a36875867dad840ae6b9cb5b5 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -791,6 +791,152 @@ void deindex_sph_idx( return; } +#ifdef IVAS_FLOAT_FIXED +// void deindex_sph_idx( +// const UWord16 sphIndex, /* i : Spherical index */ +// const SPHERICAL_GRID_DATA *gridData, /* i : Prepared spherical grid */ +// Word32 *theta_fx, /* o : Elevation */ +// Word32 *phi_fx /* o : Azimuth */ +//) +//{ +// Word32 ba_crt_fx, del_crt_fx, div_crt_fx, a4_crt_fx; +// Word32 estim; +// Word32 base_low, base_up; +// Word16 n_crt; +// Word16 id_th; +// Word16 sign_theta; +// Word16 id_phi; +// Word16 no_th = gridData->no_theta; +// const Word16 *n = gridData->no_phi; +// const Word32 ba_fx[3] = { 109465, 63736, 62894 }; // q = 9 +// const Word32 del_fx[3] = { 409511008, 666052608, 729124992 }; // q = 9 +// const Word32 div_fx[3] = { -121, -51, -47 }; // q = 9 +// const Word32 a4_fx[3] = { -4308, -10144, -11124 }; // q = 9 +// const UWord16 limit_index1 = 64964, limit_index2 = 47870; +// +// if ( sphIndex >= limit_index1 ) +// { +// ba_crt_fx = ba_fx[2]; +// div_crt_fx = div_fx[2]; +// a4_crt_fx = a4_fx[2]; +// del_crt_fx = del_fx[2]; +// } +// else if ( sphIndex >= limit_index2 ) +// { +// ba_crt_fx = ba_fx[1]; +// div_crt_fx = div_fx[1]; +// a4_crt_fx = a4_fx[1]; +// del_crt_fx = del_fx[1]; +// } +// else +// { +// ba_crt_fx = ba_fx[0]; +// div_crt_fx = div_fx[0]; +// a4_crt_fx = a4_fx[0]; +// del_crt_fx = del_fx[0]; +// } +// estim = ba_crt_fx + div_crt_fx * sqrtf( del_crt + a4_crt * sphIndex ); +// +// if ( estim > MASA_NO_CIRCLES ) +// { +// estim = MASA_NO_CIRCLES; +// } +// +// assert( estim > 0 ); +// id_th = (int16_t) roundf( estim ) - 1; +// if ( id_th < 0 ) +// { +// id_th = 0; +// } +// +// if ( id_th == 0 ) +// { +// base_low = 0; +// base_up = n[0]; +// } +// else +// { +// estim = MASA_ANGLE_AT_EQUATOR * (float) ( id_th - 0.5f ); +// base_low = n[0]; +// if ( id_th >= 2 ) +// { +// if ( id_th == 2 ) +// { +// base_low += 2 * (int16_t) ceilf( MASA_NTOT2_FAC * ( sinf( estim ) - MASA_ASIN_OFFSET ) ); +// } +// else +// { +// base_low += 2 * (int16_t) roundf( MASA_NTOT2_FAC * ( sinf( estim ) - MASA_ASIN_OFFSET ) ); +// } +// } +// base_up = base_low + 2 * n[id_th]; +// } +// +// sign_theta = 1; +// +// n_crt = n[id_th]; +// if ( sphIndex < base_low ) +// { +// id_th--; +// n_crt = n[id_th]; +// if ( id_th == 0 ) +// { +// base_low = 0; +// base_up = n_crt; +// } +// else +// { +// base_up = base_low; +// base_low -= 2 * n[id_th]; +// } +// assert( sphIndex >= base_low ); +// } +// else if ( sphIndex >= base_up ) +// { +// id_th++; +// n_crt = n[id_th]; +// base_low = base_up; +// base_up += 2 * n_crt; +// assert( sphIndex < base_up ); +// } +// +// id_phi = (int16_t) ( sphIndex - base_low ); +// if ( sphIndex - base_low >= n_crt ) +// { +// id_phi -= n_crt; +// sign_theta = -1; +// } +// +// if ( id_th == 0 ) +// { +// *theta = 0.f; +// *phi = (float) sphIndex * 360 / (float) n_crt - 180; +// } +// else +// { +// if ( id_th == no_th - 1 ) +// { +// id_phi = 0; +// *phi = -180; +// *theta = 90 * (float) sign_theta; +// } +// else +// { +// *theta = id_th * MASA_ANGLE_AT_EQUATOR_DEG * (float) sign_theta; +// if ( id_th % 2 == 0 ) +// { +// *phi = (float) id_phi * 360 / (float) n_crt - 180; +// } +// else +// { +// *phi = ( (float) id_phi + 0.5f ) * 360 / (float) n_crt - 180; +// } +// } +// } +// +// return; +// } +#endif /*--------------------------------------------------------------- * valid_ratio_index() diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 68f3a9de62c838608a4488a21e8d3d9bc37e017b..12179e153a26e9da2ecf649cc626c29e90e6821d 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -745,6 +745,12 @@ int16_t get_igf_startline( float rand_triangular_signed( int16_t *seed ); +Word64 var_32_fx( + const Word32 *x, /* i : input vector */ + const int16_t len, /* i : length of inputvector */ + Word16 q /* q : q-factor for the array */ +); + void dtx_read_padding_bits( DEC_CORE_HANDLE st, const int16_t num_bits @@ -3292,6 +3298,15 @@ float companding_azimuth( const int16_t direction /* i : direction of companding (direct or inverse)*/ ); +#ifdef IVAS_FLOAT_FIXED +Word32 companding_azimuth_fx( + const Word32 azi_fx, /* i : input azimuth value */ + const MC_LS_SETUP mc_format, /* i : input channel format */ + const Word16 theta_flag, /* i : zero/non zero elevation flag */ + const Word16 direction /* i : direction of companding (direct or inverse)*/ +); +#endif + /*! r: index azimuth */ int16_t quantize_phi_chan_lbr( const float phi, /* i : azimuth value */ @@ -3338,6 +3353,14 @@ float deindex_elevation( const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ ); +#ifdef IVAS_FLOAT_FIXED +Word32 deindex_elevation_fx( + UWord16 *id_th, /* i : input index */ + const Word16 no_bits, /* i : number of bits for the spherical grid */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +); +#endif + float deindex_azimuth( int16_t id_phi, /* i : index */ const int16_t no_bits, /* i : number of bits for the spherical grid */ @@ -3346,6 +3369,25 @@ float deindex_azimuth( const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ ); +#ifdef IVAS_FLOAT_FIXED +Word32 deindex_azimuth_fx( + Word16 id_phi, /* i : index */ + const Word16 no_bits, /* i : number of bits for the spherical grid */ + const Word16 id_th, /* i : elevation index */ + const Word16 remap, /* i : remapping flag */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +); +void deindex_spherical_component_fx( + const UWord16 sph_idx, /* i : spherical index */ + Word32 *az_fx, /* o : decoded azimuth value */ + Word32 *el_fx, /* o : decoded elevation value */ + UWord16 *az_idx, /* o : azimuth index */ + UWord16 *el_idx, /* o : elevation index */ + const UWord16 no_bits, /* i : number of bits for the spherical grid */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +); +#endif + void deindex_spherical_component( const uint16_t sph_idx, /* i : spherical index */ float *az, /* o : decoded azimuth value */ @@ -3871,6 +3913,20 @@ int16_t matrix_product( float *Z /* o : resulting matrix after the matrix multiplication */ ); +#ifdef IVAS_FLOAT_FIXED +Word16 matrix_product_fx( + const Word32 *X_fx, /* i : left hand matrix */ + const Word16 rowsX, /* i : number of rows of the left hand matrix */ + const Word16 colsX, /* i : number of columns of the left hand matrix */ + const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication */ + const Word32 *Y_fx, /* i : right hand matrix */ + const Word16 rowsY, /* i : number of rows of the right hand matrix */ + const Word16 colsY, /* i : number of columns of the right hand matrix */ + const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication */ + Word32 *Z_fx /* o : resulting matrix after the matrix multiplication */ +); +#endif + void mat2svdMat( const float *mat, /* i : matrix as column ordered vector */ float svdMat[MAX_OUTPUT_CHANNELS][MAX_OUTPUT_CHANNELS], /* o : matrix as two-dimensional arry */ @@ -4966,12 +5022,21 @@ void distribute_evenly_ism( const int16_t nchan_ism ); +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_qmetadata_DecodeExtendedGR( + UWord16* bitstream, + Word16* index, + const Word16 alph_size, + const Word16 gr_param +); +#else int16_t ivas_qmetadata_DecodeExtendedGR( uint16_t* bitstream, int16_t* index, const int16_t alph_size, const int16_t gr_param ); +#endif int16_t ivas_qmetadata_encode_extended_gr_length( const uint16_t value, @@ -5081,6 +5146,14 @@ void invdct4_transform( uint8_t *invdct_v /* o : transformed vector */ ); +#ifdef IVAS_FLOAT_FIXED +void invdct4_transform_fx( + Word32 *v_fx, /* i : input vector */ + UWord8 *invdct_v, /* o : transformed vector */ + Word16 q +); +#endif + void update_bits_next_block( IVAS_QDIRECTION *q_direction, /* i/o: qdirection */ int16_t *p_diff, /* i/o: bits to be transferred */ @@ -5752,6 +5825,16 @@ void ivas_omasa_decode_masa_to_total( const int16_t nblocks ); +#ifdef IVAS_FLOAT_FIXED +void ivas_omasa_decode_masa_to_total_fx( + UWord16 *bit_stream, + Word16 *index, + Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + const Word16 nbands, + const Word16 nblocks, + Word16 *q); +#endif + void ivas_omasa_modify_masa_energy_ratios( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_MAXIMUM_CODING_SUBBANDS] diff --git a/lib_com/ivas_qmetadata_com.c b/lib_com/ivas_qmetadata_com.c index 57adf7c6aae2048cad144afefbaffe5e418b4cb8..7ca4a37cd010254fd0fcd96a4f3656871384285c 100644 --- a/lib_com/ivas_qmetadata_com.c +++ b/lib_com/ivas_qmetadata_com.c @@ -486,6 +486,44 @@ void invdct4_transform( return; } +#ifdef IVAS_FLOAT_FIXED +void invdct4_transform_fx( + Word32 *v_fx, /* i : input vector */ + UWord8 *invdct_v, /* o : inverse transformed vector */ + Word16 q ) +{ + Word32 a_fx, b_fx, c_fx, d_fx; + int16_t i; + Word32 f_invdct_v_fx[4]; + + a_fx = L_add( v_fx[0], v_fx[2] ); + b_fx = L_sub( v_fx[0], v_fx[2] ); + c_fx = L_shl( L_add( Mpy_32_32( 1402911360, v_fx[1] ), Mpy_32_32( 581104896, v_fx[3] ) ), 31 - 30 ); + d_fx = L_shl( L_sub( Mpy_32_32( 581104896, v_fx[1] ), Mpy_32_32( 1402911360, v_fx[3] ) ), 31 - 30 ); + f_invdct_v_fx[0] = L_shl( L_add( a_fx, c_fx ), 7 ); + f_invdct_v_fx[1] = L_shl( L_add( b_fx, d_fx ), 7 ); + f_invdct_v_fx[2] = L_shl( L_sub( b_fx, d_fx ), 7 ); + f_invdct_v_fx[3] = L_shl( L_sub( a_fx, c_fx ), 7 ); + + FOR( i = 0; i < 4; i++ ) + { + IF( f_invdct_v_fx[i] < 0 ) + { + invdct_v[i] = 0; + } + ELSE + { + IF( f_invdct_v_fx[i] > L_shl( 255, q ) ) + { + f_invdct_v_fx[i] = L_shl( 255, q ); + } + invdct_v[i] = (uint8_t) L_shr( f_invdct_v_fx[i], q ); + } + } + + return; +} +#endif /*--------------------------------------------------------------- * masa_compensate_two_dir_energy_ratio_index() diff --git a/lib_com/ivas_qspherical_com.c b/lib_com/ivas_qspherical_com.c index e754fb692bbd3ab149ffcf930c7931c3115e930d..30ab85904071a0838be2ebe604e1e153cfd396d5 100644 --- a/lib_com/ivas_qspherical_com.c +++ b/lib_com/ivas_qspherical_com.c @@ -370,6 +370,125 @@ float companding_azimuth( return comp_azi; } +#ifdef IVAS_FLOAT_FIXED +Word32 companding_azimuth_fx( + const Word32 azi_fx, /* i : input azimuth value */ + const MC_LS_SETUP mc_format, /* i : input channel format */ + const Word16 theta_flag, /* i : zero/non zero elevation flag */ + const Word16 direction /* i : direction of companding (direct or inverse)*/ +) +{ + const Word16 pointsA[] = { 0, 60, 110, 150, 180, 0, 50, 90, 150, 180, 0, 30, 80, 150, 180 }; + const Word16 pointsB[] = { 0, 90, 110, 170, 180, 0, 90, 110, 170, 180, 0, 10, 100, 170, 180 }; + const Word16 *pA, *pB; + const Word32 pointsA_fx[] = { 0, 251658240, 461373440, 629145600, 754974720, 0, 209715200, 377487360, 629145600, 754974720, 0, 125829120, 335544320, 629145600, 754974720 }; // q=22 + const Word32 pointsB_fx[] = { 0, 377487360, 461373440, 713031680, 754974720, 0, 377487360, 461373440, 713031680, 754974720, 0, 41943040, 419430400, 713031680, 754974720 }; // q=22 + const Word32 *pA_fx, *pB_fx; + Word16 no_points; + Word32 comp_azi_fx; + Word16 i, not_done, start; + Word32 abs_azi_fx; + + IF( mc_format == MC_LS_SETUP_5_1 || mc_format == MC_LS_SETUP_5_1_2 || mc_format == MC_LS_SETUP_5_1_4 ) /* 5.1, 5.1+2 or 5.1+4*/ + { + start = 5; + } + ELSE + { + start = 0; + } + + /* theta flag 1 is for non zero, larger than a threshold elevation */ + IF( ( theta_flag == 1 ) && ( ( mc_format == MC_LS_SETUP_5_1_2 ) || ( mc_format == MC_LS_SETUP_5_1_4 ) || ( mc_format == MC_LS_SETUP_7_1_4 ) ) ) /* 5.1+2, 5.1+4 or 7.1+4*/ + { + start = 10; + } + no_points = 5; + + pA_fx = &pointsA_fx[start]; + pB_fx = &pointsB_fx[start]; + pA = &pointsA[start]; + pB = &pointsB[start]; + + IF( direction == -1 ) /* inverse companding */ + { + pA_fx = &pointsB_fx[start]; + pB_fx = &pointsA_fx[start]; + pA = &pointsB[start]; + pB = &pointsA[start]; + } + ELSE + { + IF( direction != 1 ) + { + printf( "Wrong direction in companding" ); + } + } + + not_done = 1; + abs_azi_fx = L_abs( azi_fx ); + + comp_azi_fx = azi_fx; + i = 0; + WHILE( not_done && ( i < no_points - 1 ) ) + { + IF( abs_azi_fx <= pA_fx[i + 1] ) + { + not_done = 0; + /* calculate companding */ + comp_azi_fx = Mpy_32_32( L_sub( pB_fx[i + 1], pB_fx[i] ), L_sub( abs_azi_fx, pA_fx[i] ) ); + SWITCH( pA[i + 1] - pA[i] ) + { + case 10: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 214748364 ); + BREAK; + case 20: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 107374182 ); + BREAK; + case 30: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 71582788 ); + BREAK; + case 40: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 53687091 ); + BREAK; + case 50: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 42949672 ); + BREAK; + case 60: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 35791394 ); + BREAK; + case 70: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 30678337 ); + BREAK; + case 90: + comp_azi_fx = Mpy_32_32( comp_azi_fx, 23860929 ); + BREAK; + default: + assert( 0 ); + BREAK; + } + comp_azi_fx = L_add( pB_fx[i], L_shl( comp_azi_fx, 31 - 22 ) ); + // comp_azi = pB[i] + ( pB[i + 1] - pB[i] ) / ( pA[i + 1] - pA[i] ) * ( abs_azi - pA[i] ); + } + ELSE + { + i++; + } + } + + IF( azi_fx < 0 ) + { + comp_azi_fx = L_negate( comp_azi_fx ); + } + + IF( not_done == 1 ) + { + comp_azi_fx = azi_fx; + } + + return comp_azi_fx; +} +#endif /*-----------------------------------------------------------------------* * quantize_phi_chan_lbr() diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index ad8279712ee5b1539860287fd87dc84dd0a3c50c..e34016da89f6b48217b49afebf116635517a7254 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -835,6 +835,13 @@ const float diffuseness_reconstructions[DIRAC_DIFFUSE_LEVELS] = 0.85009765625f }; +#ifdef IVAS_FLOAT_FIXED +const Word32 diffuseness_reconstructions_fx[DIRAC_DIFFUSE_LEVELS] = // q = 30 +{ + 0, 42467328, 96206848, 170655744, 331087872, 508821504, 678952960, 912785408 +}; +#endif + const float diffuseness_thresholds[DIRAC_DIFFUSE_LEVELS + 1] = { 0.0f, @@ -2621,6 +2628,29 @@ const float coherence_cb1_masa[MASA_NO_CV_COH1*MASA_MAXIMUM_CODING_SUBBANDS] = 0.0017f, 0.2521f, -0.2479f, 0.7217f, -0.7157f }; +#ifdef IVAS_FLOAT_FIXED + +const Word32 coherence_cb0_masa_fx[DIRAC_DIFFUSE_LEVELS * 2 * MASA_NO_CV_COH] = //q = 21 +{ + 100243, 534144, 1156579, 2068840, 2846464, 3531184, 4125936, 0, 253965, 864655, 1467377, + 2129448, 2977326, 3768791, 0, 0, 338480, 1189924, 2035915, 2872888, 3640026, 0, 0, 0, + 492621, 1532179, 2527278, 3470157, 0, 0, 0, 0, 499331, 1506803, 2465831, 3425697, 0, + 0, 0, 0, 503316, 1473668, 2392221, 3406404, 0, 0, 0, 0, 737778, 1970903, 3450654, 0, 0, + 0, 0, 0, 2097152, 0, 0, 0, 0, 0, 0, 0, 303038, 719742, 1122186, 1577897, 2117075, 2770337, + 3648834, 0, 419849, 932603, 1440533, 2011797, 2745172, 3571240, 0, 0, 548824, 1165177, + 1812987, 2555379, 3366138, 0, 0, 0, 695835, 1428160, 2190475, 3084910, 0, 0, 0, 0, 697093, + 1381603, 2092957, 2970406, 0, 0, 0, 0, 708417, 1396283, 2099039, 2992426, 0, 0, 0, 0, 835924, + 1728892, 2836607, 0, 0, 0, 0, 0, 2097152, 0, 0, 0, 0, 0, 0, 0 +}; + +const Word32 coherence_cb1_masa_fx[MASA_NO_CV_COH1*MASA_MAXIMUM_CODING_SUBBANDS] = // q = 21 +{ + -3984, 544630, -565392, 1314704, -1320157, -11534, 541484, -583847, 1357486, -1371118, + -6081, 525546, -551551, 1362729, -1371537, -838, 533934, -540855, 1436758, -1414109, + 3565, 528692, -519883, 1513514, -1500931 +}; +#endif + const int16_t len_cb_dct0_masa[DIRAC_DIFFUSE_LEVELS] = { 7, 6, 5, 4, 4, 4, 3, 2 }; const uint8_t sur_coherence_cb_masa[MASA_MAX_NO_CV_SUR_COH*MASA_NO_CB_SUR_COH] = @@ -2659,6 +2689,31 @@ const int16_t no_phi_masa[NO_SPHERICAL_GRIDS][MAX_NO_THETA] = /* from 1 to 11 bi { 60, 60, 58, 56, 54, 50, 46, 41, 36, 30, 23, 17, 10, 1 }, { 89, 89, 88, 86, 84, 81, 77, 73, 68, 63, 57, 51, 44, 38, 30, 23, 15, 8, 1 } }; +#ifdef IVAS_FLOAT_FIXED +const Word32 no_phi_masa_inv_fx[NO_SPHERICAL_GRIDS][MAX_NO_THETA] = /* from 1 to 11 bits*/ /*q factor = 8*/ +{ + {1073741824}, + {536870912}, + {536870912, 1073741824}, + {268435456, 536870912}, + {178956970, 306783378, 1073741824, 2147483648}, + {153391689, 165191049, 238609294, 1073741824, 2147483648}, + {97612893, 102261126, 126322567, 195225786, 715827882, 2147483648}, + {65075262, 67108864, 74051160, 93368854, 126322567, 238609294, 2147483648}, + {44739242, 45691141, 47721858, 52377649, 61356675, 76695844, 107374182, 178956970, 1073741824, 2147483648}, + {35791394, 35791394, 37025580, 38347922, 39768215, 42949672, 46684427, 52377649, 59652323, 71582788, 93368854, 126322567, 214748364, 2147483648}, + {24129029, 24129029, 24403223, 24970740, 25565281, 26512143, 27889398, 29417584, 31580641, 34087042, 37675151, 42107522, 48806446, 56512727, 71582788, 93368854, 143165576, 268435456, 2147483648} +}; + +const Word32 azimuth_cb_fx[8] = +{ + 0, -754974720, -377487360, 377487360, -188743680, 188743680, -566231040, 566231040 +}; + +const Word32 delta_theta_masa_fx[NO_SPHERICAL_GRIDS - 2] = +{ 188743680, 188743680, 150994944, 106954752, 83886080, 62914560, 45214596, 28101836, 20971520 }; + +#endif const float delta_theta_masa[NO_SPHERICAL_GRIDS - 2] = { /*180.0f, 90.0f,*/ 45.0f, 45.0f, 36.0f, 25.5f, 20.0f, /*14.9f*/ 15.0f, 10.78f, 6.7f, 5.0f }; @@ -2787,6 +2842,10 @@ const float ls_elevation_CICP19[11] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0 const float cb_azi_chan[] = { 0.0f, 30.0f, 110.0f, 135.0f }; +#ifdef IVAS_FLOAT_FIXED +const Word32 cb_azi_chan_fx[] = { 0, 125829120, 461373440, 566231040 }; +#endif + const float McMASA_LFEGain_vectors[64] = { 0.38f, 0.33f, 0.19f, 0.20f, /* 1st bit */ @@ -2875,6 +2934,53 @@ const float dct12[12*12]= 0.2887f, -0.4048f, 0.3943f, -0.3772f, 0.3536f, -0.3239f, 0.2887f, -0.2485f, 0.2041f, -0.1562f, 0.1057f, -0.0533f }; +#ifdef IVAS_FLOAT_FIXED +const Word32 dct4_fx[4*4] = +{ + 1073741824, 1402951040, 1073741824, 581109056, + 1073741824, 581109056, -1073741824, -1402951040, + 1073741824, -581109056, -1073741824, 1402951040, + 1073741824, -1402951040, 1073741824, -581109056 +}; + +const Word32 dct5_fx[5*5] = +{ + 960354688, 1291711360, 1098867328, 798219648, 419618304, + 960354688, 798219648, -419618304, -1291711360, -1098867328, + 960354688, 0, -1358283392, 0, 1358283392, + 960354688, -798219648, -419618304, 1291711360, -1098867328, + 960354688, -1291711360, 1098867328, -798219648, 419618304 +}; + +const Word32 dct8_fx[8*8] = +{ + 759350208, 1053125952, 991922688, 892708928, 759350208, 596570944, 410813632, 209379648, + 759350208, 892708928, 410813632, -209379648, -759350208, -1053125952, -991922688, -596570944, + 759350208, 596570944, -410813632, -1053125952, -759350208, 209379648, 991922688, 892708928, + 759350208, 209379648, -991922688, -596570944, 759350208, 892708928, -410813632, -1053125952, + 759350208, -209379648, -991922688, 596570944, 759350208, -892708928, -410813632, 1053125952, + 759350208, -596570944, -410813632, 1053125952, -759350208, -209379648, 991922688, -892708928, + 759350208, -892708928, 410813632, 209379648, -759350208, 1053125952, -991922688, 596570944, + 759350208, -1053125952, 991922688, -892708928, 759350208, -596570944, 410813632, -209379648 +}; + +const Word32 dct12_fx[12*12]= +{ + 619978560, 869301376, 846752832, 810030848, 759350208, 695569984, 619978560, 533649696, 438301408, 335436960, 226989024, 114460880, + 619978560, 810030848, 619978560, 335436960, 0, -335436960, -619978560, -810030848, -876602816, -810030848, -619978560, -335436960, + 619978560, 695569984, 226989024, -335436960, -759350208, -869301376, -619978560, -114460880, 438301408, 810030848, 846752832, 533649696, + 619978560, 533649696, -226989024, -810030848, -759350208, -114460880, 619978560, 869301376, 438301408, -335436960, -846752832, -695569984, + 619978560, 335436960, -619978560, -810030848, 0, 810030848, 619978560, -335436960, -876602816, -335436960, 619978560, 810030848, 619978560, + 114460880, -846752832, -335436960, 759350208, 533649696, -619978560, -695569984, 438301408, 810030848, -226989024, -869301376, 619978560, + -114460880, -846752832, 335436960, 759350208, -533649696, -619978560, 695569984, 438301408, -810030848, -226989024, 869301376, 619978560, + -335436960, -619978560, 810030848, 0, -810030848, 619978560, 335436960, -876602816, 335436960, 619978560, -810030848, 619978560, -533649696, + -226989024, 810030848, -759350208, 114460880, 619978560, -869301376, 438301408, 335436960, -846752832, 695569984, 619978560, -695569984, + 226989024, 335436960, -759350208, 869301376, -619978560, 114460880, 438301408, -810030848, 846752832, -533649696, 619978560, -810030848, + 619978560, -335436960, 0, 335436960, -619978560, 810030848, -876602816, 810030848, -619978560, 335436960, 619978560, -869301376, 846752832, + -810030848, 759350208, -695569984, 619978560, -533649696, 438301408, -335436960, 226989024, -114460880 +}; +#endif + /*----------------------------------------------------------------------------------* * ISM ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index b13d415487dc36d6875ec3df31b0da3f70e06c9d..f9fb4e57a9d585f92a97508016e6851a3d560f01 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -150,6 +150,10 @@ extern const int16_t dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1]; * DirAC ROM tables *----------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +extern const Word32 diffuseness_reconstructions_fx[DIRAC_DIFFUSE_LEVELS]; +#endif + extern const float diffuseness_reconstructions[DIRAC_DIFFUSE_LEVELS]; extern const float diffuseness_thresholds[DIRAC_DIFFUSE_LEVELS + 1]; extern const int16_t DirAC_band_grouping_12[12 + 1]; @@ -265,6 +269,14 @@ extern const int16_t bits_direction_masa[DIRAC_DIFFUSE_LEVELS]; extern const int16_t no_theta_masa[NO_SPHERICAL_GRIDS - 2]; extern const int16_t no_phi_masa[NO_SPHERICAL_GRIDS][MAX_NO_THETA]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 no_phi_masa_inv_fx[NO_SPHERICAL_GRIDS][MAX_NO_THETA]; +extern const Word32 azimuth_cb_fx[8]; +extern const Word32 delta_theta_masa_fx[NO_SPHERICAL_GRIDS - 2]; +extern const Word32 coherence_cb0_masa_fx[DIRAC_DIFFUSE_LEVELS * 2 * MASA_NO_CV_COH]; +extern const Word32 coherence_cb1_masa_fx[MASA_NO_CV_COH1 * MASA_MAXIMUM_CODING_SUBBANDS]; /* 25 */ +#endif + extern const float delta_theta_masa[NO_SPHERICAL_GRIDS - 2]; extern const float azimuth_cb[8]; @@ -312,6 +324,9 @@ extern const float ls_azimuth_CICP19[11]; extern const float ls_elevation_CICP19[11]; extern const float cb_azi_chan[]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 cb_azi_chan_fx[]; +#endif extern const float McMASA_LFEGain_vectors[64]; @@ -325,6 +340,12 @@ extern const float dct5[]; extern const float dct8[]; extern const float dct12[]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 dct4_fx[]; +extern const Word32 dct5_fx[]; +extern const Word32 dct8_fx[]; +extern const Word32 dct12_fx[]; +#endif /*----------------------------------------------------------------------------------* * ISM ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 965c727c82f41bf8bf85d659519324d80f09ee1c..ba3417a4651c8769f21a844a235f05403b246711 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -56,32 +56,32 @@ typedef struct /* ISM metadata handle (storage for one frame of read ISM metadata) */ typedef struct { - int16_t ism_metadata_flag; /* flag whether metadata are coded in particular frame of particular object */ - int16_t last_ism_metadata_flag; /* last frame ism_metadata_flag */ + int16_t ism_metadata_flag; /* flag whether metadata are coded in particular frame of particular object */ + int16_t last_ism_metadata_flag; /* last frame ism_metadata_flag */ - float azimuth; /* azimuth value read from the input metadata file */ - float elevation; /* elevation value read from the input metadata file */ - float radius; /* radius value read from the input metadata file */ - float yaw; /* yaw value read from the input metadata file */ - float pitch; /* pitch value read from the input metadata file */ + float azimuth; /* azimuth value read from the input metadata file */ + float elevation; /* elevation value read from the input metadata file */ + float radius; /* radius value read from the input metadata file */ + float yaw; /* yaw value read from the input metadata file */ + float pitch; /* pitch value read from the input metadata file */ - int16_t non_diegetic_flag; /* Non-diegetic (non-headtracked) object flag */ + int16_t non_diegetic_flag; /* Non-diegetic (non-headtracked) object flag */ ISM_METADATA_ANGLE position_angle; /* Angle structs for azimuth and elevation */ ISM_METADATA_ANGLE orientation_angle; /* Angle structs for yaw and pitch */ int16_t last_radius_idx; /* last frame index of coded radius */ int16_t radius_diff_cnt; /* FEC counter of consecutive differentially radius coded frames */ - float last_azimuth; /* MD smoothing in DTX- last Q azimuth value */ - float last_elevation; /* MD smoothing in DTX - last Q elevation value */ - float last_true_azimuth; /* MD smoothing in DTX- last true Q azimuth value */ - float last_true_elevation; /* MD smoothing in DTX- last true Q elevation value */ + float last_azimuth; /* MD smoothing in DTX- last Q azimuth value */ + float last_elevation; /* MD smoothing in DTX - last Q elevation value */ + float last_true_azimuth; /* MD smoothing in DTX- last true Q azimuth value */ + float last_true_elevation; /* MD smoothing in DTX- last true Q elevation value */ - int16_t ism_md_fec_cnt_enc; /* counter of continuous frames where MD are not transmitted */ - int16_t ism_md_inc_diff_cnt; /* counter of continuous frames where MD are transmitted in inactive segments when MD significantly changes */ - float last_true_radius; /* last true Q radius value */ + int16_t ism_md_fec_cnt_enc; /* counter of continuous frames where MD are not transmitted */ + int16_t ism_md_inc_diff_cnt; /* counter of continuous frames where MD are transmitted in inactive segments when MD significantly changes */ + float last_true_radius; /* last true Q radius value */ - int16_t ism_imp; /* ISM importance flag */ + int16_t ism_imp; /* ISM importance flag */ int16_t ism_md_null_flag; int16_t ism_md_lowrate_flag; float q_azimuth_old; @@ -98,9 +98,9 @@ typedef struct stereo_dft_config_data_struct { int16_t dmx_active; int16_t band_res; - int16_t prm_res; /* Send prm every # DFT frames */ - int16_t res_pred_mode; /* mode : from 0 (off) to 1 (on) */ - int16_t res_cod_mode; /* mode : from 0 (off) to 3 */ + int16_t prm_res; /* Send prm every # DFT frames */ + int16_t res_pred_mode; /* mode : from 0 (off) to 1 (on) */ + int16_t res_cod_mode; /* mode : from 0 (off) to 3 */ int16_t hybrid_itd_flag; int16_t ada_wb_res_cod_mode; /* res_cod_mode for adaptive wide band residual coding */ @@ -473,10 +473,17 @@ typedef struct ivas_qdirection_band_data_struct uint16_t spherical_index[MAX_PARAM_SPATIAL_SUBFRAMES]; float azimuth[MAX_PARAM_SPATIAL_SUBFRAMES]; float elevation[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef IVAS_FLOAT_FIXED + Word32 azimuth_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 elevation_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; +#endif int16_t elevation_m_alphabet[MAX_PARAM_SPATIAL_SUBFRAMES]; int16_t azimuth_m_alphabet[MAX_PARAM_SPATIAL_SUBFRAMES]; float energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef IVAS_FLOAT_FIXED + Word32 energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; +#endif uint8_t distance[MAX_PARAM_SPATIAL_SUBFRAMES]; uint16_t bits_sph_idx[MAX_PARAM_SPATIAL_SUBFRAMES]; diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index 4e28892da362cd8c38dfeb1569b759c366158438..0f8805093a0d7cab5150a5fcc28e54934fb40120 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -681,6 +681,105 @@ int16_t matrix_product( return EXIT_SUCCESS; } +#ifdef IVAS_FLOAT_FIXED +Word16 matrix_product_fx( + const Word32 *X_fx, /* i : left hand matrix */ + const Word16 rowsX, /* i : number of rows of the left hand matrix */ + const Word16 colsX, /* i : number of columns of the left hand matrix */ + const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication */ + const Word32 *Y_fx, /* i : right hand matrix */ + const Word16 rowsY, /* i : number of rows of the right hand matrix */ + const Word16 colsY, /* i : number of columns of the right hand matrix */ + const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication */ + Word32 *Z_fx /* o : resulting matrix after the matrix multiplication */ +) +{ + Word16 i, j, k; + Word32 *Zp_fx = Z_fx; + + /* Processing */ + IF( transpX == 1 && transpY == 0 ) /* We use X transpose */ + { + IF( rowsX != rowsY ) + { + return EXIT_FAILURE; + } + FOR( j = 0; j < colsY; ++j ) + { + FOR( i = 0; i < colsX; ++i ) + { + ( *Zp_fx ) = 0; + FOR( k = 0; k < rowsX; ++k ) + { + ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ) ); + } + Zp_fx++; + } + } + } + ELSE IF( transpX == 0 && transpY == 1 ) /* We use Y transpose */ + { + IF( colsX != colsY ) + { + return EXIT_FAILURE; + } + FOR( j = 0; j < rowsY; ++j ) + { + FOR( i = 0; i < rowsX; ++i ) + { + ( *Zp_fx ) = 0; + FOR( k = 0; k < colsX; ++k ) + { + ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ) ); + } + Zp_fx++; + } + } + } + ELSE IF( transpX == 1 && transpY == 1 ) /* We use both transpose */ + { + IF( rowsX != colsY ) + { + return EXIT_FAILURE; + } + FOR( j = 0; j < rowsY; ++j ) + { + FOR( i = 0; i < colsX; ++i ) + { + ( *Zp_fx ) = 0; + FOR( k = 0; k < colsX; ++k ) + { + ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ) ); + } + + Zp_fx++; + } + } + } + ELSE /* Regular case */ + { + IF( colsX != rowsY ) + { + return EXIT_FAILURE; + } + + FOR( j = 0; j < colsY; ++j ) + { + FOR( i = 0; i < rowsX; ++i ) + { + ( *Zp_fx ) = 0; + for ( k = 0; k < colsX; ++k ) + { + ( *Zp_fx ) = L_add( *Zp_fx, Mpy_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ) ); + } + Zp_fx++; + } + } + } + + return EXIT_SUCCESS; +} +#endif /*---------------------------------------------------------------------* * matrix_diag_product @@ -1243,3 +1342,124 @@ float rand_triangular_signed( return 0.5f - 0.5f * sqrtf( 1.0f - rand_val ); } } + + +/*-------------------------------------------------------------------* + * ceil_log_2() + * + * calculates ceil(log2(val)) + *-------------------------------------------------------------------*/ + +Word16 ceil_log_2( + UWord64 val ) +{ + + IF( val <= 0 ) + { + assert( 0 ); + } + return val <= 1 ? 0 : val <= 2 ? 1 + : val <= 4 ? 2 + : val <= 8 ? 3 + : val <= 16 ? 4 + : val <= 32 ? 5 + : val <= 64 ? 6 + : val <= 128 ? 7 + : val <= 256 ? 8 + : val <= 512 ? 9 + : val <= 1024 ? 10 + : val <= 2048 ? 11 + : val <= 4096 ? 12 + : val <= 8192 ? 13 + : val <= 16384 ? 14 + : val <= 32768 ? 15 + : val <= 65536 ? 16 + : val <= 131072 ? 17 + : val <= 262144 ? 18 + : val <= 524288 ? 19 + : val <= 1048576 ? 20 + : val <= 2097152 ? 21 + : val <= 4194304 ? 22 + : val <= 8388608 ? 23 + : val <= 16777216 ? 24 + : val <= 33554432 ? 25 + : val <= 67108864 ? 26 + : val <= 134217728 ? 27 + : val <= 268435456 ? 28 + : val <= 536870912 ? 29 + : val <= 1073741824 ? 30 + : val <= 2147483648 ? 31 + : val <= 4294967296 ? 32 + : val <= 8589934592 ? 33 + : val <= 17179869184 ? 34 + : val <= 34359738368 ? 35 + : val <= 68719476736 ? 36 + : val <= 137438953472 ? 37 + : val <= 274877906944 ? 38 + : val <= 549755813888 ? 39 + : val <= 1099511627776 ? 40 + : val <= 2199023255552 ? 41 + : val <= 4398046511104 ? 42 + : val <= 8796093022208 ? 43 + : val <= 17592186044416 ? 44 + : val <= 35184372088832 ? 45 + : val <= 70368744177664 ? 46 + : val <= 140737488355328 ? 47 + : val <= 281474976710656 ? 48 + : val <= 562949953421312 ? 49 + : val <= 1125899906842624 ? 50 + : val <= 2251799813685248 ? 51 + : val <= 4503599627370496 ? 52 + : val <= 9007199254740992 ? 53 + : val <= 18014398509481984 ? 54 + : val <= 36028797018963968 ? 55 + : val <= 72057594037927936 ? 56 + : val <= 144115188075855872 ? 57 + : val <= 288230376151711744 ? 58 + : val <= 576460752303423488 ? 59 + : val <= 1152921504606846976 ? 60 + : val <= 2305843009213693952 ? 61 + : val <= 4611686018427387904 ? 62 + : val <= 9223372036854775808 ? 63 + : 64; +} + + +/*-------------------------------------------------------------------* + * var_32_fx() + * + * calculates variance of 32-bit array + * Currently using direct division. + * Needs update once required basops are implemented. + *-------------------------------------------------------------------*/ + +Word64 var_32_fx( + const Word32 *x, /* i : input vector */ + const int16_t len, /* i : length of inputvector */ + Word16 q /* q : q-factor for the array */ +) +{ + + Word64 mean, var; + + mean = 0; + var = 0; + + FOR( int i = 0; i < len; i++ ) + { + mean = mean + x[i]; + } + + mean = mean / len; + + FOR( int i = 0; i < len; i++ ) + { + var = var + Mpy_32_32( L_sub( x[i], mean ), L_sub( x[i], mean ) ); + } + + var = var << ( 31 - q ); + + var = var / len; + + return var; +} \ No newline at end of file diff --git a/lib_com/prot_fx1.h b/lib_com/prot_fx1.h index 536740741e213521ed6680360845ed89673c9e8c..b948a78b7d6c1e1422ffc7de33f8a5278f8ca058 100644 --- a/lib_com/prot_fx1.h +++ b/lib_com/prot_fx1.h @@ -436,4 +436,6 @@ void delay_signal( const Word16 delay /* i : delay in samples */ ); +Word16 ceil_log_2( UWord64 val ); + #endif \ No newline at end of file diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 8d571f5f412125c7c61d857eb5ed77a35990b511..83e90e01f5915d5f4c3afb22a4227f6c6f07e449 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1122,9 +1122,9 @@ static int16_t decode_lfe_to_total_energy_ratio( lfeBitsRead = 0; byteBuffer = bitstream[( *index )--]; lfeBitsRead += 1; - lfeToTotalEnergyRatioIndices[0] = byteBuffer; /* First LFE index */ + lfeToTotalEnergyRatioIndices[0] = byteBuffer; /* First LFE index */ - if ( ivas_total_brate == IVAS_13k2 ) /* 1-bit adaptive LFE gain quantizer at 13.2 kbps */ + if ( ivas_total_brate == IVAS_13k2 ) /* 1-bit adaptive LFE gain quantizer at 13.2 kbps */ { lfeToTotalEnergyRatioTemp = hMasaLfeSynth->lfeToTotalEnergyRatio[3]; /* Take memory from the last subframe */ if ( lfeToTotalEnergyRatioIndices[0] == 1 ) @@ -1230,7 +1230,7 @@ static int16_t decode_lfe_to_total_energy_ratio( ivas_error ivas_masa_dec_reconfigure( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ uint16_t *nSamplesRendered, /* o : number of samples flushed from the previous frame (JBM) */ - int16_t *data /* o : output synthesis signal */ + int16_t *data /* o : output synthesis signal */ ) { int16_t n, tmp, num_bits; @@ -1247,12 +1247,12 @@ ivas_error ivas_masa_dec_reconfigure( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; - if ( st_ivas->hSpatParamRendCom != NULL && st_ivas->hSpatParamRendCom->slot_size == st_ivas->hTcBuffer->n_samples_granularity ) - { - mvs2s( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); - st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpatParamRendCom->nb_subframes; - st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; - } + if ( st_ivas->hSpatParamRendCom != NULL && st_ivas->hSpatParamRendCom->slot_size == st_ivas->hTcBuffer->n_samples_granularity ) + { + mvs2s( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); + st_ivas->hTcBuffer->nb_subframes = st_ivas->hSpatParamRendCom->nb_subframes; + st_ivas->hTcBuffer->subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; + } ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); @@ -1347,7 +1347,7 @@ ivas_error ivas_masa_dec_reconfigure( if ( st_ivas->hDiracDecBin != NULL ) { - /* regularization factor is bitrate-dependent */ + /* regularization factor is bitrate-dependent */ st_ivas->hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); } @@ -1649,7 +1649,7 @@ void ivas_spar_param_to_masa_param_mapping( E = ( foaCovarianceMtx[0][0] + foaCovarianceMtx[1][1] + foaCovarianceMtx[2][2] + foaCovarianceMtx[3][3] ) / 2.0f; /* Overall energy */ azi = atan2f( Iy, Ix ); /* Azimuth */ ele = atan2f( Iz, sqrtf( Ix * Ix + Iy * Iy ) ); /* Elevation */ - ratio_float = I / fmaxf( 1e-12f, E ); /* Energy ratio */ + ratio_float = I / fmaxf( 1e-12f, E ); /* Energy ratio */ ratio_float = fmaxf( 0.0f, fminf( 1.0f, ratio_float ) ); hSpatParamRendCom->azimuth[dirac_write_idx][bin] = (int16_t) roundf( azi / PI_OVER_180 ); @@ -2302,7 +2302,27 @@ static int16_t ivas_decode_masaism_metadata( nblocks = hQMetaData->q_direction->cfg.nblocks; /* Read MASA-to-total energy ratios */ +#ifdef IVAS_FLOAT_FIXED1 + Word16 q = 18; + + ivas_omasa_decode_masa_to_total_fx( bit_stream, next_bit_pos, hMasaIsmData->masa_to_total_energy_ratio_fx, nbands, nblocks, &q ); + + FOR( int i = 0; i < nblocks; i++ ) + { + FOR( int j = 0; j < nbands; j++ ) + { + hMasaIsmData->masa_to_total_energy_ratio[i][j] = (float) hMasaIsmData->masa_to_total_energy_ratio_fx[i][j] / (float) ( 1 << q ); + } + } + +#else ivas_omasa_decode_masa_to_total( bit_stream, next_bit_pos, hMasaIsmData->masa_to_total_energy_ratio, nbands, nblocks ); +#endif + /*FOR(int i = 0; i < nblocks; i++) { + FOR(int j = 0; j masa_to_total_energy_ratio[i][j]); + } + }*/ if ( nchan_ism > 1 ) { /* read ISM ratios */ diff --git a/lib_dec/ivas_qmetadata_dec.c b/lib_dec/ivas_qmetadata_dec.c index 011a16d81cfc342238fdc4812d5caa8736a23e03..bf480ea80995b2705503976b8f4950fcdb88ce73 100644 --- a/lib_dec/ivas_qmetadata_dec.c +++ b/lib_dec/ivas_qmetadata_dec.c @@ -41,21 +41,38 @@ #include "wmc_auto.h" #include "prot.h" +#include "prot_fx1.h" + /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_diffuseness( uint16_t *bitstream, Word16 *index, IVAS_QDIRECTION *q_direction, UWord16 *diffuseness_index_max_ec_frame ); +#else static int16_t ivas_qmetadata_entropy_decode_diffuseness( uint16_t *bitstream, int16_t *index, IVAS_QDIRECTION *q_direction, uint16_t *diffuseness_index_max_ec_frame ); +#endif +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_df_ratio( UWord16 *bitstream, Word16 *index, IVAS_QDIRECTION *q_direction, Word16 *dfRatio_bits ); +#else static int16_t ivas_qmetadata_entropy_decode_df_ratio( uint16_t *bitstream, int16_t *index, IVAS_QDIRECTION *q_direction, int16_t *dfRatio_bits ); +#endif static int16_t ivas_qmetadata_entropy_decode_dir( IVAS_QDIRECTION *q_direction, uint16_t *bitstream, int16_t *index, const uint16_t diffuseness_index_max_ec_frame, const int16_t nbands, const int16_t start_band, const int16_t hrmasa_flag ); static int16_t ivas_qmetadata_raw_decode_dir( IVAS_QDIRECTION *q_direction, uint16_t *bitstream, int16_t *index, const int16_t nbands, const int16_t start_band, const int16_t hrmasa_flag ); +#ifdef IVAS_FLOAT_FIXED +static UWord16 ivas_qmetadata_DecodeQuasiUniform( const UWord16 *bitstream, Word16 *index, const UWord16 alphabet_size ); +#else static uint16_t ivas_qmetadata_DecodeQuasiUniform( const uint16_t *bitstream, int16_t *index, const uint16_t alphabet_size ); +#endif +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_ReorderElevationDecoded( const Word16 elev_dist, const Word16 elev_avg, const Word16 elev_alph ); +#else static int16_t ivas_qmetadata_ReorderElevationDecoded( const int16_t elev_dist, const int16_t elev_avg, const int16_t elev_alph ); +#endif static int16_t read_directions( IVAS_QDIRECTION *q_direction, const uint8_t coding_subbands, const uint8_t masa_subframes, uint16_t *bitstream, int16_t *pbit_pos, int16_t *ind_order ); @@ -65,6 +82,44 @@ static int16_t decode_fixed_rate( IVAS_QDIRECTION *q_direction, const uint16_t * static int16_t decode_azimuth( IVAS_QDIRECTION *q_direction, uint16_t *bitstream, int16_t *pbit_pos, const int16_t idx_subband, const int16_t masa_subframes ); +#ifdef IVAS_FLOAT_FIXED + +static Word16 ivas_qmetadata_raw_decode_dir_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, Word16 *index, const Word16 nbands, const Word16 start_band, const Word16 hrmasa_flag ); + +static Word16 read_directions_fx( IVAS_QDIRECTION *q_direction, const UWord8 coding_subbands, const UWord8 masa_subframes, UWord16 *bitstream, Word16 *pbit_pos, Word16 *ind_order ); + +static Word16 decode_fixed_rate_fx( IVAS_QDIRECTION *q_direction, const UWord16 *bitstream, Word16 *pbit_pos, const Word16 b, const Word16 nblocks ); + +static Word16 decode_azimuth_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, Word16 *pbit_pos, const Word16 idx_subband, const Word16 masa_subframes ); + +static void set_zero_direction_fx( IVAS_QDIRECTION *q_direction, const Word16 idx_band, const Word16 len ); + +static Word16 decode_azimuth2D_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, const Word16 coding_subbands, Word16 *pbit_pos, const Word16 no_frames ); + +static Word16 read_truncGR_azimuth_fx( UWord16 *bitstream, IVAS_QDIRECTION *q_direction, const Word16 j, const Word16 no_subframes, Word16 *pbit_pos ); + +static void decode_combined_index_fx( UWord64 comb_index, const Word16 *no_cv_vec, UWord16 *index, const Word16 len ); + +static Word16 decode_elevation_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, Word16 *pbit_pos, const Word16 j, const Word16 masa_subframes ); + +static Word16 decode_fixed_rate_composed_index_coherence_fx( UWord16 *bitstream, Word16 *p_bit_pos, const Word16 no_bands, Word16 *no_cv_vec, UWord16 *decoded_index, const Word16 no_symb ); + +static void decode_spread_coherence_fx( IVAS_QMETADATA_HANDLE hQMetaData, int16_t idx_d, const int16_t no_frames, const int16_t hrmasa_flag ); + +static Word16 ivas_diffuseness_huff_ec_decode_fx( const UWord16 *bitstream, Word16 *index, Word16 av ); + +static void read_stream_dct_coeffs_omasa_fx( Word16 *q_idx, Word32 *q_dct_data_fx, const Word16 len_stream, UWord16 *bit_stream, Word16 *index, const Word16 first_line ); + +static Word16 read_coherence_data_hr_512_fx( UWord16 *bitstream, Word16 *p_bit_pos, IVAS_QMETADATA *hQMetaData, const Word16 idx_dir, const Word16 nbits_coh ); + +static Word16 read_surround_coherence_hr_fx( UWord16 *bitstream, Word16 *p_bit_pos, IVAS_QMETADATA *hQMetaData, Word16 *q ); + +static Word16 read_common_direction_fx( UWord16 *bitstream, IVAS_QDIRECTION *q_direction, const Word16 j, const Word16 no_subframes, const Word16 bits_total, Word16 *pbit_pos ); + +static Word16 read_coherence_data_fx( UWord16 *bitstream, Word16 *p_bit_pos, IVAS_QMETADATA *hQMetaData, const Word16 idx_dir, const Word16 hrmasa_flag ); + +#endif + static int16_t decode_elevation( IVAS_QDIRECTION *q_direction, uint16_t *bitstream, int16_t *pbit_pos, const int16_t j, const int16_t masa_subframes ); static int16_t decode_azimuth2D( IVAS_QDIRECTION *q_direction, uint16_t *bitstream, const int16_t coding_subbands, int16_t *pbit_pos, const int16_t no_frames ); @@ -73,7 +128,11 @@ static void set_zero_direction( IVAS_QDIRECTION *q_direction, const int16_t idx_ static int16_t read_truncGR_azimuth( uint16_t *bitstream, IVAS_QDIRECTION *q_direction, const int16_t j, const int16_t no_subframes, int16_t *pbit_pos ); +#ifdef IVAS_FLOAT_FIXED +static ivas_error read_huf( Word16 *num_bits_read, const UWord16 *bitstream, UWord16 *out, const Word16 start_pos, const Word16 len, const Word16 *huff_code, const Word16 max_len ); +#else static ivas_error read_huf( int16_t *num_bits_read, const uint16_t *bitstream, uint16_t *out, const int16_t start_pos, const int16_t len, const int16_t *huff_code, const int16_t max_len ); +#endif static int16_t read_coherence_data( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData, const int16_t idx_dir, const int16_t hrmasa_flag ); @@ -89,7 +148,11 @@ static int16_t read_GR_min_removed_data( uint16_t *bitstream, int16_t *p_bit_pos static int16_t decode_fixed_rate_composed_index_coherence( uint16_t *bitstream, int16_t *p_bit_pos, const int16_t no_bands, int16_t *no_cv_vec, uint16_t *decoded_index, const int16_t no_symb ); +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_diffuseness_hr_512( UWord16 *bitstream, Word16 *index, IVAS_QDIRECTION *q_direction ); +#else static int16_t ivas_qmetadata_entropy_decode_diffuseness_hr_512( uint16_t *bitstream, int16_t *index, IVAS_QDIRECTION *q_direction ); +#endif static int16_t ivas_qmetadata_raw_decode_dir_512( IVAS_QDIRECTION *q_direction, uint16_t *bitstream, int16_t *index, const int16_t nbands, const int16_t start_band, const SPHERICAL_GRID_DATA *sph_grid16 ); @@ -414,7 +477,11 @@ int16_t ivas_qmetadata_dec_decode( if ( all_coherence_zero == 0 ) { +#ifdef IVAS_FLOAT_FIXED + bits_coherence = read_coherence_data_fx( bitstream, index, hQMetaData, d, 0 ); +#else bits_coherence = read_coherence_data( bitstream, index, hQMetaData, d, 0 ); +#endif } else { @@ -466,7 +533,64 @@ int16_t ivas_qmetadata_dec_decode( } else { + FOR( int i = 0; i < nbands; i++ ) + { + FOR( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + q_direction->band_data[i].elevation[j] = 0; + q_direction->band_data[i].azimuth[j] = 0; + } + } + +#ifdef IVAS_FLOAT_FIXED + FOR( Word16 j = 0; j < nbands; j++ ) + { + FOR( Word16 k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + { + q_direction->band_data[j].elevation_fx[k] = q_direction->band_data[j].elevation[k] * ( 1 << 22 ); + q_direction->band_data[j].azimuth_fx[k] = q_direction->band_data[j].azimuth[k] * ( 1 << 22 ); + } + } + bits_dir += ivas_qmetadata_raw_decode_dir_fx( q_direction, bitstream, index, nbands, start_band, 0 ); + FOR( Word16 j = 0; j < nbands; j++ ) + { + FOR( Word16 k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + { + q_direction->band_data[j].elevation[k] = (float) q_direction->band_data[j].elevation_fx[k] / (float) ( 1 << 22 ); + q_direction->band_data[j].azimuth[k] = (float) q_direction->band_data[j].azimuth_fx[k] / (float) ( 1 << 22 ); + } + } +#else bits_dir += ivas_qmetadata_raw_decode_dir( q_direction, bitstream, index, nbands, start_band, 0 ); +#endif + // FILE *fp; + + ///*Opening the file in appending mode...*/ + // fp = fopen("ivas_qmetadata_raw_decode_dir_dumps_idx_fx.txt", "a+"); + ///*File open operation failed.*/ + // if (fp == NULL) return -1; + // fprintf(fp, "%d\n", *index); + // fclose(fp); + + // fp = fopen("ivas_qmetadata_raw_decode_dir_dumps_elevation_fx.txt", "a+"); + ///*File open operation failed.*/ + // if (fp == NULL) return -1; + // FOR(int i = 0; i < nbands; i++) { + // FOR(int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++) { + // fprintf(fp, "%f\n", q_direction->band_data[i].elevation[j]); + // } + // } + // fclose(fp); + + // fp = fopen("ivas_qmetadata_raw_decode_dir_dumps_azimuth_fx.txt", "a+"); + ///*File open operation failed.*/ + // if (fp == NULL) return -1; + // FOR(int i = 0; i < nbands; i++) { + // FOR(int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++) { + // fprintf(fp, "%f\n", q_direction->band_data[i].azimuth[j]); + // } + // } + // fclose(fp); } } /* Decode quantized directions band-wise */ @@ -526,7 +650,27 @@ int16_t ivas_qmetadata_dec_decode( { if ( raw_flag[b] ) { +#ifdef IVAS_FLOAT_FIXED1 + FOR( Word16 j = 0; j < nbands; j++ ) + { + FOR( Word16 k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + { + q_direction->band_data[j].elevation_fx[k] = q_direction->band_data[j].elevation[k] * ( 1 << 22 ); + q_direction->band_data[j].azimuth_fx[k] = q_direction->band_data[j].azimuth[k] * ( 1 << 22 ); + } + } + bits_dir += ivas_qmetadata_raw_decode_dir_fx( q_direction, bitstream, index, b + 1, b, 0 ); + FOR( Word16 j = 0; j < nbands; j++ ) + { + FOR( Word16 k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + { + q_direction->band_data[j].elevation[k] = (float) q_direction->band_data[j].elevation_fx[k] / (float) ( 1 << 22 ); + q_direction->band_data[j].azimuth[k] = (float) q_direction->band_data[j].azimuth_fx[k] / (float) ( 1 << 22 ); + } + } +#else bits_dir += ivas_qmetadata_raw_decode_dir( q_direction, bitstream, index, b + 1, b, 0 ); +#endif } } } @@ -553,14 +697,57 @@ int16_t ivas_qmetadata_dec_decode( only_reduce_bits_direction( &dummy, q_direction, reduce_bits, nbands, nblocks, ind_order ); /* Read directions */ +#ifdef IVAS_FLOAT_FIXED + FOR( Word16 j = 0; j < nbands; j++ ) + { + FOR( Word16 k = 0; k < nblocks; k++ ) + { + q_direction->band_data[j].elevation_fx[k] = q_direction->band_data[j].elevation[k] * ( 1 << 22 ); + q_direction->band_data[j].azimuth_fx[k] = q_direction->band_data[j].azimuth[k] * ( 1 << 22 ); + } + } + bits_dir = read_directions_fx( q_direction, (uint8_t) nbands, (uint8_t) nblocks, bitstream, index, ind_order ); + FOR( Word16 j = 0; j < nbands; j++ ) + { + FOR( Word16 k = 0; k < nblocks; k++ ) + { + q_direction->band_data[j].elevation[k] = (float) q_direction->band_data[j].elevation_fx[k] / (float) ( 1 << 22 ); + q_direction->band_data[j].azimuth[k] = (float) q_direction->band_data[j].azimuth_fx[k] / (float) ( 1 << 22 ); + } + } +#else bits_dir = read_directions( q_direction, (uint8_t) nbands, (uint8_t) nblocks, bitstream, index, ind_order ); +#endif + /*FOR (Word16 j = 0; j < nbands; j++) { + FOR (Word16 k = 0; k < nblocks; k++) { + printf("%f\n", q_direction->band_data[j].elevation[k]); + } + }*/ } if ( bits_coherence > 0 ) { if ( nblocks > 1 ) { +#ifdef IVAS_FLOAT_FIXED + for ( int i = 0; i < q_direction->cfg.nbands; i++ ) + { + for ( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + q_direction->band_data[i].azimuth_fx[j] = q_direction->band_data[i].azimuth[j] * ( 1 << 22 ); + } + } + decode_spread_coherence_fx( hQMetaData, d, nblocks, 0 ); + for ( int i = 0; i < q_direction->cfg.nbands; i++ ) + { + for ( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + q_direction->band_data[i].azimuth[j] = (float) q_direction->band_data[i].azimuth_fx[j] / (float) ( 1 << 22 ); + } + } +#else decode_spread_coherence( hQMetaData, d, nblocks, 0 ); +#endif } } else @@ -580,7 +767,6 @@ int16_t ivas_qmetadata_dec_decode( bits_dir_target += bits_dir_raw; bits_dir_used += bits_dir; - } /* move 2 dir data to its correct subband */ @@ -785,11 +971,11 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( hQMetaData->q_direction[1].cfg.nbands = codedBands; } } - ivas_qmetadata_entropy_decode_diffuseness_hr_512( bitstream, index, &( hQMetaData->q_direction[0] ) ); + ivas_qmetadata_entropy_decode_diffuseness_hr_512( bitstream, index, &( hQMetaData->q_direction[0] ) ); if ( hQMetaData->no_directions == 2 ) { - ivas_qmetadata_entropy_decode_diffuseness_hr_512( bitstream, index, &( hQMetaData->q_direction[1] ) ); + ivas_qmetadata_entropy_decode_diffuseness_hr_512( bitstream, index, &( hQMetaData->q_direction[1] ) ); } @@ -879,7 +1065,58 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( if ( all_coherence_zero == 0 ) { - read_surround_coherence_hr( bitstream, index, hQMetaData ); +#ifdef IVAS_FLOAT_FIXED1 + Word16 q = 31; + for ( int sf = 0; sf < hQMetaData->q_direction[0].cfg.nblocks; sf++ ) + { + for ( int j = 0; j < hQMetaData->q_direction[0].cfg.nbands; j++ ) + { + if ( abs( hQMetaData->q_direction[0].band_data[j].energy_ratio[sf] ) >= 1 ) + { + q = min( q, norm_l( hQMetaData->q_direction[0].band_data[j].energy_ratio[sf] ) ); + } + } + } + for ( int sf = 0; sf < hQMetaData->q_direction[1].cfg.nblocks; sf++ ) + { + for ( int j = 0; j < hQMetaData->q_direction[0].cfg.nbands; j++ ) + { + if ( abs( hQMetaData->q_direction[1].band_data[j].energy_ratio[sf] ) >= 1 ) + { + q = min( q, norm_l( hQMetaData->q_direction[1].band_data[j].energy_ratio[sf] ) ); + } + } + } + q -= 1; // guarded bits + for ( int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + for ( int j = 0; j < hQMetaData->q_direction[0].cfg.nbands; j++ ) + { + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[sf] = hQMetaData->q_direction[0].band_data[j].energy_ratio[sf] * ( 1 << q ); + } + } + for ( int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + for ( int j = 0; j < hQMetaData->q_direction[1].cfg.nbands; j++ ) + { + hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[sf] = hQMetaData->q_direction[1].band_data[j].energy_ratio[sf] * ( 1 << q ); + } + } + read_surround_coherence_hr_fx( bitstream, index, hQMetaData, &q ); + printf( "%d\n", *index ); + /*for (int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++) { + for (int j = 0; j < hQMetaData->q_direction[0].cfg.nbands; j++) { + hQMetaData->q_direction[0].band_data[j].energy_ratio[sf] = (float)hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[sf] / (float)(1 << q); + } + } + for (int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++) { + for (int j = 0; j < hQMetaData->q_direction[1].cfg.nbands; j++) { + hQMetaData->q_direction[1].band_data[j].energy_ratio[sf] = (float)hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[sf] / (float)(1 << q); + } + }*/ +#else + read_surround_coherence_hr( bitstream, index, hQMetaData ); +#endif } else { @@ -902,7 +1139,11 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( /* Read coherence, if any */ if ( all_coherence_zero == 0 ) { +#ifdef IVAS_FLOAT_FIXED + read_coherence_data_hr_512_fx( bitstream, index, hQMetaData, d, bits_sp_coh ); +#else read_coherence_data_hr_512( bitstream, index, hQMetaData, d, bits_sp_coh ); +#endif } else { @@ -923,7 +1164,6 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( /* Decode quantized directions frame-wise */ ivas_qmetadata_raw_decode_dir_512( q_direction, bitstream, index, nbands, start_band, sph_grid16 ); - } if ( hQMetaData->no_directions == 2 ) @@ -1234,6 +1474,232 @@ int16_t ivas_qmetadata_dec_sid_decode( return ( start_index - *index ); } +// #ifdef IVAS_FLOAT_FIXED +// Word16 ivas_qmetadata_dec_sid_decode( +// IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ +// UWord16 *bitstream, /* i : bitstream */ +// Word16 *index, /* i/o: bitstream position */ +// const Word16 nchan_transport, /* i : number of transport channels */ +// Word16 *element_mode, /* o : element mode */ +// const Word16 ivas_format /* i : IVAS format */ +//) +//{ +// Word16 b, m, i; +// UWord16 value; +// UWord16 diffuseness_index[DIRAC_MAX_NBANDS]; +// Word16 nbands, nblocks, start_band; +// IVAS_QDIRECTION *q_direction; +// Word16 start_index; +// Word32 avg_elevation_fx, avg_azimuth_fx; +// Word32 avg_direction_vector_fx[3]; +// Word32 direction_vector_fx[3]; +// Word16 metadata_sid_bits; /* bits allocated to SID for metadata */ +// Word16 bits_delta, bits_dir; +// +// IF ( ivas_format == SBA_FORMAT ) +// { +// metadata_sid_bits = (Word16) ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - ( SPAR_DTX_BANDS * SPAR_SID_BITS_TAR_PER_BAND ) - 2 - SID_FORMAT_NBITS; /* -1 for inactive mode header bit*/ +// } +// ELSE +// { +// metadata_sid_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; +// } +// +// start_index = *index; +// +// /* read MASA SID descriptor */ +// IF ( ivas_format == MASA_FORMAT && nchan_transport == 2 ) +// { +// b = bitstream[( *index )--]; +// IF ( b ) +// { +// *element_mode = IVAS_CPE_MDCT; +// } +// ELSE +// { +// *element_mode = IVAS_CPE_DFT; +// } +// } +// +// /* Fix configuration for SID */ +// q_direction = &hQMetaData->q_direction[0]; /* only 1 direction */ +// IF ( ivas_format == SBA_FORMAT ) +// { +// nbands = DIRAC_DTX_BANDS; /* only 2 bands transmitted */ +// } +// ELSE +// { +// nbands = 5; /* only 5 bands transmitted */ +// } +// +// nblocks = q_direction->cfg.nblocks; /* only 1 block transmitted but up to 4 blocks re-generated */ +// start_band = 0; /* start from band 0 */ +// +// /* Read 2D signaling*/ +// IF ( ivas_format != SBA_FORMAT ) +// { +// q_direction->not_in_2D = bitstream[( *index )--]; +// } +// ELSE +// { +// q_direction->not_in_2D = 1; +// } +// +// bits_dir = 0; +// IF ( ivas_format != SBA_FORMAT ) +// { +// /* Decode diffuseness*/ +// FOR ( b = start_band; b < nbands; b++ ) +// { +// diffuseness_index[b] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS - 4 ) + 4; +// q_direction->band_data[b].energy_ratio_index[0] = diffuseness_index[b]; +// q_direction->band_data[b].bits_sph_idx[0] = bits_direction_masa[diffuseness_index[b]]; +// bits_dir += q_direction->band_data[b].bits_sph_idx[0]; +// q_direction->band_data[b].azimuth_m_alphabet[0] = no_phi_masa[q_direction->band_data[b].bits_sph_idx[0] - 1][0]; +// } +// +// bits_delta = metadata_sid_bits - ( start_index - *index ) - bits_dir; /* bit_diff is already read */ +// +// IF ( bits_delta > 0 ) +// { +// WHILE ( bits_delta > 0 ) +// { +// FOR ( b = start_band; b < nbands && ( bits_delta > 0 ); b++ ) +// { +// IF ( q_direction->band_data[b].bits_sph_idx[0] < 11 ) +// { +// bits_delta -= 1; +// q_direction->band_data[b].bits_sph_idx[0]++; +// } +// } +// } +// +// IF ( q_direction->not_in_2D == 0 ) +// { +// FOR ( b = start_band; b < nbands; b++ ) +// { +// q_direction->band_data[b].azimuth_m_alphabet[0] = 1 << ( min( 8, q_direction->band_data[b].bits_sph_idx[0] ) ); +// } +// } +// } +// ELSE +// { +// WHILE ( bits_delta < 0 ) +// { +// FOR ( b = nbands - 1; b >= start_band && ( bits_delta < 0 ); b-- ) +// { +// IF ( q_direction->band_data[b].bits_sph_idx[0] >= 4 ) +// { +// bits_delta += 1; +// q_direction->band_data[b].bits_sph_idx[0]--; +// } +// } +// +// IF ( q_direction->not_in_2D == 0 ) +// { +// FOR ( b = start_band; b < nbands; b++ ) +// { +// q_direction->band_data[b].azimuth_m_alphabet[0] = 1 << ( min( 8, q_direction->band_data[b].bits_sph_idx[0] ) ); +// } +// } +// } +// } +// } +// ELSE +// { +// /* Decode diffuseness*/ +// FOR ( b = start_band; b < nbands; b++ ) +// { +// diffuseness_index[b] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS - 4 ) + 4; +// q_direction->band_data[b].energy_ratio_index[0] = diffuseness_index[b]; +// q_direction->band_data[b].bits_sph_idx[0] = bits_direction_masa[diffuseness_index[b]]; +// q_direction->band_data[b].azimuth_m_alphabet[0] = no_phi_masa[q_direction->band_data[b].bits_sph_idx[0] - 1][0]; +// } +// } +// +// FOR ( b = start_band; b < nbands; b++ ) +// { +// q_direction->band_data[b].energy_ratio_fx[0] = (1<<30) - diffuseness_reconstructions_fx[diffuseness_index[b]]; +// FOR ( i = 0; i < nblocks; i++ ) +// { +// q_direction->band_data[b].energy_ratio_fx[i] = q_direction->band_data[b].energy_ratio_fx[0]; +// } +// } +// +// /* Decoder DOAs*/ +// IF ( q_direction->not_in_2D > 0 ) +// { +// FOR ( b = start_band; b < nbands; b++ ) +// { +// value = 0; +// FOR ( i = 0; i < q_direction->band_data[b].bits_sph_idx[0]; i++ ) +// { +// value = ( value << 1 ) + bitstream[( *index )--]; +// } +// FOR ( i = 0; i < nblocks; i++ ) +// { +// q_direction->band_data[b].spherical_index[i] = value; +// } +// +// deindex_spherical_component_fx( q_direction->band_data[b].spherical_index[0], &avg_azimuth_fx, &avg_elevation_fx, &q_direction->band_data[b].azimuth_index[0], &q_direction->band_data[b].elevation_index[0], q_direction->band_data[b].bits_sph_idx[0], q_direction->cfg.mc_ls_setup ); +// +// //Modifications required ////////////////////////////////////////////////////////////////////////////////// +// ivas_qmetadata_azimuth_elevation_to_direction_vector( avg_azimuth, avg_elevation, avg_direction_vector ); +// ivas_qmetadata_azimuth_elevation_to_direction_vector( q_direction->band_data[b].azimuth[nblocks - 1], q_direction->band_data[b].elevation[nblocks - 1], direction_vector ); +// +// FOR ( m = 0; m < nblocks - 1; m++ ) +// { +// v_add( direction_vector, avg_direction_vector, direction_vector, 3 ); +// ivas_qmetadata_direction_vector_to_azimuth_elevation( direction_vector, &q_direction->band_data[b].azimuth[m], &q_direction->band_data[b].elevation[m] ); +// } +// +// ivas_qmetadata_direction_vector_to_azimuth_elevation( avg_direction_vector, &q_direction->band_data[b].azimuth[nblocks - 1], &q_direction->band_data[b].elevation[nblocks - 1] ); +// } +// } +// ELSE +// { +// FOR ( b = start_band; b < nbands; b++ ) +// { +// IF ( ivas_format == SBA_FORMAT ) +// { +// q_direction->band_data[b].azimuth_m_alphabet[0] = 1 << ( min( 5, q_direction->band_data[b].bits_sph_idx[0] ) ); +// } +// +// q_direction->band_data[b].azimuth_index[0] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, q_direction->band_data[b].azimuth_m_alphabet[0] ); +// q_direction->band_data[b].azimuth_index[0] = ivas_qmetadata_dereorder_generic( q_direction->band_data[b].azimuth_index[0] ) + ( q_direction->band_data[b].azimuth_m_alphabet[0] >> 1 ); +// avg_azimuth = 360.0f / (float) ( q_direction->band_data[b].azimuth_m_alphabet[0] ) * q_direction->band_data[b].azimuth_index[0] - 180; +// +// avg_elevation_fx = 0; +// +// ivas_qmetadata_azimuth_elevation_to_direction_vector( avg_azimuth, avg_elevation, avg_direction_vector ); +// ivas_qmetadata_azimuth_elevation_to_direction_vector( q_direction->band_data[b].azimuth[nblocks - 1], q_direction->band_data[b].elevation[nblocks - 1], direction_vector ); +// +// FOR ( m = 0; m < nblocks - 1; m++ ) +// { +// v_add( direction_vector, avg_direction_vector, direction_vector, 3 ); +// ivas_qmetadata_direction_vector_to_azimuth_elevation( direction_vector, &q_direction->band_data[b].azimuth[m], &q_direction->band_data[b].elevation[m] ); +// } +// +// ivas_qmetadata_direction_vector_to_azimuth_elevation( avg_direction_vector, &q_direction->band_data[b].azimuth[nblocks - 1], &q_direction->band_data[b].elevation[nblocks - 1] ); +// +// FOR ( i = 0; i < nblocks; i++ ) +// { +// q_direction->band_data[b].spherical_index[i] = q_direction->band_data[b].azimuth_index[0]; +// } +// } +// } +// +// +// /*Read filling bits*/ +// WHILE ( start_index - *index < metadata_sid_bits ) +// { +// b = bitstream[( *index )--]; +// } +// +// return ( start_index - *index ); +// } +// #endif + /*-----------------------------------------------------------------------* * Local function definitions for diffuseness/energy ratios @@ -1277,13 +1743,147 @@ static int16_t ivas_diffuseness_huff_ec_decode( } } +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_diffuseness_huff_ec_decode_fx( + const UWord16 *bitstream, + Word16 *index, + Word16 av ) +{ + Word16 val; + + val = 0; + WHILE( val <= DIFF_EC_HUFF_GR0_LIMIT ) + { + IF( bitstream[( *index )--] == 1 ) + { + val++; + } + ELSE + { + BREAK; + } + } + + IF( val == DIFF_EC_HUFF_GR0_LIMIT + 1 ) + { + val += 2 * bitstream[( *index )]; + ( *index )--; + val += bitstream[( *index )]; + ( *index )--; + } + + IF( val % 2 == 0 ) + { + return -( val / 2 ) + av; + } + ELSE + { + return ( val + 1 ) / 2 + av; + } +} +#endif /*-------------------------------------------------------------------* * ivas_qmetadata_entropy_decode_diffuseness() * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_diffuseness( + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, + IVAS_QDIRECTION *q_direction, + UWord16 *diffuseness_index_max_ec_frame ) +{ + Word16 b; + UWord16 dif_min; + Word16 index_start; + Word16 nbands; + Word16 start_band; + + index_start = *index; + nbands = q_direction->cfg.nbands; + start_band = q_direction->cfg.start_band; + + /* diffuseness decoding */ + /* Handle one band as special case*/ + IF( nbands == 1 ) + { + q_direction->band_data[0].energy_ratio_index[0] = 0; + FOR( b = 0; b < MASA_BITS_ER; b++ ) + { + q_direction->band_data[0].energy_ratio_index[0] = ( q_direction->band_data[0].energy_ratio_index[0] << 1 ) + bitstream[( *index )--]; + } + *diffuseness_index_max_ec_frame = 5; + + return MASA_BITS_ER; + } + IF( bitstream[( *index )--] == 0 ) /* dif_use_raw_coding */ + { + /* Decode with similarity strategy with low band count. On higher band counts, decode with Huffman-coding strategy. */ + IF( nbands < DIFF_EC_HUFF_BAND_LIMIT ) + { + IF( bitstream[( *index )--] != 0 ) /* dif_have_unique_value */ + { + dif_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS ); /* dif_unique_value */ + + FOR( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = dif_min; + } + } + ELSE /* all diffuseness values are dif_min_value or dif_min_value + 1 */ + { + dif_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS - 1 ); /* dif_min_value */ + + FOR( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = dif_min + bitstream[( *index )--]; /* dif_bit_offset_values */ + } + } + } + ELSE + { + int16_t av; + + /* read average on 3 bits*/ + av = 0; + FOR( b = 0; b < MASA_BITS_ER; b++ ) + { + av += bitstream[( *index )--] * ( 1 << ( MASA_BITS_ER - 1 - b ) ); + } + + dif_min = DIRAC_DIFFUSE_LEVELS; + /* read average removed data (average is added inside)*/ + FOR( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = ivas_diffuseness_huff_ec_decode_fx( bitstream, index, av ); + dif_min = min( dif_min, q_direction->band_data[b].energy_ratio_index[0] ); + } + } + } + ELSE /* different values for diffuseness */ + { + dif_min = DIRAC_DIFFUSE_LEVELS; + + FOR( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS ); + dif_min = min( dif_min, q_direction->band_data[b].energy_ratio_index[0] ); + } + } + + *diffuseness_index_max_ec_frame = 5; + /* adaptively select the diffuseness_index_max_ec threshold */ + IF( dif_min > 5 ) + { + *diffuseness_index_max_ec_frame = DIRAC_DIFFUSE_LEVELS - 1; + } + + return ( index_start - *index ); +} +#else static int16_t ivas_qmetadata_entropy_decode_diffuseness( uint16_t *bitstream, /* i : bitstream */ int16_t *index, @@ -1319,7 +1919,7 @@ static int16_t ivas_qmetadata_entropy_decode_diffuseness( /* Decode with similarity strategy with low band count. On higher band counts, decode with Huffman-coding strategy. */ if ( nbands < DIFF_EC_HUFF_BAND_LIMIT ) { - if ( bitstream[( *index )--] != 0 ) /* dif_have_unique_value */ + if ( bitstream[( *index )--] != 0 ) /* dif_have_unique_value */ { dif_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS ); /* dif_unique_value */ @@ -1328,7 +1928,7 @@ static int16_t ivas_qmetadata_entropy_decode_diffuseness( q_direction->band_data[b].energy_ratio_index[0] = dif_min; } } - else /* all diffuseness values are dif_min_value or dif_min_value + 1 */ + else /* all diffuseness values are dif_min_value or dif_min_value + 1 */ { dif_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, DIRAC_DIFFUSE_LEVELS - 1 ); /* dif_min_value */ @@ -1378,7 +1978,7 @@ static int16_t ivas_qmetadata_entropy_decode_diffuseness( return ( index_start - *index ); } - +#endif /*-------------------------------------------------------------------* * ivas_qmetadata_entropy_decode_diffuseness_hr_512() @@ -1386,6 +1986,47 @@ static int16_t ivas_qmetadata_entropy_decode_diffuseness( * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_diffuseness_hr_512( + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, + IVAS_QDIRECTION *q_direction ) +{ + Word16 b, k; + + Word16 index_start; + Word16 nbands, nblocks; + Word16 start_band; + + index_start = *index; + nbands = q_direction->cfg.nbands; + nblocks = q_direction->cfg.nblocks; + start_band = q_direction->cfg.start_band; + + /* diffuseness decoding */ + /* Handle one band as special case*/ + IF( nbands == 1 ) + { + q_direction->band_data[0].energy_ratio_index[0] = 0; + FOR( b = 0; b < MASA_BITS_ER_HR; b++ ) + { + q_direction->band_data[0].energy_ratio_index[0] = ( q_direction->band_data[0].energy_ratio_index[0] << 1 ) + bitstream[( *index )--]; + } + + return MASA_BITS_ER_HR; + } + + FOR( b = start_band; b < nbands; b++ ) + { + FOR( k = 0; k < nblocks; k++ ) + { + q_direction->band_data[b].energy_ratio_index[k] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, HR_MASA_ER_LEVELS ); + } + } + + return ( index_start - *index ); +} +#else static int16_t ivas_qmetadata_entropy_decode_diffuseness_hr_512( uint16_t *bitstream, /* i : bitstream */ int16_t *index, @@ -1425,6 +2066,7 @@ static int16_t ivas_qmetadata_entropy_decode_diffuseness_hr_512( return ( index_start - *index ); } +#endif /*-------------------------------------------------------------------* @@ -1432,33 +2074,33 @@ static int16_t ivas_qmetadata_entropy_decode_diffuseness_hr_512( * * *-------------------------------------------------------------------*/ - -static int16_t ivas_qmetadata_entropy_decode_df_ratio( - uint16_t *bitstream, - int16_t *index, +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_df_ratio( + UWord16 *bitstream, + Word16 *index, IVAS_QDIRECTION *q_direction, - int16_t *dfRatio_bits ) + Word16 *dfRatio_bits ) { - int16_t b; - int16_t bits_raw; - int16_t max_dfRatio_bits; - uint16_t ratio_min; - int16_t index_start; - int16_t nbands; - int16_t start_band; - int16_t ec_mode; - int16_t dec_mode; - int16_t max_alphabet_size; + Word16 b; + Word16 bits_raw; + Word16 max_dfRatio_bits; + UWord16 ratio_min; + Word16 index_start; + Word16 nbands; + Word16 start_band; + Word16 ec_mode; + Word16 dec_mode; + Word16 max_alphabet_size; index_start = *index; nbands = q_direction->cfg.nbands; start_band = q_direction->cfg.start_band; /* Handle one band as special case*/ - if ( nbands == 1 ) + IF( nbands == 1 ) { q_direction->band_data[0].energy_ratio_index[0] = 0; - for ( b = 0; b < dfRatio_bits[0]; b++ ) + FOR( b = 0; b < dfRatio_bits[0]; b++ ) { q_direction->band_data[0].energy_ratio_index[0] = ( q_direction->band_data[0].energy_ratio_index[0] << 1 ) + bitstream[( *index )--]; } @@ -1468,71 +2110,71 @@ static int16_t ivas_qmetadata_entropy_decode_df_ratio( /* Calculate raw coding bits and decide what modes are possible */ bits_raw = 0; max_dfRatio_bits = 0; - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { bits_raw += dfRatio_bits[b]; max_dfRatio_bits = max( max_dfRatio_bits, dfRatio_bits[b] ); } /* Decide what modes are possible */ - if ( bits_raw >= max_dfRatio_bits + 2 + nbands ) + IF( bits_raw >= max_dfRatio_bits + 2 + nbands ) { ec_mode = 2; } - else if ( bits_raw >= max_dfRatio_bits + 1 ) + ELSE IF( bits_raw >= max_dfRatio_bits + 1 ) { ec_mode = 1; } - else + ELSE { ec_mode = 0; } max_alphabet_size = 1 << max_dfRatio_bits; dec_mode = 2; /* Default to raw decoding */ - if ( ec_mode == 1 ) + IF( ec_mode == 1 ) { - if ( bitstream[( *index )--] == 0 ) + IF( bitstream[( *index )--] == 0 ) { dec_mode = 1; /* Switch to one value EC coding */ } } - else if ( ec_mode == 2 ) + ELSE IF( ec_mode == 2 ) { - if ( bitstream[( *index )--] == 0 ) + IF( bitstream[( *index )--] == 0 ) { - if ( bitstream[( *index )--] == 0 ) + IF( bitstream[( *index )--] == 0 ) { dec_mode = 1; /* Switch to one value EC coding */ } - else + ELSE { dec_mode = 0; /* Use one-bit diff bandwise mode */ } } } - if ( dec_mode == 2 ) /* Raw decoding */ + IF( dec_mode == 2 ) /* Raw decoding */ { - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { q_direction->band_data[b].energy_ratio_index[0] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, 1 << dfRatio_bits[b] ); } } - else if ( dec_mode == 1 ) /* One value decoding */ + ELSE IF( dec_mode == 1 ) /* One value decoding */ { ratio_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, max_alphabet_size ); /* dif_unique_value */ - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { q_direction->band_data[b].energy_ratio_index[0] = ratio_min; } } - else /* Bandwise 1-bit diff decoding */ + ELSE /* Bandwise 1-bit diff decoding */ { ratio_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, max_alphabet_size - 1 ); /* dif_min_value */ - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { q_direction->band_data[b].energy_ratio_index[0] = ratio_min + bitstream[( *index )--]; /* dif_bit_offset_values */ } @@ -1540,21 +2182,130 @@ static int16_t ivas_qmetadata_entropy_decode_df_ratio( return ( index_start - *index ); } - - -/*-----------------------------------------------------------------------* - * Local functions (EC1) - *-----------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------- - * ivas_qmetadata_entropy_decode_dir() - * - * Main function for entropy decoding of the directions - *------------------------------------------------------------------------*/ - -static int16_t ivas_qmetadata_entropy_decode_dir( - IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ - uint16_t *bitstream, /* i : bitstream */ +#else +static int16_t ivas_qmetadata_entropy_decode_df_ratio( + uint16_t *bitstream, + int16_t *index, + IVAS_QDIRECTION *q_direction, + int16_t *dfRatio_bits ) +{ + int16_t b; + int16_t bits_raw; + int16_t max_dfRatio_bits; + uint16_t ratio_min; + int16_t index_start; + int16_t nbands; + int16_t start_band; + int16_t ec_mode; + int16_t dec_mode; + int16_t max_alphabet_size; + + index_start = *index; + nbands = q_direction->cfg.nbands; + start_band = q_direction->cfg.start_band; + + /* Handle one band as special case*/ + if ( nbands == 1 ) + { + q_direction->band_data[0].energy_ratio_index[0] = 0; + for ( b = 0; b < dfRatio_bits[0]; b++ ) + { + q_direction->band_data[0].energy_ratio_index[0] = ( q_direction->band_data[0].energy_ratio_index[0] << 1 ) + bitstream[( *index )--]; + } + return dfRatio_bits[0]; + } + + /* Calculate raw coding bits and decide what modes are possible */ + bits_raw = 0; + max_dfRatio_bits = 0; + for ( b = start_band; b < nbands; b++ ) + { + bits_raw += dfRatio_bits[b]; + max_dfRatio_bits = max( max_dfRatio_bits, dfRatio_bits[b] ); + } + + /* Decide what modes are possible */ + if ( bits_raw >= max_dfRatio_bits + 2 + nbands ) + { + ec_mode = 2; + } + else if ( bits_raw >= max_dfRatio_bits + 1 ) + { + ec_mode = 1; + } + else + { + ec_mode = 0; + } + max_alphabet_size = 1 << max_dfRatio_bits; + + dec_mode = 2; /* Default to raw decoding */ + if ( ec_mode == 1 ) + { + if ( bitstream[( *index )--] == 0 ) + { + dec_mode = 1; /* Switch to one value EC coding */ + } + } + else if ( ec_mode == 2 ) + { + if ( bitstream[( *index )--] == 0 ) + { + if ( bitstream[( *index )--] == 0 ) + { + dec_mode = 1; /* Switch to one value EC coding */ + } + else + { + dec_mode = 0; /* Use one-bit diff bandwise mode */ + } + } + } + + if ( dec_mode == 2 ) /* Raw decoding */ + { + for ( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, 1 << dfRatio_bits[b] ); + } + } + else if ( dec_mode == 1 ) /* One value decoding */ + { + ratio_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, max_alphabet_size ); /* dif_unique_value */ + + for ( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = ratio_min; + } + } + else /* Bandwise 1-bit diff decoding */ + { + ratio_min = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, max_alphabet_size - 1 ); /* dif_min_value */ + + for ( b = start_band; b < nbands; b++ ) + { + q_direction->band_data[b].energy_ratio_index[0] = ratio_min + bitstream[( *index )--]; /* dif_bit_offset_values */ + } + } + + return ( index_start - *index ); +} +#endif + + +/*-----------------------------------------------------------------------* + * Local functions (EC1) + *-----------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + * ivas_qmetadata_entropy_decode_dir() + * + * Main function for entropy decoding of the directions + *------------------------------------------------------------------------*/ + +static int16_t ivas_qmetadata_entropy_decode_dir( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + uint16_t *bitstream, /* i : bitstream */ int16_t *index, const uint16_t diffuseness_index_max_ec_frame, const int16_t nbands, @@ -1900,1548 +2651,3484 @@ static int16_t ivas_qmetadata_entropy_decode_dir( return ( index_start - *index ); } - -/*------------------------------------------------------------------------- - * ivas_qmetadata_raw_decode_dir() - * - * Main function for raw decoding of the directions - *------------------------------------------------------------------------*/ - -static int16_t ivas_qmetadata_raw_decode_dir_512( +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_entropy_decode_dir_fx( IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ - uint16_t *bitstream, /* i : bitstream */ - int16_t *index, - const int16_t nbands, - const int16_t start_band, - const SPHERICAL_GRID_DATA *sph_grid16 /* i : spherical grid for deindexing */ + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, + const UWord16 diffuseness_index_max_ec_frame, + const Word16 nbands, + const Word16 start_band, + const Word16 hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ ) { - int16_t b, m, i; - int16_t nblocks; - int16_t index_start; - uint16_t value; + Word16 b, m; + Word16 diff_idx; + Word16 diff_idx_min; + Word16 nblocks; + Word16 index_start; + + UWord16 gr_param_elev, gr_param_azith; + Word16 bands_entropic[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 elev_alph[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 azith_alph[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + + Word16 avg_elevation_alphabet, avg_azimuth_alphabet; + Word16 avg_elevation_idx, avg_azimuth_index; + Word16 avg_elevation_index_projected, avg_azimuth_index_projected; + float direction_vector[3], avg_direction_vector[3], avg_azimuth, avg_elevation; + Word16 use_adapt_avg, idx; index_start = *index; nblocks = q_direction->cfg.nblocks; - for ( b = start_band; b < nbands; b++ ) + diff_idx_min = DIRAC_DIFFUSE_LEVELS; + + /*Raw coding for high diffuseness*/ + FOR( b = start_band; b < nbands; b++ ) { - for ( m = 0; m < nblocks; m++ ) + IF( hrmasa_flag ) { - value = 0; - for ( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) - { - value = ( value << 1 ) + bitstream[( *index )--]; - } - q_direction->band_data[b].spherical_index[m] = value; + diff_idx = 0; + } + ELSE + { + diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + } - if ( q_direction->band_data[b].bits_sph_idx[m] == 16 ) + diff_idx_min = min( diff_idx_min, diff_idx ); + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + elev_alph[b] = no_theta_masa[bits_direction_masa[diff_idx] - 3]; + } + ELSE + { + elev_alph[b] = no_theta_masa[bits_direction_masa[diff_idx] - 3] * 2 - 1; + } + + IF( q_direction->band_data[b].energy_ratio_index_mod[0] > diffuseness_index_max_ec_frame ) + { + bands_entropic[b] = 0; + + IF( q_direction->not_in_2D > 0 ) { - deindex_sph_idx( value, sph_grid16, &( q_direction->band_data[b].elevation[m] ), &( q_direction->band_data[b].azimuth[m] ) ); + decode_fixed_rate( q_direction, bitstream, index, b, nblocks ); } - else + ELSE { - deindex_spherical_component( q_direction->band_data[b].spherical_index[m], &q_direction->band_data[b].azimuth[m], &q_direction->band_data[b].elevation[m], &q_direction->band_data[b].azimuth_index[m], &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + /* in 2D */ + FOR( m = 0; m < nblocks; m++ ) + { + q_direction->band_data[b].elevation[m] = 0.f; + q_direction->band_data[b].elevation_index[m] = 0; + + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][0]; + q_direction->band_data[b].azimuth_index[m] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, azith_alph[b][m] ); + q_direction->band_data[b].azimuth[m] = deindex_azimuth( q_direction->band_data[b].azimuth_index[m], q_direction->band_data[b].bits_sph_idx[m], 0, 1, q_direction->cfg.mc_ls_setup ); + } } } + ELSE + { + bands_entropic[b] = 1; + } } - return ( index_start - *index ); -} - - -/*------------------------------------------------------------------------- - * ivas_qmetadata_raw_decode_dir() - * - * Main function for raw decoding of the directions - *------------------------------------------------------------------------*/ - -static int16_t ivas_qmetadata_raw_decode_dir( - IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ - uint16_t *bitstream, /* i : bitstream */ - int16_t *index, - const int16_t nbands, - const int16_t start_band, - const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ -) -{ - int16_t b, m, azith_alph; - int16_t diff_idx; - int16_t nblocks; - int16_t index_start; - - index_start = *index; - nblocks = q_direction->cfg.nblocks; + /*EC for the low diffuseness*/ - for ( b = start_band; b < nbands; b++ ) + /*Elevation only if not 2D */ + IF( q_direction->not_in_2D > 0 ) { - if ( q_direction->not_in_2D > 0 ) + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { - decode_fixed_rate( q_direction, bitstream, index, b, nblocks ); + avg_elevation_alphabet = no_theta_masa[bits_direction_masa[diff_idx_min] - 3]; + avg_elevation_idx = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, avg_elevation_alphabet ); } - else + ELSE { - if ( hrmasa_flag ) - { - diff_idx = 0; - } - else - { - diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; - } - - for ( m = 0; m < nblocks; m++ ) - { - q_direction->band_data[b].elevation[m] = 0.f; - q_direction->band_data[b].elevation_index[m] = 0; - azith_alph = no_phi_masa[bits_direction_masa[diff_idx] - 1][0]; - q_direction->band_data[b].azimuth_index[m] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, azith_alph ); - q_direction->band_data[b].azimuth[m] = deindex_azimuth( q_direction->band_data[b].azimuth_index[m], q_direction->band_data[b].bits_sph_idx[m], 0, 1, q_direction->cfg.mc_ls_setup ); - } + avg_elevation_alphabet = no_theta_masa[bits_direction_masa[diff_idx_min] - 3] * 2 - 1; + avg_elevation_idx = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, avg_elevation_alphabet ); + avg_elevation_idx = ivas_qmetadata_dereorder_generic( avg_elevation_idx ) + ( avg_elevation_alphabet >> 1 ); } - } - return ( index_start - *index ); -} + gr_param_elev = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, 4 + 1 ); + IF( gr_param_elev == 4 ) /* all the elevation distances are zero */ + { + FOR( b = start_band; b < nbands; b++ ) + { + IF( bands_entropic[b] ) + { + Word16 tmp_index; + IF( hrmasa_flag ) + { + diff_idx = 0; + } + ELSE + { + diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + } + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + avg_elevation_index_projected = ivas_chan_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); + } + ELSE + { + avg_elevation_index_projected = ivas_dirac_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); -/*------------------------------------------------------------------------- - * ivas_qmetadata_DecodeQuasiUniform() - * - * Read the bitstream following the encoding scheme of EncodeQuasiUniform + /*reorder elevation indexing*/ + tmp_index = avg_elevation_index_projected - ( elev_alph[b] >> 1 ); + IF( tmp_index < 0 ) + { + tmp_index = tmp_index * -2; + } + ELSE IF( tmp_index > 0 ) + { + tmp_index = tmp_index * 2 - 1; + } + avg_elevation_index_projected = tmp_index; + } + + FOR( m = 0; m < nblocks; m++ ) + { + q_direction->band_data[b].elevation_index[m] = avg_elevation_index_projected; + + /*deduce aplhabet for azimuth*/ + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][q_direction->band_data[b].elevation_index[m]]; + } + ELSE + { + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][( q_direction->band_data[b].elevation_index[m] + 1 ) >> 1]; + } + + /*decode elevation*/ + q_direction->band_data[b].elevation[m] = deindex_elevation( &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + } + } + } + } + ELSE + { + FOR( b = start_band; b < nbands; b++ ) + { + IF( bands_entropic[b] ) + { + IF( hrmasa_flag ) + { + diff_idx = 0; + } + ELSE + { + diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + } + + FOR( m = 0; m < nblocks; m++ ) + { + Word16 tmp_index; + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + avg_elevation_index_projected = ivas_chan_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); + tmp_index = ivas_qmetadata_DecodeExtendedGR( bitstream, index, 2 * elev_alph[b] - 1, gr_param_elev ); + IF( tmp_index % 2 ) + { + tmp_index = avg_elevation_index_projected + ( ( tmp_index + 1 ) >> 1 ); + } + ELSE + { + tmp_index = avg_elevation_index_projected - ( tmp_index >> 1 ); + } + q_direction->band_data[b].elevation_index[m] = tmp_index; + + /*deduce aplhabet for azimuth*/ + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][q_direction->band_data[b].elevation_index[m]]; + } + ELSE + { + avg_elevation_index_projected = ivas_dirac_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); + + tmp_index = ivas_qmetadata_DecodeExtendedGR( bitstream, index, elev_alph[b], gr_param_elev ); + tmp_index = ivas_qmetadata_ReorderElevationDecoded( tmp_index, avg_elevation_index_projected, elev_alph[b] ); + + /*reorder elevation indexing*/ + tmp_index = tmp_index - ( elev_alph[b] >> 1 ); + IF( tmp_index < 0 ) + { + tmp_index = tmp_index * -2; + } + ELSE IF( tmp_index > 0 ) + { + tmp_index = tmp_index * 2 - 1; + } + q_direction->band_data[b].elevation_index[m] = tmp_index; + + /*deduce aplhabet for azimuth*/ + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][( q_direction->band_data[b].elevation_index[m] + 1 ) >> 1]; + } + + /*decode elevation*/ + q_direction->band_data[b].elevation[m] = deindex_elevation( &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + } + } + } + } + } + ELSE + { + FOR( b = start_band; b < nbands; b++ ) + { + IF( bands_entropic[b] ) + { + IF( hrmasa_flag ) + { + diff_idx = 0; + } + ELSE + { + diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + } + + FOR( m = 0; m < nblocks; m++ ) + { + q_direction->band_data[b].elevation_index[m] = 0; + + /*deduce alphabet for azimuth*/ + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][q_direction->band_data[b].elevation_index[m]]; + } + ELSE + { + azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][( q_direction->band_data[b].elevation_index[m] + 1 ) >> 1]; + } + + /*decode elevation*/ + q_direction->band_data[b].elevation[m] = deindex_elevation( &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + } + } + } + } + + /*Azimuth*/ + avg_azimuth_alphabet = no_phi_masa[bits_direction_masa[diff_idx_min] - 1][0]; /* average azimuth is quantized on the equatorial plane */ + avg_azimuth_index = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, avg_azimuth_alphabet ); + avg_azimuth_index = ivas_qmetadata_dereorder_generic( avg_azimuth_index ); + avg_azimuth_index = avg_azimuth_index + ( avg_azimuth_alphabet >> 1 ); + + gr_param_azith = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, 5 + 1 ); + IF( gr_param_azith == 5 ) /* all the azimuth distances are zero */ + { + FOR( b = start_band; b < nbands; b++ ) + { + IF( bands_entropic[b] ) + { + FOR( m = 0; m < nblocks; m++ ) + { + q_direction->band_data[b].azimuth_index[m] = ivas_dirac_project_azimuth_index( avg_azimuth_index, avg_azimuth_alphabet, azith_alph[b][m] ); + + IF( azith_alph[b][m] == 1 ) + { + q_direction->band_data[b].azimuth[m] = 0.f; + } + ELSE + { + q_direction->band_data[b].azimuth[m] = deindex_azimuth( q_direction->band_data[b].azimuth_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->band_data[b].elevation_index[m], 0, q_direction->cfg.mc_ls_setup ); + } + } + } + } + } + ELSE + { + set_zero( avg_direction_vector, 3 ); + use_adapt_avg = 0; + idx = 0; + + FOR( b = start_band; b < nbands; b++ ) + { + IF( bands_entropic[b] ) + { + FOR( m = 0; m < nblocks; m++ ) + { + IF( ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) && ( idx == MASA_LIMIT_IDX_AVG_AZI ) && ( nblocks > 1 ) ) + { + use_adapt_avg = bitstream[*index]; + ( *index )--; + } + avg_azimuth_index_projected = ivas_dirac_project_azimuth_index( avg_azimuth_index, avg_azimuth_alphabet, azith_alph[b][m] ); + q_direction->band_data[b].azimuth_index[m] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, azith_alph[b][m], gr_param_azith ); + q_direction->band_data[b].azimuth_index[m] = ivas_qmetadata_ReorderElevationDecoded( q_direction->band_data[b].azimuth_index[m], avg_azimuth_index_projected, azith_alph[b][m] ); + + IF( azith_alph[b][m] == 1 ) + { + q_direction->band_data[b].azimuth[m] = 0.f; + } + ELSE + { + q_direction->band_data[b].azimuth[m] = deindex_azimuth( q_direction->band_data[b].azimuth_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->band_data[b].elevation_index[m], 0, q_direction->cfg.mc_ls_setup ); + } + IF( ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) && ( nblocks > 1 ) ) + { + IF( idx < MASA_LIMIT_IDX_AVG_AZI ) + { + ivas_qmetadata_azimuth_elevation_to_direction_vector( q_direction->band_data[b].azimuth[m], q_direction->band_data[b].elevation[m], direction_vector ); + v_add( avg_direction_vector, direction_vector, avg_direction_vector, 3 ); + } + ELSE + { + IF( use_adapt_avg == 1 ) + { + IF( m == 0 ) + { + v_multc( avg_direction_vector, 0.5f, avg_direction_vector, 3 ); + } + /*compute the average direction per already coded subband */ + ivas_qmetadata_azimuth_elevation_to_direction_vector( q_direction->band_data[b].azimuth[m], q_direction->band_data[b].elevation[m], direction_vector ); + v_add( avg_direction_vector, direction_vector, avg_direction_vector, 3 ); + ivas_qmetadata_direction_vector_to_azimuth_elevation( avg_direction_vector, &avg_azimuth, &avg_elevation ); + avg_azimuth_index = quantize_phi( avg_azimuth + 180, 0, &avg_azimuth, avg_azimuth_alphabet ); + } + } + idx++; + } + } + } + } + } + + return ( index_start - *index ); +} +#endif + +/*------------------------------------------------------------------------- + * ivas_qmetadata_raw_decode_dir() + * + * Main function for raw decoding of the directions + *------------------------------------------------------------------------*/ + +static int16_t ivas_qmetadata_raw_decode_dir_512( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + uint16_t *bitstream, /* i : bitstream */ + int16_t *index, + const int16_t nbands, + const int16_t start_band, + const SPHERICAL_GRID_DATA *sph_grid16 /* i : spherical grid for deindexing */ +) +{ + int16_t b, m, i; + int16_t nblocks; + int16_t index_start; + uint16_t value; + + index_start = *index; + nblocks = q_direction->cfg.nblocks; + + for ( b = start_band; b < nbands; b++ ) + { + for ( m = 0; m < nblocks; m++ ) + { + value = 0; + for ( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) + { + value = ( value << 1 ) + bitstream[( *index )--]; + } + q_direction->band_data[b].spherical_index[m] = value; + + if ( q_direction->band_data[b].bits_sph_idx[m] == 16 ) + { + deindex_sph_idx( value, sph_grid16, &( q_direction->band_data[b].elevation[m] ), &( q_direction->band_data[b].azimuth[m] ) ); + } + else + { + deindex_spherical_component( q_direction->band_data[b].spherical_index[m], &q_direction->band_data[b].azimuth[m], &q_direction->band_data[b].elevation[m], &q_direction->band_data[b].azimuth_index[m], &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + } + } + } + + return ( index_start - *index ); +} + + +/*------------------------------------------------------------------------- + * ivas_qmetadata_raw_decode_dir() + * + * Main function for raw decoding of the directions *------------------------------------------------------------------------*/ -/*! r: Value read from the bitstream */ -static uint16_t ivas_qmetadata_DecodeQuasiUniform( - const uint16_t *bitstream, /* i : pointer to the bitstream to read */ - int16_t *index, /* i : position in the bitstream to start reading (gets updated with reading) */ - const uint16_t alphabet_size /* i : size of the alphabet, used to calculate the number of bits needed */ +static int16_t ivas_qmetadata_raw_decode_dir( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + uint16_t *bitstream, /* i : bitstream */ + int16_t *index, + const int16_t nbands, + const int16_t start_band, + const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ +) +{ + int16_t b, m, azith_alph; + int16_t diff_idx; + int16_t nblocks; + int16_t index_start; + + index_start = *index; + nblocks = q_direction->cfg.nblocks; + + for ( b = start_band; b < nbands; b++ ) + { + if ( q_direction->not_in_2D > 0 ) + { + decode_fixed_rate( q_direction, bitstream, index, b, nblocks ); + } + else + { + if ( hrmasa_flag ) + { + diff_idx = 0; + } + else + { + diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + } + + for ( m = 0; m < nblocks; m++ ) + { + q_direction->band_data[b].elevation[m] = 0.f; + q_direction->band_data[b].elevation_index[m] = 0; + azith_alph = no_phi_masa[bits_direction_masa[diff_idx] - 1][0]; + q_direction->band_data[b].azimuth_index[m] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, azith_alph ); + q_direction->band_data[b].azimuth[m] = deindex_azimuth( q_direction->band_data[b].azimuth_index[m], q_direction->band_data[b].bits_sph_idx[m], 0, 1, q_direction->cfg.mc_ls_setup ); + } + } + } + + return ( index_start - *index ); +} + +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_raw_decode_dir_fx( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, + const Word16 nbands, + const Word16 start_band, + const Word16 hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ +) +{ + Word16 b, m, azith_alph; + Word16 diff_idx; + Word16 nblocks; + Word16 index_start; + + index_start = *index; + nblocks = q_direction->cfg.nblocks; + + FOR( b = start_band; b < nbands; b++ ) + { + IF( q_direction->not_in_2D > 0 ) + { + decode_fixed_rate_fx( q_direction, bitstream, index, b, nblocks ); + } + ELSE + { + IF( hrmasa_flag ) + { + diff_idx = 0; + } + ELSE + { + diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + } + + FOR( m = 0; m < nblocks; m++ ) + { + q_direction->band_data[b].elevation_fx[m] = 0; + q_direction->band_data[b].elevation_index[m] = 0; + azith_alph = no_phi_masa[bits_direction_masa[diff_idx] - 1][0]; + q_direction->band_data[b].azimuth_index[m] = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, azith_alph ); + q_direction->band_data[b].azimuth_fx[m] = deindex_azimuth_fx( q_direction->band_data[b].azimuth_index[m], q_direction->band_data[b].bits_sph_idx[m], 0, 1, q_direction->cfg.mc_ls_setup ); + } + } + } + + return ( index_start - *index ); +} +#endif + +/*------------------------------------------------------------------------- + * ivas_qmetadata_DecodeQuasiUniform() + * + * Read the bitstream following the encoding scheme of EncodeQuasiUniform + *------------------------------------------------------------------------*/ + +/*! r: Value read from the bitstream */ +#ifdef IVAS_FLOAT_FIXED +static UWord16 ivas_qmetadata_DecodeQuasiUniform( + const UWord16 *bitstream, /* i : pointer to the bitstream to read */ + Word16 *index, /* i : position in the bitstream to start reading (gets updated with reading) */ + const UWord16 alphabet_size /* i : size of the alphabet, used to calculate the number of bits needed */ +) +{ + Word16 i, bits; + UWord16 tresh, value; + + + bits = 30 - norm_l( alphabet_size ); /* bits = floor(log2(alphabet_size)) */ + tresh = ( 1U << ( bits + 1 ) ) - alphabet_size; + + value = 0; + FOR( i = 0; i < bits; i++ ) + { + value = ( value << 1 ) + bitstream[( *index )--]; + } + + IF( value >= tresh ) + { + value = ( value << 1 ) - tresh + bitstream[( *index )--]; + } + + return value; +} +#else +static uint16_t ivas_qmetadata_DecodeQuasiUniform( + const uint16_t *bitstream, /* i : pointer to the bitstream to read */ + int16_t *index, /* i : position in the bitstream to start reading (gets updated with reading) */ + const uint16_t alphabet_size /* i : size of the alphabet, used to calculate the number of bits needed */ +) +{ + int16_t i, bits; + uint16_t tresh, value; + + + bits = 30 - norm_l( alphabet_size ); /* bits = floor(log2(alphabet_size)) */ + tresh = ( 1U << ( bits + 1 ) ) - alphabet_size; + + value = 0; + for ( i = 0; i < bits; i++ ) + { + value = ( value << 1 ) + bitstream[( *index )--]; + } + + if ( value >= tresh ) + { + value = ( value << 1 ) - tresh + bitstream[( *index )--]; + } + + return value; +} +#endif + + +/*------------------------------------------------------------------------- + * ivas_qmetadata_DecodeExtendedGR() + * + * Reads the bitstream and decodes the value using the ExtendedGR algorithm + *------------------------------------------------------------------------*/ + +/*! r: Value decoded from the bitstream */ + +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_qmetadata_DecodeExtendedGR( + UWord16 *bitstream, /* i : pointer to the bitstream to read */ + Word16 *index, /* i/o: position in the bitstream to start reading (gets updated with reading) */ + const Word16 alph_size, /* i : size of the alphabet, used to calculate the number of bits needed */ + const Word16 gr_param /* i : GR parameter that indicates the limit for the most significant bits (msb) */ +) +{ + Word16 i, msb_size; + UWord16 value; + Word16 msb, lsb; + + msb_size = ( alph_size + ( 1 << gr_param ) - 1 ) >> gr_param; /* ceil division */ + IF( msb_size <= 3 ) + { + value = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, alph_size ); + } + ELSE + { + msb = 0; + WHILE( ( msb < msb_size - 1 ) && ( bitstream[*index] != 0 ) ) + { + msb++; + ( *index )--; + } + + IF( msb == msb_size - 1 ) + { + lsb = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, alph_size - ( ( msb_size - 1 ) << gr_param ) ); + } + ELSE + { + ( *index )--; + lsb = 0; + FOR( i = 0; i < gr_param; i++ ) + { + lsb = ( lsb << 1 ) + bitstream[( *index )--]; + } + } + + value = ( msb << gr_param ) + lsb; + } + + return value; +} +#else +int16_t ivas_qmetadata_DecodeExtendedGR( + uint16_t *bitstream, /* i : pointer to the bitstream to read */ + int16_t *index, /* i/o: position in the bitstream to start reading (gets updated with reading) */ + const int16_t alph_size, /* i : size of the alphabet, used to calculate the number of bits needed */ + const int16_t gr_param /* i : GR parameter that indicates the limit for the most significant bits (msb) */ +) +{ + int16_t i, msb_size; + uint16_t value; + int16_t msb, lsb; + + msb_size = ( alph_size + ( 1 << gr_param ) - 1 ) >> gr_param; /* ceil division */ + if ( msb_size <= 3 ) + { + value = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, alph_size ); + } + else + { + msb = 0; + while ( ( msb < msb_size - 1 ) && ( bitstream[*index] != 0 ) ) + { + msb++; + ( *index )--; + } + + if ( msb == msb_size - 1 ) + { + lsb = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, alph_size - ( ( msb_size - 1 ) << gr_param ) ); + } + else + { + ( *index )--; + lsb = 0; + for ( i = 0; i < gr_param; i++ ) + { + lsb = ( lsb << 1 ) + bitstream[( *index )--]; + } + } + + value = ( msb << gr_param ) + lsb; + } + + return value; +} +#endif + +/*------------------------------------------------------------------------- + * ivas_qmetadata_ReorderElevationDecoded() + * + * Calculates the correct elevation index from the decoded data + *------------------------------------------------------------------------*/ + +/*! r: Elevation index as it will be read by the dequantizer */ +#ifdef IVAS_FLOAT_FIXED +static Word16 ivas_qmetadata_ReorderElevationDecoded( + const Word16 elev_dist, /* i : Distance to the average extracted from the bitstream */ + const Word16 elev_avg, /* i : Average value over time-blocks extracted from the bitstream */ + const Word16 elev_alph /* i : elevation alphabet */ +) +{ + Word16 dist_reorder; + Word16 elev_index_reorder; + + dist_reorder = ivas_qmetadata_dereorder_generic( elev_dist ); + elev_index_reorder = elev_avg + dist_reorder; + + IF( elev_index_reorder < 0 ) + { + elev_index_reorder += elev_alph; + } + ELSE IF( elev_index_reorder >= elev_alph ) + { + elev_index_reorder -= elev_alph; + } + + return elev_index_reorder; +} +#else +static int16_t ivas_qmetadata_ReorderElevationDecoded( + const int16_t elev_dist, /* i : Distance to the average extracted from the bitstream */ + const int16_t elev_avg, /* i : Average value over time-blocks extracted from the bitstream */ + const int16_t elev_alph /* i : elevation alphabet */ +) +{ + int16_t dist_reorder; + int16_t elev_index_reorder; + + dist_reorder = ivas_qmetadata_dereorder_generic( elev_dist ); + elev_index_reorder = elev_avg + dist_reorder; + + if ( elev_index_reorder < 0 ) + { + elev_index_reorder += elev_alph; + } + else if ( elev_index_reorder >= elev_alph ) + { + elev_index_reorder -= elev_alph; + } + + return elev_index_reorder; +} +#endif + + +/*-----------------------------------------------------------------------* + * Local functions: requentizeEC3 + *-----------------------------------------------------------------------*/ + +/*! r: number of bits read */ +static int16_t read_directions( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + const uint8_t coding_subbands, /* i : number of directions */ + const uint8_t masa_subframes, /* i : number of tiles */ + uint16_t *bitstream, /* i : bitstream to be read */ + int16_t *pbit_pos, + int16_t *ind_order ) +{ + int16_t j, k, allowed_bits, last_j, nbits, fixed_rate; + int16_t i; + int16_t diff; + uint16_t byteBuffer; + int16_t use_vq, max_nb_idx; + int16_t bit_pos; + int16_t *bits_dir0; + + bit_pos = *pbit_pos; + + diff = 0; + if ( q_direction->not_in_2D ) + { + if ( coding_subbands > 1 ) + { + j = ind_order[coding_subbands - 1]; + allowed_bits = 0; + + for ( k = 0; k < masa_subframes; k++ ) + { + allowed_bits += q_direction->band_data[j].bits_sph_idx[k]; + } + + last_j = j - ( allowed_bits == 0 ); + + for ( j = 0; j < last_j; j++ ) + { + i = ind_order[j]; + bits_dir0 = (int16_t *) q_direction->band_data[i].bits_sph_idx; + + nbits = 0; + allowed_bits = sum_s( bits_dir0, q_direction->cfg.nblocks ); + use_vq = 0; + max_nb_idx = 0; + + for ( k = 0; k < q_direction->cfg.nblocks; k++ ) + { + if ( bits_dir0[k] > use_vq ) + { + use_vq = bits_dir0[k]; + max_nb_idx = k; + } + } + + if ( q_direction->cfg.nblocks == 1 ) + { + byteBuffer = 0; + } + else + { + byteBuffer = 0; + if ( use_vq <= 1 ) + { + byteBuffer = 1; + } + if ( use_vq > 1 && use_vq <= LIMIT_USE_COMMON ) + { + bits_dir0[max_nb_idx] -= 1; + allowed_bits -= 1; + /* read 1 bit to tell if joint of VQ coding */ + byteBuffer = bitstream[bit_pos--]; + } + } + + for ( k = 0; k < masa_subframes; k++ ) + { + q_direction->band_data[i].bits_sph_idx[k] = bits_dir0[k]; + if ( bits_dir0[k] > 2 ) + { + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + q_direction->band_data[i].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3]; + } + else + { + q_direction->band_data[i].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3] * 2 - 1; + } + } + else + { + q_direction->band_data[i].elevation_m_alphabet[k] = 1; + } + } + + if ( allowed_bits > 0 ) + { + if ( byteBuffer == 1 ) + { + nbits = read_common_direction( bitstream, q_direction, i, masa_subframes, allowed_bits, &bit_pos ); + } + else + { + if ( q_direction->cfg.nblocks == 1 && q_direction->band_data[i].bits_sph_idx[0] <= MASA_MIN_BITS_TF + 1 ) + { + /* there is fixed rate only, no need to read */ + fixed_rate = 1; + nbits = 0; + } + else + { + /* check if fixed_rate */ + fixed_rate = bitstream[bit_pos--]; + nbits = 1; + } + + if ( fixed_rate == 1 ) + { + /* decode_fixed_rate()*/ + nbits += decode_fixed_rate( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + else + { + /* decode elevation */ + nbits += decode_elevation( q_direction, bitstream, &bit_pos, i, masa_subframes ); + + /* decode azimuth */ + nbits += decode_azimuth( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + } + } + else + { + set_zero_direction( q_direction, i, masa_subframes ); + } + diff += nbits - allowed_bits; + + /* update bits for next block */ + update_bits_next_block( q_direction, &diff, ind_order[j + 1], coding_subbands, masa_subframes ); + } + } + else + { + last_j = q_direction->cfg.start_band; + } + + + for ( j = last_j; j < coding_subbands; j++ ) + { + i = ind_order[j]; + bits_dir0 = (int16_t *) q_direction->band_data[i].bits_sph_idx; + + nbits = 0; + allowed_bits = sum_s( bits_dir0, q_direction->cfg.nblocks ); + if ( allowed_bits > 0 && masa_subframes == 1 ) + { + nbits += decode_fixed_rate( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + else + { + if ( allowed_bits > 0 ) + { + use_vq = 0; + max_nb_idx = 0; + for ( k = 0; k < masa_subframes; k++ ) + { + if ( bits_dir0[k] > use_vq ) + { + use_vq = bits_dir0[k]; + max_nb_idx = k; + } + } + + byteBuffer = 0; + + if ( use_vq > 1 && use_vq <= LIMIT_USE_COMMON ) + { + bits_dir0[max_nb_idx] -= 1; + allowed_bits -= 1; + + /* read 1 bit to tell if joint of VQ coding */ + byteBuffer = bitstream[bit_pos--]; + } + + if ( allowed_bits > 0 ) + { + if ( byteBuffer == 1 || use_vq <= 1 ) + { + nbits = read_common_direction( bitstream, q_direction, i, masa_subframes, allowed_bits, &bit_pos ); + } + else + { + /* decode_fixed_rate()*/ + nbits += decode_fixed_rate( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + } + else + { + set_zero_direction( q_direction, i, masa_subframes ); + } + } + else + { + set_zero_direction( q_direction, i, masa_subframes ); + } + } + } + } + else + { + /* 2D */ + for ( j = 0; j < coding_subbands; j++ ) + { + for ( k = 0; k < q_direction->cfg.nblocks; k++ ) + { + q_direction->band_data[j].elevation[k] = 0; + q_direction->band_data[j].elevation_index[k] = 0; + } + } + nbits = decode_azimuth2D( q_direction, bitstream, coding_subbands, &bit_pos, masa_subframes ); + } + nbits = *pbit_pos - bit_pos; + *pbit_pos = bit_pos; + + return nbits; +} + +#ifdef IVAS_FLOAT_FIXED +static Word16 read_directions_fx( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + const UWord8 coding_subbands, /* i : number of directions */ + const UWord8 masa_subframes, /* i : number of tiles */ + UWord16 *bitstream, /* i : bitstream to be read */ + Word16 *pbit_pos, + Word16 *ind_order ) +{ + Word16 j, k, allowed_bits, last_j, nbits, fixed_rate; + Word16 i; + Word16 diff; + UWord16 byteBuffer; + Word16 use_vq, max_nb_idx; + Word16 bit_pos; + Word16 *bits_dir0; + + bit_pos = *pbit_pos; + + diff = 0; + IF( q_direction->not_in_2D ) + { + + IF( coding_subbands > 1 ) + { + j = ind_order[coding_subbands - 1]; + allowed_bits = 0; + + FOR( k = 0; k < masa_subframes; k++ ) + { + allowed_bits += q_direction->band_data[j].bits_sph_idx[k]; + } + + last_j = j - ( allowed_bits == 0 ); + + FOR( j = 0; j < last_j; j++ ) + { + i = ind_order[j]; + bits_dir0 = (Word16 *) q_direction->band_data[i].bits_sph_idx; + + nbits = 0; + allowed_bits = sum_s( bits_dir0, q_direction->cfg.nblocks ); + use_vq = 0; + max_nb_idx = 0; + + FOR( k = 0; k < q_direction->cfg.nblocks; k++ ) + { + IF( bits_dir0[k] > use_vq ) + { + use_vq = bits_dir0[k]; + max_nb_idx = k; + } + } + + IF( q_direction->cfg.nblocks == 1 ) + { + byteBuffer = 0; + } + ELSE + { + byteBuffer = 0; + IF( use_vq <= 1 ) + { + byteBuffer = 1; + } + IF( use_vq > 1 && use_vq <= LIMIT_USE_COMMON ) + { + bits_dir0[max_nb_idx] -= 1; + allowed_bits -= 1; + /* read 1 bit to tell if joint of VQ coding */ + byteBuffer = bitstream[bit_pos--]; + } + } + + FOR( k = 0; k < masa_subframes; k++ ) + { + q_direction->band_data[i].bits_sph_idx[k] = bits_dir0[k]; + IF( bits_dir0[k] > 2 ) + { + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + q_direction->band_data[i].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3]; + } + ELSE + { + q_direction->band_data[i].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3] * 2 - 1; + } + } + ELSE + { + q_direction->band_data[i].elevation_m_alphabet[k] = 1; + } + } + + IF( allowed_bits > 0 ) + { + IF( byteBuffer == 1 ) + { + nbits = read_common_direction_fx( bitstream, q_direction, i, masa_subframes, allowed_bits, &bit_pos ); + } + ELSE + { + IF( q_direction->cfg.nblocks == 1 && q_direction->band_data[i].bits_sph_idx[0] <= MASA_MIN_BITS_TF + 1 ) + { + /* there is fixed rate only, no need to read */ + fixed_rate = 1; + nbits = 0; + } + ELSE + { + /* check if fixed_rate */ + fixed_rate = bitstream[bit_pos--]; + nbits = 1; + } + + IF( fixed_rate == 1 ) + { + /* decode_fixed_rate()*/ + nbits += decode_fixed_rate_fx( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + ELSE + { + + /* decode elevation */ + nbits += decode_elevation_fx( q_direction, bitstream, &bit_pos, i, masa_subframes ); + /* decode azimuth */ + nbits += decode_azimuth_fx( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + } + } + ELSE + { + set_zero_direction_fx( q_direction, i, masa_subframes ); + } + + diff += nbits - allowed_bits; + + /* update bits for next block */ + update_bits_next_block( q_direction, &diff, ind_order[j + 1], coding_subbands, masa_subframes ); + } + } + ELSE + { + last_j = q_direction->cfg.start_band; + } + + + FOR( j = last_j; j < coding_subbands; j++ ) + { + i = ind_order[j]; + bits_dir0 = (Word16 *) q_direction->band_data[i].bits_sph_idx; + + nbits = 0; + allowed_bits = sum_s( bits_dir0, q_direction->cfg.nblocks ); + IF( allowed_bits > 0 && masa_subframes == 1 ) + { + nbits += decode_fixed_rate_fx( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + ELSE + { + IF( allowed_bits > 0 ) + { + use_vq = 0; + max_nb_idx = 0; + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( bits_dir0[k] > use_vq ) + { + use_vq = bits_dir0[k]; + max_nb_idx = k; + } + } + + byteBuffer = 0; + + IF( use_vq > 1 && use_vq <= LIMIT_USE_COMMON ) + { + bits_dir0[max_nb_idx] -= 1; + allowed_bits -= 1; + + /* read 1 bit to tell if joint of VQ coding */ + byteBuffer = bitstream[bit_pos--]; + } + + IF( allowed_bits > 0 ) + { + IF( byteBuffer == 1 || use_vq <= 1 ) + { + nbits = read_common_direction_fx( bitstream, q_direction, i, masa_subframes, allowed_bits, &bit_pos ); + } + ELSE + { + /* decode_fixed_rate()*/ + nbits += decode_fixed_rate_fx( q_direction, bitstream, &bit_pos, i, masa_subframes ); + } + } + ELSE + { + set_zero_direction_fx( q_direction, i, masa_subframes ); + } + } + ELSE + { + set_zero_direction_fx( q_direction, i, masa_subframes ); + } + } + } + } + ELSE + { + /* 2D */ + FOR( j = 0; j < coding_subbands; j++ ) + { + FOR( k = 0; k < q_direction->cfg.nblocks; k++ ) + { + q_direction->band_data[j].elevation_fx[k] = 0; + q_direction->band_data[j].elevation_index[k] = 0; + } + } + + nbits = decode_azimuth2D_fx( q_direction, bitstream, coding_subbands, &bit_pos, masa_subframes ); + } + nbits = *pbit_pos - bit_pos; + *pbit_pos = bit_pos; + + return nbits; +} +#endif + +/*-------------------------------------------------------------------* + * decode_azimuth() + * + * read and decode the azimuth indexes for one subband + *-------------------------------------------------------------------*/ + +/*! r: number of bits read */ +static int16_t decode_azimuth( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + uint16_t *bitstream, /* i : bitstream to be read */ + int16_t *pbit_pos, /* i/o: current position in bitstream */ + const int16_t idx_subband, /* i : subband index */ + const int16_t masa_subframes /* i : number of tiles */ +) +{ + int16_t bit_pos, nbits, k; + uint16_t use_context, byteBuffer; + uint16_t min_idx; + int16_t j_az, max_val; + + nbits = 0; + bit_pos = *pbit_pos; + byteBuffer = 0; + + j_az = 0; + /* check number of valid indexes to decode */ + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[idx_subband].azimuth_index[k] < MASA_NO_INDEX ) + { + j_az++; + } + else + { + q_direction->band_data[idx_subband].azimuth[k] = 0.f; /*To be in sync with encoder values.*/ + } + } + + if ( j_az == 0 ) + { + return nbits; + } + + if ( byteBuffer == 0 ) + { + /* use context */ + use_context = 0; + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[idx_subband].bits_sph_idx[k] <= 1 ) + { + use_context = 1; + } + } + + if ( use_context == 1 ) + { + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 0 ) + { + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + q_direction->band_data[idx_subband].azimuth[k] = 0; + } + else + { + if ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 1 ) + { + byteBuffer = bitstream[bit_pos--]; + q_direction->band_data[idx_subband].azimuth_index[k] = byteBuffer; + + q_direction->band_data[idx_subband].azimuth[k] = q_direction->band_data[idx_subband].azimuth_index[k] * ( -180.f ); + } + else + { + q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 2 ) ); + + q_direction->band_data[idx_subband].azimuth[k] = deindex_azimuth( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); + } + } + } + } + else + { + /* read bit to check if min removed encoding */ + byteBuffer = bitstream[bit_pos--]; + if ( byteBuffer == 0 ) /* regular GR coding5 */ + { + /* read GR_order */ + byteBuffer = bitstream[bit_pos--]; + nbits += 1; + + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[idx_subband].bits_sph_idx[k] > 0 ) + { + if ( no_phi_masa[q_direction->band_data[idx_subband].bits_sph_idx[k] - 1][q_direction->band_data[idx_subband].elevation_index[k]] > 1 ) + { + q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - byteBuffer ); + q_direction->band_data[idx_subband].azimuth[k] = deindex_azimuth( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); + } + else + { + q_direction->band_data[idx_subband].azimuth[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + else + { + q_direction->band_data[idx_subband].azimuth[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + } + else + { + /* min removed GR coding */ + /* read GR_order */ + byteBuffer = bitstream[bit_pos--]; + /* read min index value */ + maximum_s( q_direction->band_data[idx_subband].azimuth_m_alphabet, masa_subframes, &max_val ); + min_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, max_val, MASA_GR_ORD_AZ ); + + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[idx_subband].bits_sph_idx[k] > 0 ) + { + if ( no_phi_masa[q_direction->band_data[idx_subband].bits_sph_idx[k] - 1][q_direction->band_data[idx_subband].elevation_index[k]] > 1 ) + { + q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - 1 - byteBuffer ); + q_direction->band_data[idx_subband].azimuth_index[k] += min_idx; + q_direction->band_data[idx_subband].azimuth[k] = deindex_azimuth( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); + } + else + { + q_direction->band_data[idx_subband].azimuth[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + else + { + q_direction->band_data[idx_subband].azimuth[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + } + } + } + + nbits = *pbit_pos - bit_pos; + + *pbit_pos = bit_pos; + + return nbits; +} + +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_azimuth_fx( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + UWord16 *bitstream, /* i : bitstream to be read */ + Word16 *pbit_pos, /* i/o: current position in bitstream */ + const Word16 idx_subband, /* i : subband index */ + const Word16 masa_subframes /* i : number of tiles */ +) +{ + Word16 bit_pos, nbits, k; + UWord16 use_context, byteBuffer; + UWord16 min_idx; + Word16 j_az, max_val; + + nbits = 0; + bit_pos = *pbit_pos; + byteBuffer = 0; + + j_az = 0; + /* check number of valid indexes to decode */ + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[idx_subband].azimuth_index[k] < MASA_NO_INDEX ) + { + j_az++; + } + ELSE + { + q_direction->band_data[idx_subband].azimuth_fx[k] = 0; /*To be in sync with encoder values.*/ + } + } + + IF( j_az == 0 ) + { + return nbits; + } + + IF( byteBuffer == 0 ) + { + /* use context */ + use_context = 0; + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[idx_subband].bits_sph_idx[k] <= 1 ) + { + use_context = 1; + } + } + + IF( use_context == 1 ) + { + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[idx_subband].bits_sph_idx[k] == 0 ) + { + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + q_direction->band_data[idx_subband].azimuth_fx[k] = 0; + } + ELSE + { + IF( q_direction->band_data[idx_subband].bits_sph_idx[k] == 1 ) + { + byteBuffer = bitstream[bit_pos--]; + q_direction->band_data[idx_subband].azimuth_index[k] = byteBuffer; + + q_direction->band_data[idx_subband].azimuth_fx[k] = L_shl( q_direction->band_data[idx_subband].azimuth_index[k] * ( -180 ), 22 ); + } + ELSE + { + q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 2 ) ); + + q_direction->band_data[idx_subband].azimuth_fx[k] = deindex_azimuth_fx( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); + // q_direction->band_data[idx_subband].azimuth_fx[k] = (float)deindex_azimuth_fx(q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup) / (float) (1<<22); + } + } + } + } + ELSE + { + /* read bit to check if min removed encoding */ + byteBuffer = bitstream[bit_pos--]; + IF( byteBuffer == 0 ) /* regular GR coding5 */ + { + /* read GR_order */ + byteBuffer = bitstream[bit_pos--]; + nbits += 1; + + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[idx_subband].bits_sph_idx[k] > 0 ) + { + IF( no_phi_masa[q_direction->band_data[idx_subband].bits_sph_idx[k] - 1][q_direction->band_data[idx_subband].elevation_index[k]] > 1 ) + { + q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - byteBuffer ); + q_direction->band_data[idx_subband].azimuth_fx[k] = deindex_azimuth_fx( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); + } + ELSE + { + q_direction->band_data[idx_subband].azimuth_fx[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + ELSE + { + q_direction->band_data[idx_subband].azimuth_fx[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + } + ELSE + { + /* min removed GR coding */ + /* read GR_order */ + byteBuffer = bitstream[bit_pos--]; + /* read min index value */ + maximum_s( q_direction->band_data[idx_subband].azimuth_m_alphabet, masa_subframes, &max_val ); + min_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, max_val, MASA_GR_ORD_AZ ); + + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[idx_subband].bits_sph_idx[k] > 0 ) + { + IF( no_phi_masa[q_direction->band_data[idx_subband].bits_sph_idx[k] - 1][q_direction->band_data[idx_subband].elevation_index[k]] > 1 ) + { + q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - 1 - byteBuffer ); + q_direction->band_data[idx_subband].azimuth_index[k] += min_idx; + q_direction->band_data[idx_subband].azimuth_fx[k] = deindex_azimuth_fx( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); + } + ELSE + { + q_direction->band_data[idx_subband].azimuth_fx[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + ELSE + { + q_direction->band_data[idx_subband].azimuth_fx[k] = 0; + q_direction->band_data[idx_subband].azimuth_index[k] = 0; + } + } + } + } + } + + nbits = *pbit_pos - bit_pos; + + *pbit_pos = bit_pos; + + return nbits; +} +#endif + + +/*-------------------------------------------------------------------* + * decode_elevation() + * + * Reads the bitstream and decode the elevation index + *-------------------------------------------------------------------*/ + +/*! r: number of bits read */ +static int16_t decode_elevation( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + uint16_t *bitstream, /* i : input bitstream */ + int16_t *pbit_pos, /* i/o: current position to be read in bitstream*/ + const int16_t j, /* i : subband index */ + const int16_t masa_subframes /* i : number of tiles */ +) +{ + int16_t nr_NO_INDEX, nbits; + int16_t bit_pos; + uint16_t byteBuffer; + int16_t k, GR_ord_elevation; + uint16_t same_idx; + + nr_NO_INDEX = 0; + nbits = 0; + bit_pos = *pbit_pos; + + for ( k = 0; k < masa_subframes; k++ ) + { + q_direction->band_data[j].elevation_index[k] = 0; + q_direction->band_data[j].elevation[k] = 0; + + if ( q_direction->band_data[j].bits_sph_idx[k] > 0 ) + { + if ( q_direction->band_data[j].bits_sph_idx[k] <= 2 ) + { + q_direction->band_data[j].elevation_index[k] = MASA_NO_INDEX; + nr_NO_INDEX += 1; + q_direction->band_data[j].elevation[k] = 0; + q_direction->band_data[j].elevation_m_alphabet[k] = 1; + } + else + { + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[q_direction->band_data[j].bits_sph_idx[k] - 3]; + } + else + { + q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[q_direction->band_data[j].bits_sph_idx[k] - 3] * 2 - 1; + } + } + } + else + { + nr_NO_INDEX++; + } + } + + if ( nr_NO_INDEX < masa_subframes ) + { + { + /* read if same or not */ + byteBuffer = bitstream[bit_pos--]; + if ( byteBuffer == 1 ) /* same value */ + { + /* read value */ + byteBuffer = bitstream[bit_pos--]; + byteBuffer = ( byteBuffer << 1 ) + bitstream[bit_pos--]; + same_idx = byteBuffer; + + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) + { + q_direction->band_data[j].elevation_index[k] = same_idx; + q_direction->band_data[j].elevation[k] = deindex_elevation( &q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].bits_sph_idx[k], q_direction->cfg.mc_ls_setup ); + } + } + } + else + { + /* not same; decode mean removed GR */ + byteBuffer = bitstream[bit_pos--]; + GR_ord_elevation = MASA_GR_ORD_EL - byteBuffer; + + for ( k = 0; k < masa_subframes; k++ ) + { + if ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) + { + q_direction->band_data[j].elevation_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[j].elevation_m_alphabet[k], GR_ord_elevation ); + q_direction->band_data[j].elevation[k] = deindex_elevation( &q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].bits_sph_idx[k], q_direction->cfg.mc_ls_setup ); + } + } + } + } + } + + for ( k = 0; k < masa_subframes; k++ ) + { + if ( ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) && + ( no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][q_direction->band_data[j].elevation_index[k]] <= 1 ) ) + { + q_direction->band_data[j].azimuth_index[k] = MASA_NO_INDEX; + q_direction->band_data[j].azimuth_m_alphabet[k] = 1; + } + else + { + q_direction->band_data[j].azimuth_index[k] = 0; + if ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) + { + q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][q_direction->band_data[j].elevation_index[k]]; + } + else + { + q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][0]; + q_direction->band_data[j].elevation_index[k] = 0; + } + } + } + + nbits = *pbit_pos - bit_pos; + *pbit_pos = bit_pos; + + return nbits; +} + +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_elevation_fx( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + UWord16 *bitstream, /* i : input bitstream */ + Word16 *pbit_pos, /* i/o: current position to be read in bitstream*/ + const Word16 j, /* i : subband index */ + const Word16 masa_subframes /* i : number of tiles */ +) +{ + Word16 nr_NO_INDEX, nbits; + Word16 bit_pos; + UWord16 byteBuffer; + Word16 k, GR_ord_elevation; + UWord16 same_idx; + + nr_NO_INDEX = 0; + nbits = 0; + bit_pos = *pbit_pos; + + FOR( k = 0; k < masa_subframes; k++ ) + { + q_direction->band_data[j].elevation_index[k] = 0; + q_direction->band_data[j].elevation_fx[k] = 0; + + IF( q_direction->band_data[j].bits_sph_idx[k] > 0 ) + { + IF( q_direction->band_data[j].bits_sph_idx[k] <= 2 ) + { + q_direction->band_data[j].elevation_index[k] = MASA_NO_INDEX; + nr_NO_INDEX += 1; + q_direction->band_data[j].elevation_fx[k] = 0; + q_direction->band_data[j].elevation_m_alphabet[k] = 1; + } + ELSE + { + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[q_direction->band_data[j].bits_sph_idx[k] - 3]; + } + ELSE + { + q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[q_direction->band_data[j].bits_sph_idx[k] - 3] * 2 - 1; + } + } + } + ELSE + { + nr_NO_INDEX++; + } + } + + IF( nr_NO_INDEX < masa_subframes ) + { + { + /* read if same or not */ + byteBuffer = bitstream[bit_pos--]; + IF( byteBuffer == 1 ) /* same value */ + { + /* read value */ + byteBuffer = bitstream[bit_pos--]; + byteBuffer = ( byteBuffer << 1 ) + bitstream[bit_pos--]; + same_idx = byteBuffer; + + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) + { + q_direction->band_data[j].elevation_index[k] = same_idx; + q_direction->band_data[j].elevation_fx[k] = deindex_elevation_fx( &q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].bits_sph_idx[k], q_direction->cfg.mc_ls_setup ); + } + } + } + ELSE + { + /* not same; decode mean removed GR */ + byteBuffer = bitstream[bit_pos--]; + GR_ord_elevation = MASA_GR_ORD_EL - byteBuffer; + + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) + { + q_direction->band_data[j].elevation_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[j].elevation_m_alphabet[k], GR_ord_elevation ); + q_direction->band_data[j].elevation_fx[k] = deindex_elevation_fx( &q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].bits_sph_idx[k], q_direction->cfg.mc_ls_setup ); + } + } + } + } + } + + FOR( k = 0; k < masa_subframes; k++ ) + { + IF( ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) && + ( no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][q_direction->band_data[j].elevation_index[k]] <= 1 ) ) + { + q_direction->band_data[j].azimuth_index[k] = MASA_NO_INDEX; + q_direction->band_data[j].azimuth_m_alphabet[k] = 1; + } + ELSE + { + q_direction->band_data[j].azimuth_index[k] = 0; + IF( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) + { + q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][q_direction->band_data[j].elevation_index[k]]; + } + ELSE + { + q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][0]; + q_direction->band_data[j].elevation_index[k] = 0; + } + } + } + + nbits = *pbit_pos - bit_pos; + *pbit_pos = bit_pos; + + return nbits; +} +#endif + +/*---------------------------------------------------------------- + * decode_fixed_rate() + * + * decoding in fixed rate case, i.e. when using the spherical indexes + *-----------------------------------------------------------------*/ + +/*! r: number of bits read */ +static int16_t decode_fixed_rate( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata */ + const uint16_t *bitstream, /* i : bitstream to be read */ + int16_t *pbit_pos, /* i/o: position in bitstream */ + const int16_t b, /* i : subband index */ + const int16_t nblocks /* i : number of tiles in subband */ ) { - int16_t i, bits; - uint16_t tresh, value; + int16_t nbits, m, i; + uint16_t value; + nbits = 0; - bits = 30 - norm_l( alphabet_size ); /* bits = floor(log2(alphabet_size)) */ - tresh = ( 1U << ( bits + 1 ) ) - alphabet_size; + for ( m = 0; m < nblocks; m++ ) + { + value = 0; + for ( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) + { + value = ( value << 1 ) + bitstream[( *pbit_pos )--]; + } - value = 0; - for ( i = 0; i < bits; i++ ) + q_direction->band_data[b].spherical_index[m] = value; + nbits += q_direction->band_data[b].bits_sph_idx[m]; + + deindex_spherical_component( q_direction->band_data[b].spherical_index[m], &q_direction->band_data[b].azimuth[m], &q_direction->band_data[b].elevation[m], &q_direction->band_data[b].azimuth_index[m], &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + } + + return nbits; +} + +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_fixed_rate_fx( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata */ + const UWord16 *bitstream, /* i : bitstream to be read */ + Word16 *pbit_pos, /* i/o: position in bitstream */ + const Word16 b, /* i : subband index */ + const Word16 nblocks /* i : number of tiles in subband */ +) +{ + Word16 nbits, m, i; + UWord16 value; + + nbits = 0; + + FOR( m = 0; m < nblocks; m++ ) { - value = ( value << 1 ) + bitstream[( *index )--]; + value = 0; + FOR( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) + { + value = ( value << 1 ) + bitstream[( *pbit_pos )--]; + } + + q_direction->band_data[b].spherical_index[m] = value; + nbits += q_direction->band_data[b].bits_sph_idx[m]; + + deindex_spherical_component_fx( q_direction->band_data[b].spherical_index[m], &q_direction->band_data[b].azimuth_fx[m], &q_direction->band_data[b].elevation_fx[m], &q_direction->band_data[b].azimuth_index[m], &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); } - if ( value >= tresh ) + return nbits; +} +#endif +/*-------------------------------------------------------------------* + * decode_azimuth2D() + * + * Azimuth bitstream reading and decoding in 2D case + *-------------------------------------------------------------------*/ + +/*! r: number of bits read */ +static int16_t decode_azimuth2D( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + uint16_t *bitstream, /* i : bitstream to be read */ + const int16_t coding_subbands, /* i : number of subbands */ + int16_t *pbit_pos, + const int16_t no_frames ) +{ + int16_t i, j, k; + int16_t allowed_bits, nbits; + int16_t use_vq; + uint16_t Buffer; + int16_t bit_pos; + int16_t *bits_dir0; + + bit_pos = *pbit_pos; + nbits = 0; + for ( j = 0; j < coding_subbands; j++ ) { - value = ( value << 1 ) - tresh + bitstream[( *index )--]; + bits_dir0 = (int16_t *) q_direction->band_data[j].bits_sph_idx; + allowed_bits = sum_s( bits_dir0, no_frames ); + + if ( allowed_bits > 0 ) + { + use_vq = 0; + for ( k = 0; k < no_frames; k++ ) + { + q_direction->band_data[j].elevation[k] = 0; + q_direction->band_data[j].elevation_index[k] = 0; + + if ( bits_dir0[k] > use_vq ) + { + use_vq = bits_dir0[k]; + } + } + + if ( use_vq <= 3 && allowed_bits <= 11 ) + { + if ( allowed_bits <= no_frames + 1 ) + { + set_f( q_direction->band_data[j].azimuth, 0.0f, no_frames ); + for ( k = 0; k < min( allowed_bits, no_frames ); k++ ) + { + q_direction->band_data[j].azimuth[k] = ( -180.f ) * bitstream[bit_pos--]; + nbits += 1; + } + } + else + { + nbits += read_truncGR_azimuth( bitstream, q_direction, j, no_frames, &bit_pos ); + } + } + else + { + for ( k = 0; k < no_frames; k++ ) + { + Buffer = 0; + for ( i = 0; i < bits_dir0[k]; i++ ) + { + Buffer = ( Buffer << 1 ) + bitstream[bit_pos--]; + } + + nbits += bits_dir0[k]; + + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + q_direction->band_data[j].azimuth[k] = 360.0f / (float) ( 1 << bits_dir0[k] ) * Buffer - 180; + q_direction->band_data[j].azimuth[k] = companding_azimuth( q_direction->band_data[j].azimuth[k], q_direction->cfg.mc_ls_setup, + ( q_direction->band_data[j].elevation[k] > MC_MASA_THR_ELEVATION ), -1 ); + } + else + { + q_direction->band_data[j].azimuth[k] = 360.0f / (float) ( 1 << bits_dir0[k] ) * Buffer - 180; + } + } + } + } + else + { + set_zero_direction( q_direction, j, no_frames ); + } } + *pbit_pos = bit_pos; - return value; + return nbits; } +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_azimuth2D_fx( + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + UWord16 *bitstream, /* i : bitstream to be read */ + const Word16 coding_subbands, /* i : number of subbands */ + Word16 *pbit_pos, + const Word16 no_frames ) +{ + Word16 i, j, k; + Word16 allowed_bits, nbits; + Word16 use_vq; + UWord16 Buffer; + Word16 bit_pos; + Word16 *bits_dir0; -/*------------------------------------------------------------------------- - * ivas_qmetadata_DecodeExtendedGR() + bit_pos = *pbit_pos; + nbits = 0; + FOR( j = 0; j < coding_subbands; j++ ) + { + bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx; + allowed_bits = sum_s( bits_dir0, no_frames ); + + IF( allowed_bits > 0 ) + { + use_vq = 0; + FOR( k = 0; k < no_frames; k++ ) + { + q_direction->band_data[j].elevation_fx[k] = 0; + q_direction->band_data[j].elevation_index[k] = 0; + + IF( bits_dir0[k] > use_vq ) + { + use_vq = bits_dir0[k]; + } + } + + IF( use_vq <= 3 && allowed_bits <= 11 ) + { + IF( allowed_bits <= no_frames + 1 ) + { + set_l( q_direction->band_data[j].azimuth_fx, 0, no_frames ); + FOR( k = 0; k < min( allowed_bits, no_frames ); k++ ) + { + q_direction->band_data[j].azimuth_fx[k] = L_shl( -180 * bitstream[bit_pos--], 22 ); + nbits += 1; + } + } + ELSE + { + nbits += read_truncGR_azimuth_fx( bitstream, q_direction, j, no_frames, &bit_pos ); + } + } + ELSE + { + FOR( k = 0; k < no_frames; k++ ) + { + Buffer = 0; + FOR( i = 0; i < bits_dir0[k]; i++ ) + { + Buffer = ( Buffer << 1 ) + bitstream[bit_pos--]; + } + + nbits += bits_dir0[k]; + + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + q_direction->band_data[j].azimuth_fx[k] = L_shl( 360, 22 - bits_dir0[k] ) * Buffer - L_shl( 180, 22 ); + q_direction->band_data[j].azimuth_fx[k] = companding_azimuth_fx( q_direction->band_data[j].azimuth_fx[k], q_direction->cfg.mc_ls_setup, + ( q_direction->band_data[j].elevation_fx[k] > MC_MASA_THR_ELEVATION * ( 1 << 22 ) ), -1 ); + } + ELSE + { + q_direction->band_data[j].azimuth_fx[k] = L_shl( 360, 22 - bits_dir0[k] ) * Buffer - L_shl( 180, 22 ); + } + } + } + } + ELSE + { + set_zero_direction_fx( q_direction, j, no_frames ); + } + } + *pbit_pos = bit_pos; + + return nbits; +} +#endif + +/*-------------------------------------------------------------------* + * set_zero_direction() * - * Reads the bitstream and decodes the value using the ExtendedGR algorithm - *------------------------------------------------------------------------*/ + * + *-------------------------------------------------------------------*/ -/*! r: Value decoded from the bitstream */ -int16_t ivas_qmetadata_DecodeExtendedGR( - uint16_t *bitstream, /* i : pointer to the bitstream to read */ - int16_t *index, /* i/o: position in the bitstream to start reading (gets updated with reading) */ - const int16_t alph_size, /* i : size of the alphabet, used to calculate the number of bits needed */ - const int16_t gr_param /* i : GR parameter that indicates the limit for the most significant bits (msb) */ +static void set_zero_direction( + IVAS_QDIRECTION *q_direction, + const int16_t idx_band, + const int16_t len ) +{ + int16_t k; + + for ( k = 0; k < len; k++ ) + { + q_direction->band_data[idx_band].azimuth[k] = 0; + q_direction->band_data[idx_band].azimuth_index[k] = 0; + q_direction->band_data[idx_band].elevation[k] = 0; + q_direction->band_data[idx_band].elevation_index[k] = 0; + q_direction->band_data[idx_band].spherical_index[k] = 0; + } + + return; +} + +#ifdef IVAS_FLOAT_FIXED +static void set_zero_direction_fx( + IVAS_QDIRECTION *q_direction, + const Word16 idx_band, + const Word16 len ) +{ + Word16 k; + + FOR( k = 0; k < len; k++ ) + { + q_direction->band_data[idx_band].azimuth_fx[k] = 0; + q_direction->band_data[idx_band].azimuth_index[k] = 0; + q_direction->band_data[idx_band].elevation_fx[k] = 0; + q_direction->band_data[idx_band].elevation_index[k] = 0; + q_direction->band_data[idx_band].spherical_index[k] = 0; + } + + return; +} +#endif + + +/*-------------------------------------------------------------------* + * read_truncGR_azimuth() + * + * + *-------------------------------------------------------------------*/ + +static int16_t read_truncGR_azimuth( + uint16_t *bitstream, /* i : bitstream to be read */ + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + const int16_t j, /* i : subband index */ + const int16_t no_subframes, /* i : number of tiles */ + int16_t *pbit_pos /* i/o: position in bitstream */ ) { - int16_t i, msb_size; - uint16_t value; - int16_t msb, lsb; + int16_t i; + int16_t nbits; + uint16_t idx; + int16_t no_symb, allowed_bits; - msb_size = ( alph_size + ( 1 << gr_param ) - 1 ) >> gr_param; /* ceil division */ - if ( msb_size <= 3 ) + allowed_bits = sum_s( (int16_t *) q_direction->band_data[j].bits_sph_idx, no_subframes ); + nbits = 0; + if ( allowed_bits <= no_subframes + 1 ) { - value = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, alph_size ); + for ( i = 0; i < min( allowed_bits, no_subframes ); i++ ) + { + if ( bitstream[( *pbit_pos )--] == 0 ) + { + q_direction->band_data[j].azimuth[i] = 0.0f; + } + else + { + q_direction->band_data[j].azimuth[i] = -180; + } + nbits++; + } + + return nbits; + } + + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + { + no_symb = 9; } else { - msb = 0; - while ( ( msb < msb_size - 1 ) && ( bitstream[*index] != 0 ) ) - { - msb++; - ( *index )--; - } + no_symb = 8; + } + nbits = 0; - if ( msb == msb_size - 1 ) + nbits = *pbit_pos; + + for ( i = 0; i < no_subframes; i++ ) + { + idx = ivas_qmetadata_DecodeExtendedGR( bitstream, pbit_pos, no_symb, 0 ); + q_direction->band_data[j].azimuth_index[i] = idx; + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { - lsb = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, alph_size - ( ( msb_size - 1 ) << gr_param ) ); + q_direction->band_data[j].azimuth[i] = cb_azi_chan[( idx + 1 ) >> 1]; + if ( idx % 2 > 0 ) + { + q_direction->band_data[j].azimuth[i] = -q_direction->band_data[j].azimuth[i]; + } } else { - ( *index )--; - lsb = 0; - for ( i = 0; i < gr_param; i++ ) - { - lsb = ( lsb << 1 ) + bitstream[( *index )--]; - } + q_direction->band_data[j].azimuth[i] = azimuth_cb[idx]; } - - value = ( msb << gr_param ) + lsb; } - return value; -} - + nbits -= *pbit_pos; -/*------------------------------------------------------------------------- - * ivas_qmetadata_ReorderElevationDecoded() - * - * Calculates the correct elevation index from the decoded data - *------------------------------------------------------------------------*/ + return nbits; +} -/*! r: Elevation index as it will be read by the dequantizer */ -static int16_t ivas_qmetadata_ReorderElevationDecoded( - const int16_t elev_dist, /* i : Distance to the average extracted from the bitstream */ - const int16_t elev_avg, /* i : Average value over time-blocks extracted from the bitstream */ - const int16_t elev_alph /* i : elevation alphabet */ +#ifdef IVAS_FLOAT_FIXED +static Word16 read_truncGR_azimuth_fx( + UWord16 *bitstream, /* i : bitstream to be read */ + IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ + const Word16 j, /* i : subband index */ + const Word16 no_subframes, /* i : number of tiles */ + Word16 *pbit_pos /* i/o: position in bitstream */ ) { - int16_t dist_reorder; - int16_t elev_index_reorder; + Word16 i; + Word16 nbits; + UWord16 idx; + Word16 no_symb, allowed_bits; - dist_reorder = ivas_qmetadata_dereorder_generic( elev_dist ); - elev_index_reorder = elev_avg + dist_reorder; + allowed_bits = sum_s( (Word16 *) q_direction->band_data[j].bits_sph_idx, no_subframes ); + nbits = 0; + IF( allowed_bits <= no_subframes + 1 ) + { + FOR( i = 0; i < min( allowed_bits, no_subframes ); i++ ) + { + IF( bitstream[( *pbit_pos )--] == 0 ) + { + q_direction->band_data[j].azimuth_fx[i] = 0; + } + ELSE + { + q_direction->band_data[j].azimuth_fx[i] = L_shl( -180, 22 ); + } + nbits++; + } - if ( elev_index_reorder < 0 ) + return nbits; + } + + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { - elev_index_reorder += elev_alph; + no_symb = 9; } - else if ( elev_index_reorder >= elev_alph ) + ELSE { - elev_index_reorder -= elev_alph; + no_symb = 8; } + nbits = 0; - return elev_index_reorder; -} - - -/*-----------------------------------------------------------------------* - * Local functions: requentizeEC3 - *-----------------------------------------------------------------------*/ - -/*! r: number of bits read */ -static int16_t read_directions( - IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ - const uint8_t coding_subbands, /* i : number of directions */ - const uint8_t masa_subframes, /* i : number of tiles */ - uint16_t *bitstream, /* i : bitstream to be read */ - int16_t *pbit_pos, - int16_t *ind_order ) -{ - int16_t j, k, allowed_bits, last_j, nbits, fixed_rate; - int16_t i; - int16_t diff; - uint16_t byteBuffer; - int16_t use_vq, max_nb_idx; - int16_t bit_pos; - int16_t *bits_dir0; - - bit_pos = *pbit_pos; + nbits = *pbit_pos; - diff = 0; - if ( q_direction->not_in_2D ) + FOR( i = 0; i < no_subframes; i++ ) { - if ( coding_subbands > 1 ) + idx = ivas_qmetadata_DecodeExtendedGR( bitstream, pbit_pos, no_symb, 0 ); + q_direction->band_data[j].azimuth_index[i] = idx; + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { - j = ind_order[coding_subbands - 1]; - allowed_bits = 0; - - for ( k = 0; k < masa_subframes; k++ ) + q_direction->band_data[j].azimuth_fx[i] = cb_azi_chan_fx[( idx + 1 ) >> 1]; + IF( idx % 2 > 0 ) { - allowed_bits += q_direction->band_data[j].bits_sph_idx[k]; + q_direction->band_data[j].azimuth_fx[i] = -q_direction->band_data[j].azimuth_fx[i]; } + } + ELSE + { + q_direction->band_data[j].azimuth_fx[i] = azimuth_cb_fx[idx]; + } + } - last_j = j - ( allowed_bits == 0 ); + nbits -= *pbit_pos; - for ( j = 0; j < last_j; j++ ) - { - i = ind_order[j]; - bits_dir0 = (int16_t *) q_direction->band_data[i].bits_sph_idx; + return nbits; +} +#endif - nbits = 0; - allowed_bits = sum_s( bits_dir0, q_direction->cfg.nblocks ); - use_vq = 0; - max_nb_idx = 0; +/*-------------------------------------------------------------------* + * read_common_direction() + * + * + *-------------------------------------------------------------------*/ - for ( k = 0; k < q_direction->cfg.nblocks; k++ ) - { - if ( bits_dir0[k] > use_vq ) - { - use_vq = bits_dir0[k]; - max_nb_idx = k; - } - } +/*! r: number of bits read */ +static int16_t read_common_direction( + uint16_t *bitstream, /* i : bitstream to be read */ + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + const int16_t j, /* i : subband index */ + const int16_t no_subframes, /* i : number of tiles */ + const int16_t bits_total, /* i : number of bits for subband directional data */ + int16_t *pbit_pos /* i/o: position in bitstream */ +) +{ + int16_t nbits; + int16_t bit_pos; + int16_t i; + uint16_t byteBuffer; + int16_t bits_el; - if ( q_direction->cfg.nblocks == 1 ) - { - byteBuffer = 0; - } - else - { - byteBuffer = 0; - if ( use_vq <= 1 ) - { - byteBuffer = 1; - } - if ( use_vq > 1 && use_vq <= LIMIT_USE_COMMON ) - { - bits_dir0[max_nb_idx] -= 1; - allowed_bits -= 1; - /* read 1 bit to tell if joint of VQ coding */ - byteBuffer = bitstream[bit_pos--]; - } - } + bit_pos = *pbit_pos; + nbits = 0; - for ( k = 0; k < masa_subframes; k++ ) - { - q_direction->band_data[i].bits_sph_idx[k] = bits_dir0[k]; - if ( bits_dir0[k] > 2 ) - { - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) - { - q_direction->band_data[i].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3]; - } - else - { - q_direction->band_data[i].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3] * 2 - 1; - } - } - else - { - q_direction->band_data[i].elevation_m_alphabet[k] = 1; - } - } + set_zero_direction( q_direction, j, no_subframes ); + if ( bits_total == 0 ) + { + return nbits; + } - if ( allowed_bits > 0 ) - { - if ( byteBuffer == 1 ) - { - nbits = read_common_direction( bitstream, q_direction, i, masa_subframes, allowed_bits, &bit_pos ); - } - else - { - if ( q_direction->cfg.nblocks == 1 && q_direction->band_data[i].bits_sph_idx[0] <= MASA_MIN_BITS_TF + 1 ) - { - /* there is fixed rate only, no need to read */ - fixed_rate = 1; - nbits = 0; - } - else - { - /* check if fixed_rate */ - fixed_rate = bitstream[bit_pos--]; - nbits = 1; - } + if ( bits_total <= no_subframes + 1 ) + { + for ( i = 0; i < min( no_subframes, bits_total ); i++ ) + { + byteBuffer = bitstream[bit_pos--]; + /*qdirection->azimuth_index[j][i] = (uint16_t)byteBuffer; */ + q_direction->band_data[j].azimuth[i] = azimuth_cb[byteBuffer]; + nbits += 1; + } + *pbit_pos = bit_pos; - if ( fixed_rate == 1 ) - { - /* decode_fixed_rate()*/ - nbits += decode_fixed_rate( q_direction, bitstream, &bit_pos, i, masa_subframes ); - } - else - { - /* decode elevation */ - nbits += decode_elevation( q_direction, bitstream, &bit_pos, i, masa_subframes ); + /*nbits += read_truncGR_azimuth(bitstream, qdirection, j, no_subframes, pbit_pos); */ + return nbits; + } - /* decode azimuth */ - nbits += decode_azimuth( q_direction, bitstream, &bit_pos, i, masa_subframes ); - } - } - } - else - { - set_zero_direction( q_direction, i, masa_subframes ); - } - diff += nbits - allowed_bits; - /* update bits for next block */ - update_bits_next_block( q_direction, &diff, ind_order[j + 1], coding_subbands, masa_subframes ); + byteBuffer = bitstream[bit_pos--]; + bits_el = 1; + nbits += 1; + /* elevation is already set to 0*/ + if ( byteBuffer == 1 ) + { + byteBuffer = bitstream[bit_pos--]; + bits_el += 1; + nbits += 1; + if ( byteBuffer == 0 ) + { + for ( i = 0; i < no_subframes; i++ ) + { + q_direction->band_data[j].elevation[i] = delta_theta_masa[2]; } } else { - last_j = q_direction->cfg.start_band; - } - - - for ( j = last_j; j < coding_subbands; j++ ) - { - i = ind_order[j]; - bits_dir0 = (int16_t *) q_direction->band_data[i].bits_sph_idx; - - nbits = 0; - allowed_bits = sum_s( bits_dir0, q_direction->cfg.nblocks ); - if ( allowed_bits > 0 && masa_subframes == 1 ) + byteBuffer = bitstream[bit_pos--]; + bits_el += 1; + nbits += 1; + if ( byteBuffer == 0 ) { - nbits += decode_fixed_rate( q_direction, bitstream, &bit_pos, i, masa_subframes ); + for ( i = 0; i < no_subframes; i++ ) + { + q_direction->band_data[j].elevation[i] = -delta_theta_masa[2]; + } } else { - if ( allowed_bits > 0 ) + /* theta is +/- 90; no azimuth is read */ + byteBuffer = bitstream[bit_pos--]; + nbits += 1; + if ( byteBuffer == 0 ) { - use_vq = 0; - max_nb_idx = 0; - for ( k = 0; k < masa_subframes; k++ ) - { - if ( bits_dir0[k] > use_vq ) - { - use_vq = bits_dir0[k]; - max_nb_idx = k; - } - } - - byteBuffer = 0; - - if ( use_vq > 1 && use_vq <= LIMIT_USE_COMMON ) - { - bits_dir0[max_nb_idx] -= 1; - allowed_bits -= 1; - - /* read 1 bit to tell if joint of VQ coding */ - byteBuffer = bitstream[bit_pos--]; - } - - if ( allowed_bits > 0 ) - { - if ( byteBuffer == 1 || use_vq <= 1 ) - { - nbits = read_common_direction( bitstream, q_direction, i, masa_subframes, allowed_bits, &bit_pos ); - } - else - { - /* decode_fixed_rate()*/ - nbits += decode_fixed_rate( q_direction, bitstream, &bit_pos, i, masa_subframes ); - } - } - else - { - set_zero_direction( q_direction, i, masa_subframes ); - } + set_f( q_direction->band_data[j].elevation, 90.0f, no_subframes ); + set_f( q_direction->band_data[j].azimuth, 0.0f, no_subframes ); } else { - set_zero_direction( q_direction, i, masa_subframes ); + set_f( q_direction->band_data[j].elevation, -90.0f, no_subframes ); + set_f( q_direction->band_data[j].azimuth, 0.0f, no_subframes ); } + *pbit_pos = bit_pos; + + return nbits; } } } - else + + bits_el = sum_s( (int16_t *) q_direction->band_data[j].bits_sph_idx, no_subframes ) - bits_el; + + if ( bits_el <= no_subframes + 1 ) { - /* 2D */ - for ( j = 0; j < coding_subbands; j++ ) + nbits += min( no_subframes, bits_el ); + for ( i = 0; i < min( no_subframes, bits_el ); i++ ) { - for ( k = 0; k < q_direction->cfg.nblocks; k++ ) - { - q_direction->band_data[j].elevation[k] = 0; - q_direction->band_data[j].elevation_index[k] = 0; - } + byteBuffer = bitstream[bit_pos--]; + /*qdirection->azimuth_index[j][i] = (uint16_t) byteBuffer; */ + q_direction->band_data[j].azimuth[i] = azimuth_cb[byteBuffer]; } - nbits = decode_azimuth2D( q_direction, bitstream, coding_subbands, &bit_pos, masa_subframes ); } - nbits = *pbit_pos - bit_pos; + else + { + nbits += read_truncGR_azimuth( bitstream, q_direction, j, no_subframes, &bit_pos ); + } + *pbit_pos = bit_pos; return nbits; } - -/*-------------------------------------------------------------------* - * decode_azimuth() - * - * read and decode the azimuth indexes for one subband - *-------------------------------------------------------------------*/ - -/*! r: number of bits read */ -static int16_t decode_azimuth( - IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ - uint16_t *bitstream, /* i : bitstream to be read */ - int16_t *pbit_pos, /* i/o: current position in bitstream */ - const int16_t idx_subband, /* i : subband index */ - const int16_t masa_subframes /* i : number of tiles */ +#ifdef IVAS_FLOAT_FIXED +static Word16 read_common_direction_fx( + UWord16 *bitstream, /* i : bitstream to be read */ + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + const Word16 j, /* i : subband index */ + const Word16 no_subframes, /* i : number of tiles */ + const Word16 bits_total, /* i : number of bits for subband directional data */ + Word16 *pbit_pos /* i/o: position in bitstream */ ) { - int16_t bit_pos, nbits, k; - uint16_t use_context, byteBuffer; - uint16_t min_idx; - int16_t j_az, max_val; + Word16 nbits; + Word16 bit_pos; + Word16 i; + UWord16 byteBuffer; + Word16 bits_el; - nbits = 0; bit_pos = *pbit_pos; - byteBuffer = 0; - - j_az = 0; - /* check number of valid indexes to decode */ - for ( k = 0; k < masa_subframes; k++ ) - { - if ( q_direction->band_data[idx_subband].azimuth_index[k] < MASA_NO_INDEX ) - { - j_az++; - } - else - { - q_direction->band_data[idx_subband].azimuth[k] = 0.f; /*To be in sync with encoder values.*/ - } - } + nbits = 0; - if ( j_az == 0 ) + set_zero_direction_fx( q_direction, j, no_subframes ); + IF( bits_total == 0 ) { return nbits; } - if ( byteBuffer == 0 ) + IF( bits_total <= no_subframes + 1 ) { - /* use context */ - use_context = 0; - for ( k = 0; k < masa_subframes; k++ ) + FOR( i = 0; i < min( no_subframes, bits_total ); i++ ) { - if ( q_direction->band_data[idx_subband].bits_sph_idx[k] <= 1 ) - { - use_context = 1; - } + byteBuffer = bitstream[bit_pos--]; + /*qdirection->azimuth_index[j][i] = (uint16_t)byteBuffer; */ + q_direction->band_data[j].azimuth_fx[i] = azimuth_cb_fx[byteBuffer]; + nbits += 1; } + *pbit_pos = bit_pos; - if ( use_context == 1 ) - { - for ( k = 0; k < masa_subframes; k++ ) - { - if ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 0 ) - { - q_direction->band_data[idx_subband].azimuth_index[k] = 0; - q_direction->band_data[idx_subband].azimuth[k] = 0; - } - else - { - if ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 1 ) - { - byteBuffer = bitstream[bit_pos--]; - q_direction->band_data[idx_subband].azimuth_index[k] = byteBuffer; + /*nbits += read_truncGR_azimuth(bitstream, qdirection, j, no_subframes, pbit_pos); */ + return nbits; + } - q_direction->band_data[idx_subband].azimuth[k] = q_direction->band_data[idx_subband].azimuth_index[k] * ( -180.f ); - } - else - { - q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - ( q_direction->band_data[idx_subband].bits_sph_idx[k] == 2 ) ); - q_direction->band_data[idx_subband].azimuth[k] = deindex_azimuth( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); - } - } + byteBuffer = bitstream[bit_pos--]; + bits_el = 1; + nbits += 1; + /* elevation is already set to 0*/ + IF( byteBuffer == 1 ) + { + byteBuffer = bitstream[bit_pos--]; + bits_el += 1; + nbits += 1; + IF( byteBuffer == 0 ) + { + FOR( i = 0; i < no_subframes; i++ ) + { + q_direction->band_data[j].elevation_fx[i] = delta_theta_masa_fx[2]; } } - else + ELSE { - /* read bit to check if min removed encoding */ byteBuffer = bitstream[bit_pos--]; - if ( byteBuffer == 0 ) /* regular GR coding5 */ + bits_el += 1; + nbits += 1; + IF( byteBuffer == 0 ) { - /* read GR_order */ - byteBuffer = bitstream[bit_pos--]; - nbits += 1; - - for ( k = 0; k < masa_subframes; k++ ) + FOR( i = 0; i < no_subframes; i++ ) { - if ( q_direction->band_data[idx_subband].bits_sph_idx[k] > 0 ) - { - if ( no_phi_masa[q_direction->band_data[idx_subband].bits_sph_idx[k] - 1][q_direction->band_data[idx_subband].elevation_index[k]] > 1 ) - { - q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - byteBuffer ); - q_direction->band_data[idx_subband].azimuth[k] = deindex_azimuth( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); - } - else - { - q_direction->band_data[idx_subband].azimuth[k] = 0; - q_direction->band_data[idx_subband].azimuth_index[k] = 0; - } - } - else - { - q_direction->band_data[idx_subband].azimuth[k] = 0; - q_direction->band_data[idx_subband].azimuth_index[k] = 0; - } + q_direction->band_data[j].elevation_fx[i] = -delta_theta_masa_fx[2]; } } - else + ELSE { - /* min removed GR coding */ - /* read GR_order */ + /* theta is +/- 90; no azimuth is read */ byteBuffer = bitstream[bit_pos--]; - /* read min index value */ - maximum_s( q_direction->band_data[idx_subband].azimuth_m_alphabet, masa_subframes, &max_val ); - min_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, max_val, MASA_GR_ORD_AZ ); - - for ( k = 0; k < masa_subframes; k++ ) + nbits += 1; + IF( byteBuffer == 0 ) { - if ( q_direction->band_data[idx_subband].bits_sph_idx[k] > 0 ) - { - if ( no_phi_masa[q_direction->band_data[idx_subband].bits_sph_idx[k] - 1][q_direction->band_data[idx_subband].elevation_index[k]] > 1 ) - { - q_direction->band_data[idx_subband].azimuth_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[idx_subband].azimuth_m_alphabet[k], MASA_GR_ORD_AZ - 1 - byteBuffer ); - q_direction->band_data[idx_subband].azimuth_index[k] += min_idx; - q_direction->band_data[idx_subband].azimuth[k] = deindex_azimuth( q_direction->band_data[idx_subband].azimuth_index[k], q_direction->band_data[idx_subband].bits_sph_idx[k], q_direction->band_data[idx_subband].elevation_index[k], 1, q_direction->cfg.mc_ls_setup ); - } - else - { - q_direction->band_data[idx_subband].azimuth[k] = 0; - q_direction->band_data[idx_subband].azimuth_index[k] = 0; - } - } - else - { - q_direction->band_data[idx_subband].azimuth[k] = 0; - q_direction->band_data[idx_subband].azimuth_index[k] = 0; - } + set32_fx( q_direction->band_data[j].elevation_fx, 90 << 22, no_subframes ); + set32_fx( q_direction->band_data[j].azimuth_fx, 0, no_subframes ); + } + ELSE + { + set32_fx( q_direction->band_data[j].elevation_fx, -90.0f, no_subframes ); + set32_fx( q_direction->band_data[j].azimuth_fx, 0.0f, no_subframes ); } + *pbit_pos = bit_pos; + + return nbits; } } } - nbits = *pbit_pos - bit_pos; + bits_el = sum_s( (Word16 *) q_direction->band_data[j].bits_sph_idx, no_subframes ) - bits_el; + + IF( bits_el <= no_subframes + 1 ) + { + nbits += min( no_subframes, bits_el ); + FOR( i = 0; i < min( no_subframes, bits_el ); i++ ) + { + byteBuffer = bitstream[bit_pos--]; + /*qdirection->azimuth_index[j][i] = (uint16_t) byteBuffer; */ + q_direction->band_data[j].azimuth_fx[i] = azimuth_cb_fx[byteBuffer]; + } + } + ELSE + { + nbits += read_truncGR_azimuth_fx( bitstream, q_direction, j, no_subframes, &bit_pos ); + } *pbit_pos = bit_pos; return nbits; } +#endif +/*-----------------------------------------------------------------------* + * Local functions: coherence + *-----------------------------------------------------------------------*/ -/*-------------------------------------------------------------------* - * decode_elevation() - * - * Reads the bitstream and decode the elevation index - *-------------------------------------------------------------------*/ - -/*! r: number of bits read */ -static int16_t decode_elevation( - IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ - uint16_t *bitstream, /* i : input bitstream */ - int16_t *pbit_pos, /* i/o: current position to be read in bitstream*/ - const int16_t j, /* i : subband index */ - const int16_t masa_subframes /* i : number of tiles */ +static void decode_spread_coherence( + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: quantized metadata structure */ + int16_t idx_d, /* i : direction index */ + const int16_t no_frames, /* i : number of time subframes */ + const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding */ ) { - int16_t nr_NO_INDEX, nbits; - int16_t bit_pos; - uint16_t byteBuffer; - int16_t k, GR_ord_elevation; - uint16_t same_idx; - - nr_NO_INDEX = 0; - nbits = 0; - bit_pos = *pbit_pos; + int16_t i, j; + float var_azi; + int16_t idx_sub_cb; + float dct_coh[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t MASA_grouping[MASA_MAXIMUM_CODING_SUBBANDS]; + IVAS_QDIRECTION *q_direction; + int16_t coding_subbands, coding_subbands_0, d, two_dir_band[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t min_index; - for ( k = 0; k < masa_subframes; k++ ) + coding_subbands_0 = hQMetaData->q_direction[0].cfg.nbands; + coding_subbands = hQMetaData->q_direction[idx_d].cfg.nbands; + if ( coding_subbands_0 <= 5 ) { - q_direction->band_data[j].elevation_index[k] = 0; - q_direction->band_data[j].elevation[k] = 0; - - if ( q_direction->band_data[j].bits_sph_idx[k] > 0 ) + for ( j = 0; j < 5; j++ ) { - if ( q_direction->band_data[j].bits_sph_idx[k] <= 2 ) + MASA_grouping[j] = j; + } + } + else + { + if ( coding_subbands_0 <= 8 ) + { + mvs2s( MASA_grouping_8_to_5, MASA_grouping, 8 ); + } + else if ( coding_subbands_0 <= 12 ) + { + mvs2s( MASA_grouping_12_to_5, MASA_grouping, 12 ); + } + else if ( coding_subbands_0 <= 18 ) + { + mvs2s( MASA_grouping_18_to_5, MASA_grouping, 18 ); + } + else + { + if ( coding_subbands_0 <= 24 ) { - q_direction->band_data[j].elevation_index[k] = MASA_NO_INDEX; - nr_NO_INDEX += 1; - q_direction->band_data[j].elevation[k] = 0; - q_direction->band_data[j].elevation_m_alphabet[k] = 1; + mvs2s( MASA_grouping_24_to_5, MASA_grouping, 24 ); } - else + } + } + + if ( coding_subbands < coding_subbands_0 ) + { + d = 0; + for ( j = 0; j < coding_subbands_0; j++ ) + { + if ( hQMetaData->twoDirBands[j] == 1 ) { - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) - { - q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[q_direction->band_data[j].bits_sph_idx[k] - 3]; - } - else - { - q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[q_direction->band_data[j].bits_sph_idx[k] - 3] * 2 - 1; - } + two_dir_band[d++] = j; } } + } + else + { + set_s( two_dir_band, 0, coding_subbands ); + } + + q_direction = &hQMetaData->q_direction[idx_d]; + + for ( i = 0; i < coding_subbands; i++ ) + { + var_azi = var( q_direction->band_data[i].azimuth, no_frames ); + if ( hrmasa_flag ) + { + minimum_s( (int16_t *) ( q_direction->band_data[i].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); + min_index = min_index >> 1; + } else { - nr_NO_INDEX++; + min_index = q_direction->band_data[i].energy_ratio_index[0]; } - } - if ( nr_NO_INDEX < masa_subframes ) - { + if ( var_azi < MASA_DELTA_AZI_DCT0 ) { - /* read if same or not */ - byteBuffer = bitstream[bit_pos--]; - if ( byteBuffer == 1 ) /* same value */ - { - /* read value */ - byteBuffer = bitstream[bit_pos--]; - byteBuffer = ( byteBuffer << 1 ) + bitstream[bit_pos--]; - same_idx = byteBuffer; + idx_sub_cb = MASA_NO_CV_COH * min_index; + } + else + { + idx_sub_cb = MASA_NO_CV_COH * ( min_index + DIRAC_DIFFUSE_LEVELS ); /* NO_CV_COH = 8 */ + } - for ( k = 0; k < masa_subframes; k++ ) - { - if ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) - { - q_direction->band_data[j].elevation_index[k] = same_idx; - q_direction->band_data[j].elevation[k] = deindex_elevation( &q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].bits_sph_idx[k], q_direction->cfg.mc_ls_setup ); - } - } - } - else - { - /* not same; decode mean removed GR */ - byteBuffer = bitstream[bit_pos--]; - GR_ord_elevation = MASA_GR_ORD_EL - byteBuffer; + dct_coh[i][0] = coherence_cb0_masa[idx_sub_cb + q_direction->coherence_band_data[i].spread_coherence_dct0_index]; - for ( k = 0; k < masa_subframes; k++ ) - { - if ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) - { - q_direction->band_data[j].elevation_index[k] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, q_direction->band_data[j].elevation_m_alphabet[k], GR_ord_elevation ); - q_direction->band_data[j].elevation[k] = deindex_elevation( &q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].bits_sph_idx[k], q_direction->cfg.mc_ls_setup ); - } - } - } + if ( coding_subbands < coding_subbands_0 ) + { + assert( idx_d == 1 ); + dct_coh[i][1] = coherence_cb1_masa[MASA_grouping[two_dir_band[i]] * MASA_NO_CV_COH1 + q_direction->coherence_band_data[i].spread_coherence_dct1_index]; + } + else + { + dct_coh[i][1] = coherence_cb1_masa[MASA_grouping[i] * MASA_NO_CV_COH1 + q_direction->coherence_band_data[i].spread_coherence_dct1_index]; + } + + for ( j = 2; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + dct_coh[i][j] = 0; } + + invdct4_transform( dct_coh[i], q_direction->coherence_band_data[i].spread_coherence ); } - for ( k = 0; k < masa_subframes; k++ ) + return; +} + +#ifdef IVAS_FLOAT_FIXED +static void decode_spread_coherence_fx( + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: quantized metadata structure */ + Word16 idx_d, /* i : direction index */ + const Word16 no_frames, /* i : number of time subframes */ + const Word16 hrmasa_flag /* i : flag indicating high-rate MASA MD coding */ +) +{ + Word16 i, j; + Word64 var_azi_fx; + Word16 idx_sub_cb; + Word32 dct_coh_fx[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 MASA_grouping[MASA_MAXIMUM_CODING_SUBBANDS]; + IVAS_QDIRECTION *q_direction; + Word16 coding_subbands, coding_subbands_0, d, two_dir_band[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 min_index; + + coding_subbands_0 = hQMetaData->q_direction[0].cfg.nbands; + coding_subbands = hQMetaData->q_direction[idx_d].cfg.nbands; + IF( coding_subbands_0 <= 5 ) { - if ( ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) && - ( no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][q_direction->band_data[j].elevation_index[k]] <= 1 ) ) + FOR( j = 0; j < 5; j++ ) { - q_direction->band_data[j].azimuth_index[k] = MASA_NO_INDEX; - q_direction->band_data[j].azimuth_m_alphabet[k] = 1; + MASA_grouping[j] = j; } - else + } + ELSE + { + IF( coding_subbands_0 <= 8 ) { - q_direction->band_data[j].azimuth_index[k] = 0; - if ( q_direction->band_data[j].elevation_index[k] < MASA_NO_INDEX ) - { - q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][q_direction->band_data[j].elevation_index[k]]; - } - else + mvs2s( MASA_grouping_8_to_5, MASA_grouping, 8 ); + } + ELSE IF( coding_subbands_0 <= 12 ) + { + mvs2s( MASA_grouping_12_to_5, MASA_grouping, 12 ); + } + ELSE IF( coding_subbands_0 <= 18 ) + { + mvs2s( MASA_grouping_18_to_5, MASA_grouping, 18 ); + } + ELSE + { + IF( coding_subbands_0 <= 24 ) { - q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[q_direction->band_data[j].bits_sph_idx[k] - 1][0]; - q_direction->band_data[j].elevation_index[k] = 0; + mvs2s( MASA_grouping_24_to_5, MASA_grouping, 24 ); } } } - nbits = *pbit_pos - bit_pos; - *pbit_pos = bit_pos; - - return nbits; -} + IF( coding_subbands < coding_subbands_0 ) + { + d = 0; + FOR( j = 0; j < coding_subbands_0; j++ ) + { + IF( hQMetaData->twoDirBands[j] == 1 ) + { + two_dir_band[d++] = j; + } + } + } + ELSE + { + set_s( two_dir_band, 0, coding_subbands ); + } + q_direction = &hQMetaData->q_direction[idx_d]; -/*---------------------------------------------------------------- - * decode_fixed_rate() - * - * decoding in fixed rate case, i.e. when using the spherical indexes - *-----------------------------------------------------------------*/ + FOR( i = 0; i < coding_subbands; i++ ) + { + var_azi_fx = var_32_fx( q_direction->band_data[i].azimuth_fx, no_frames, 22 ); + IF( hrmasa_flag ) + { + minimum_s( (int16_t *) ( q_direction->band_data[i].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); + min_index = min_index >> 1; + } + ELSE + { + min_index = q_direction->band_data[i].energy_ratio_index[0]; + } -/*! r: number of bits read */ -static int16_t decode_fixed_rate( - IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata */ - const uint16_t *bitstream, /* i : bitstream to be read */ - int16_t *pbit_pos, /* i/o: position in bitstream */ - const int16_t b, /* i : subband index */ - const int16_t nblocks /* i : number of tiles in subband */ -) -{ - int16_t nbits, m, i; - uint16_t value; + IF( var_azi_fx < L_shl( MASA_DELTA_AZI_DCT0, 22 ) ) + { + idx_sub_cb = MASA_NO_CV_COH * min_index; + } + ELSE + { + idx_sub_cb = MASA_NO_CV_COH * ( min_index + DIRAC_DIFFUSE_LEVELS ); /* NO_CV_COH = 8 */ + } - nbits = 0; + dct_coh_fx[i][0] = coherence_cb0_masa_fx[idx_sub_cb + q_direction->coherence_band_data[i].spread_coherence_dct0_index]; - for ( m = 0; m < nblocks; m++ ) - { - value = 0; - for ( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) + IF( coding_subbands < coding_subbands_0 ) { - value = ( value << 1 ) + bitstream[( *pbit_pos )--]; + assert( idx_d == 1 ); + dct_coh_fx[i][1] = coherence_cb1_masa_fx[MASA_grouping[two_dir_band[i]] * MASA_NO_CV_COH1 + q_direction->coherence_band_data[i].spread_coherence_dct1_index]; + } + ELSE + { + dct_coh_fx[i][1] = coherence_cb1_masa_fx[MASA_grouping[i] * MASA_NO_CV_COH1 + q_direction->coherence_band_data[i].spread_coherence_dct1_index]; } - q_direction->band_data[b].spherical_index[m] = value; - nbits += q_direction->band_data[b].bits_sph_idx[m]; + FOR( j = 2; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + dct_coh_fx[i][j] = 0; + } - deindex_spherical_component( q_direction->band_data[b].spherical_index[m], &q_direction->band_data[b].azimuth[m], &q_direction->band_data[b].elevation[m], &q_direction->band_data[b].azimuth_index[m], &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); + invdct4_transform_fx( dct_coh_fx[i], q_direction->coherence_band_data[i].spread_coherence, 21 ); } - return nbits; + return; } - +#endif /*-------------------------------------------------------------------* - * decode_azimuth2D() + * read_huf() * - * Azimuth bitstream reading and decoding in 2D case + * Read Hufman code *-------------------------------------------------------------------*/ /*! r: number of bits read */ -static int16_t decode_azimuth2D( - IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ - uint16_t *bitstream, /* i : bitstream to be read */ - const int16_t coding_subbands, /* i : number of subbands */ - int16_t *pbit_pos, - const int16_t no_frames ) +#ifdef IVAS_FLOAT_FIXED +static ivas_error read_huf( + Word16 *num_bits_read, + const UWord16 *bitstream, /* i : bitstream to be read */ + UWord16 *out, /* o : decoded value */ + const Word16 start_pos, /* i : starting position for reading */ + const Word16 len, /* i : number of codewords */ + const Word16 *huff_code, /* i : Huffman table */ + const Word16 max_len /* i : maximum codeword length */ +) { - int16_t i, j, k; - int16_t allowed_bits, nbits; - int16_t use_vq; - uint16_t Buffer; - int16_t bit_pos; - int16_t *bits_dir0; + Word16 done = 0, end_pos; + UWord16 ByteBuffer; + Word16 nbits, val; + UWord16 i; - bit_pos = *pbit_pos; + end_pos = start_pos; nbits = 0; - for ( j = 0; j < coding_subbands; j++ ) + val = 0; + WHILE( ( done == 0 ) && ( nbits < max_len ) ) { - bits_dir0 = (int16_t *) q_direction->band_data[j].bits_sph_idx; - allowed_bits = sum_s( bits_dir0, no_frames ); - - if ( allowed_bits > 0 ) + ByteBuffer = bitstream[end_pos--]; + val = val * 2 + ( ByteBuffer & 1 ); + nbits += 1; + FOR( i = 0; i < len; i++ ) { - use_vq = 0; - for ( k = 0; k < no_frames; k++ ) + IF( val == huff_code[i] ) { - q_direction->band_data[j].elevation[k] = 0; - q_direction->band_data[j].elevation_index[k] = 0; - - if ( bits_dir0[k] > use_vq ) - { - use_vq = bits_dir0[k]; - } + *out = i; + done = 1; + BREAK; } + } + } - if ( use_vq <= 3 && allowed_bits <= 11 ) - { - if ( allowed_bits <= no_frames + 1 ) - { - set_f( q_direction->band_data[j].azimuth, 0.0f, no_frames ); - for ( k = 0; k < min( allowed_bits, no_frames ); k++ ) - { - q_direction->band_data[j].azimuth[k] = ( -180.f ) * bitstream[bit_pos--]; - nbits += 1; - } - } - else - { - nbits += read_truncGR_azimuth( bitstream, q_direction, j, no_frames, &bit_pos ); - } - } - else - { - for ( k = 0; k < no_frames; k++ ) - { - Buffer = 0; - for ( i = 0; i < bits_dir0[k]; i++ ) - { - Buffer = ( Buffer << 1 ) + bitstream[bit_pos--]; - } + *num_bits_read = end_pos; - nbits += bits_dir0[k]; + return IVAS_ERR_OK; +} +#else +static ivas_error read_huf( + int16_t *num_bits_read, + const uint16_t *bitstream, /* i : bitstream to be read */ + uint16_t *out, /* o : decoded value */ + const int16_t start_pos, /* i : starting position for reading */ + const int16_t len, /* i : number of codewords */ + const int16_t *huff_code, /* i : Huffman table */ + const int16_t max_len /* i : maximum codeword length */ +) +{ + int16_t done = 0, end_pos; + uint16_t ByteBuffer; + int16_t nbits, val; + uint16_t i; - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) - { - q_direction->band_data[j].azimuth[k] = 360.0f / (float) ( 1 << bits_dir0[k] ) * Buffer - 180; - q_direction->band_data[j].azimuth[k] = companding_azimuth( q_direction->band_data[j].azimuth[k], q_direction->cfg.mc_ls_setup, - ( q_direction->band_data[j].elevation[k] > MC_MASA_THR_ELEVATION ), -1 ); - } - else - { - q_direction->band_data[j].azimuth[k] = 360.0f / (float) ( 1 << bits_dir0[k] ) * Buffer - 180; - } - } - } - } - else + end_pos = start_pos; + nbits = 0; + val = 0; + while ( ( done == 0 ) && ( nbits < max_len ) ) + { + ByteBuffer = bitstream[end_pos--]; + val = val * 2 + ( ByteBuffer & 1 ); + nbits += 1; + for ( i = 0; i < len; i++ ) { - set_zero_direction( q_direction, j, no_frames ); + if ( val == huff_code[i] ) + { + *out = i; + done = 1; + break; + } } } - *pbit_pos = bit_pos; - return nbits; + *num_bits_read = end_pos; + + return IVAS_ERR_OK; } +#endif /*-------------------------------------------------------------------* - * set_zero_direction() + * read_GR_min_removed_data() * * *-------------------------------------------------------------------*/ - -static void set_zero_direction( - IVAS_QDIRECTION *q_direction, - const int16_t idx_band, - const int16_t len ) +#ifdef IVAS_FLOAT_FIXED +static Word16 read_GR_min_removed_data( + UWord16 *bitstream, /* i : bitstream */ + Word16 *p_bit_pos, /* i : position in the bitstream */ + const Word16 *no_cv_vec, + const Word16 no_data, + Word16 *decoded_idx, + const Word16 no_symb ) { - int16_t k; + Word16 j; + Word16 bit_pos; + Word16 nbits, bits_GR; + UWord16 byteBuffer; + Word16 min_index; - for ( k = 0; k < len; k++ ) + bit_pos = *p_bit_pos; + + /* read GR order */ + byteBuffer = bitstream[bit_pos--]; + nbits = 1; + + /* read min index */ + bits_GR = bit_pos; + min_index = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_symb, 0 ); + nbits += bits_GR - bit_pos; + + /* read GR data */ + FOR( j = 0; j < no_data; j++ ) { - q_direction->band_data[idx_band].azimuth[k] = 0; - q_direction->band_data[idx_band].azimuth_index[k] = 0; - q_direction->band_data[idx_band].elevation[k] = 0; - q_direction->band_data[idx_band].elevation_index[k] = 0; - q_direction->band_data[idx_band].spherical_index[k] = 0; + bits_GR = bit_pos; + IF( no_cv_vec[j] > 1 ) + { + decoded_idx[j] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_cv_vec[j] - min_index, ( byteBuffer & 1 ) ); + nbits += bits_GR - bit_pos; + } + ELSE + { + decoded_idx[j] = 0; + } } - return; + FOR( j = 0; j < no_data; j++ ){ + IF( no_cv_vec[j] > 1 ){ + decoded_idx[j] += min_index; +} } +*p_bit_pos = bit_pos; -/*-------------------------------------------------------------------* - * read_truncGR_azimuth() - * - * - *-------------------------------------------------------------------*/ - -static int16_t read_truncGR_azimuth( - uint16_t *bitstream, /* i : bitstream to be read */ - IVAS_QDIRECTION *q_direction, /* i/o: quantized metadata structure */ - const int16_t j, /* i : subband index */ - const int16_t no_subframes, /* i : number of tiles */ - int16_t *pbit_pos /* i/o: position in bitstream */ -) +return nbits; +} +#else +static int16_t read_GR_min_removed_data( + uint16_t *bitstream, /* i : bitstream */ + int16_t *p_bit_pos, /* i : position in the bitstream */ + const int16_t *no_cv_vec, + const int16_t no_data, + int16_t *decoded_idx, + const int16_t no_symb ) { - int16_t i; - int16_t nbits; - uint16_t idx; - int16_t no_symb, allowed_bits; - - allowed_bits = sum_s( (int16_t *) q_direction->band_data[j].bits_sph_idx, no_subframes ); - nbits = 0; - if ( allowed_bits <= no_subframes + 1 ) - { - for ( i = 0; i < min( allowed_bits, no_subframes ); i++ ) - { - if ( bitstream[( *pbit_pos )--] == 0 ) - { - q_direction->band_data[j].azimuth[i] = 0.0f; - } - else - { - q_direction->band_data[j].azimuth[i] = -180; - } - nbits++; - } + int16_t j; + int16_t bit_pos; + int16_t nbits, bits_GR; + uint16_t byteBuffer; + int16_t min_index; - return nbits; - } + bit_pos = *p_bit_pos; - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) - { - no_symb = 9; - } - else - { - no_symb = 8; - } - nbits = 0; + /* read GR order */ + byteBuffer = bitstream[bit_pos--]; + nbits = 1; - nbits = *pbit_pos; + /* read min index */ + bits_GR = bit_pos; + min_index = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_symb, 0 ); + nbits += bits_GR - bit_pos; - for ( i = 0; i < no_subframes; i++ ) + /* read GR data */ + for ( j = 0; j < no_data; j++ ) { - idx = ivas_qmetadata_DecodeExtendedGR( bitstream, pbit_pos, no_symb, 0 ); - q_direction->band_data[j].azimuth_index[i] = idx; - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + bits_GR = bit_pos; + if ( no_cv_vec[j] > 1 ) { - q_direction->band_data[j].azimuth[i] = cb_azi_chan[( idx + 1 ) >> 1]; - if ( idx % 2 > 0 ) - { - q_direction->band_data[j].azimuth[i] = -q_direction->band_data[j].azimuth[i]; - } + decoded_idx[j] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_cv_vec[j] - min_index, ( byteBuffer & 1 ) ); + nbits += bits_GR - bit_pos; } else { - q_direction->band_data[j].azimuth[i] = azimuth_cb[idx]; + decoded_idx[j] = 0; } } - nbits -= *pbit_pos; + for ( j = 0; j < no_data; j++ ) + { + if ( no_cv_vec[j] > 1 ) + { + decoded_idx[j] += min_index; + } + } + + *p_bit_pos = bit_pos; return nbits; } +#endif /*-------------------------------------------------------------------* - * read_common_direction() + * decode_fixed_rate_composed_index_coherence() * * *-------------------------------------------------------------------*/ -/*! r: number of bits read */ -static int16_t read_common_direction( - uint16_t *bitstream, /* i : bitstream to be read */ - IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ - const int16_t j, /* i : subband index */ - const int16_t no_subframes, /* i : number of tiles */ - const int16_t bits_total, /* i : number of bits for subband directional data */ - int16_t *pbit_pos /* i/o: position in bitstream */ -) +static int16_t decode_fixed_rate_composed_index_coherence( + uint16_t *bitstream, /* i : bitstream */ + int16_t *p_bit_pos, /* i : position in the bitstream */ + const int16_t no_bands, + int16_t *no_cv_vec, + uint16_t *decoded_index, + const int16_t no_symb ) { - int16_t nbits; + /* fixed rate */ + uint64_t no_cb; + uint16_t temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + uint64_t idx_fr; + int16_t no_bits_vec1, half_no_bands; int16_t bit_pos; - int16_t i; - uint16_t byteBuffer; - int16_t bits_el; - - bit_pos = *pbit_pos; - nbits = 0; + int16_t nbits, bits_GR; + int16_t j; + int16_t no_vals_local; + int16_t no_bits_vec; - set_zero_direction( q_direction, j, no_subframes ); - if ( bits_total == 0 ) - { - return nbits; - } + bit_pos = *p_bit_pos; + set_s( (int16_t *) temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); - if ( bits_total <= no_subframes + 1 ) + no_cb = 1; + nbits = 0; + if ( no_bands > MASA_LIMIT_NO_BANDS_SUR_COH ) { - for ( i = 0; i < min( no_subframes, bits_total ); i++ ) + /* read 8-max_val with GR0 */ + bits_GR = bit_pos; + no_vals_local = no_symb - ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_symb, 0 ); + nbits += bits_GR - bit_pos; + for ( j = 0; j < no_bands; j++ ) { - byteBuffer = bitstream[bit_pos--]; - /*qdirection->azimuth_index[j][i] = (uint16_t)byteBuffer; */ - q_direction->band_data[j].azimuth[i] = azimuth_cb[byteBuffer]; - nbits += 1; + if ( no_cv_vec[j] > no_vals_local ) + { + no_cv_vec[j] = no_vals_local; + } } - *pbit_pos = bit_pos; - - /*nbits += read_truncGR_azimuth(bitstream, qdirection, j, no_subframes, pbit_pos); */ - return nbits; } - - byteBuffer = bitstream[bit_pos--]; - bits_el = 1; - nbits += 1; - /* elevation is already set to 0*/ - if ( byteBuffer == 1 ) + half_no_bands = no_bands / 2; + if ( sum_s( no_cv_vec, no_bands ) > MASA_COH_LIMIT_2IDX ) { - byteBuffer = bitstream[bit_pos--]; - bits_el += 1; - nbits += 1; - if ( byteBuffer == 0 ) + no_cb = 1; + + for ( j = 0; j < half_no_bands; j++ ) { - for ( i = 0; i < no_subframes; i++ ) - { - q_direction->band_data[j].elevation[i] = delta_theta_masa[2]; - } + no_cb *= no_cv_vec[j]; } - else + no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + no_cb = 1; + for ( j = half_no_bands; j < no_bands; j++ ) { - byteBuffer = bitstream[bit_pos--]; - bits_el += 1; - nbits += 1; - if ( byteBuffer == 0 ) - { - for ( i = 0; i < no_subframes; i++ ) - { - q_direction->band_data[j].elevation[i] = -delta_theta_masa[2]; - } - } - else - { - /* theta is +/- 90; no azimuth is read */ - byteBuffer = bitstream[bit_pos--]; - nbits += 1; - if ( byteBuffer == 0 ) - { - set_f( q_direction->band_data[j].elevation, 90.0f, no_subframes ); - set_f( q_direction->band_data[j].azimuth, 0.0f, no_subframes ); - } - else - { - set_f( q_direction->band_data[j].elevation, -90.0f, no_subframes ); - set_f( q_direction->band_data[j].azimuth, 0.0f, no_subframes ); - } - *pbit_pos = bit_pos; - - return nbits; - } + no_cb *= no_cv_vec[j]; } + no_bits_vec1 = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); } - - bits_el = sum_s( (int16_t *) q_direction->band_data[j].bits_sph_idx, no_subframes ) - bits_el; - - if ( bits_el <= no_subframes + 1 ) + else { - nbits += min( no_subframes, bits_el ); - for ( i = 0; i < min( no_subframes, bits_el ); i++ ) + no_cb = 1; + for ( j = 0; j < no_bands; j++ ) { - byteBuffer = bitstream[bit_pos--]; - /*qdirection->azimuth_index[j][i] = (uint16_t) byteBuffer; */ - q_direction->band_data[j].azimuth[i] = azimuth_cb[byteBuffer]; + no_cb *= no_cv_vec[j]; } + no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + no_bits_vec1 = 0; } - else + if ( no_bits_vec1 > 0 ) { - nbits += read_truncGR_azimuth( bitstream, q_direction, j, no_subframes, &bit_pos ); - } - - *pbit_pos = bit_pos; - - return nbits; -} - + idx_fr = 0; + for ( j = 0; j < no_bits_vec; j++ ) + { + idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; + } -/*-----------------------------------------------------------------------* - * Local functions: coherence - *-----------------------------------------------------------------------*/ + nbits += no_bits_vec; -static void decode_spread_coherence( - IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: quantized metadata structure */ - int16_t idx_d, /* i : direction index */ - const int16_t no_frames, /* i : number of time subframes */ - const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding */ -) -{ - int16_t i, j; - float var_azi; - int16_t idx_sub_cb; - float dct_coh[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t MASA_grouping[MASA_MAXIMUM_CODING_SUBBANDS]; - IVAS_QDIRECTION *q_direction; - int16_t coding_subbands, coding_subbands_0, d, two_dir_band[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t min_index; + decode_combined_index( idx_fr, no_cv_vec, temp_index, half_no_bands ); - coding_subbands_0 = hQMetaData->q_direction[0].cfg.nbands; - coding_subbands = hQMetaData->q_direction[idx_d].cfg.nbands; - if ( coding_subbands_0 <= 5 ) - { - for ( j = 0; j < 5; j++ ) + idx_fr = 0; + for ( j = 0; j < no_bits_vec1; j++ ) { - MASA_grouping[j] = j; + idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; } + nbits += no_bits_vec1; + decode_combined_index( idx_fr, &no_cv_vec[half_no_bands], &temp_index[half_no_bands], half_no_bands ); } else { - if ( coding_subbands_0 <= 8 ) - { - mvs2s( MASA_grouping_8_to_5, MASA_grouping, 8 ); - } - else if ( coding_subbands_0 <= 12 ) - { - mvs2s( MASA_grouping_12_to_5, MASA_grouping, 12 ); - } - else if ( coding_subbands_0 <= 18 ) - { - mvs2s( MASA_grouping_18_to_5, MASA_grouping, 18 ); - } - else + idx_fr = 0; + for ( j = 0; j < no_bits_vec; j++ ) { - if ( coding_subbands_0 <= 24 ) - { - mvs2s( MASA_grouping_24_to_5, MASA_grouping, 24 ); - } + idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; } + nbits += no_bits_vec; + decode_combined_index( idx_fr, no_cv_vec, temp_index, no_bands ); + } + + for ( j = 0; j < no_bands; j++ ) + { + decoded_index[j] = temp_index[j]; } + nbits = *p_bit_pos - bit_pos; + + *p_bit_pos = bit_pos; - if ( coding_subbands < coding_subbands_0 ) + return nbits; +} + +#ifdef IVAS_FLOAT_FIXED +static Word16 decode_fixed_rate_composed_index_coherence_fx( + UWord16 *bitstream, /* i : bitstream */ + Word16 *p_bit_pos, /* i : position in the bitstream */ + const Word16 no_bands, + Word16 *no_cv_vec, + UWord16 *decoded_index, + const Word16 no_symb ) +{ + /* fixed rate */ + UWord64 no_cb; + UWord16 temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord64 idx_fr; + Word16 no_bits_vec1, half_no_bands; + Word16 bit_pos; + Word16 nbits, bits_GR; + Word16 j; + Word16 no_vals_local; + Word16 no_bits_vec; + + bit_pos = *p_bit_pos; + set_s( (Word16 *) temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + + no_cb = 1; + nbits = 0; + IF( no_bands > MASA_LIMIT_NO_BANDS_SUR_COH ) { - d = 0; - for ( j = 0; j < coding_subbands_0; j++ ) + /* read 8-max_val with GR0 */ + bits_GR = bit_pos; + no_vals_local = no_symb - ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_symb, 0 ); + nbits += bits_GR - bit_pos; + FOR( j = 0; j < no_bands; j++ ) { - if ( hQMetaData->twoDirBands[j] == 1 ) + IF( no_cv_vec[j] > no_vals_local ) { - two_dir_band[d++] = j; + no_cv_vec[j] = no_vals_local; } } } - else - { - set_s( two_dir_band, 0, coding_subbands ); - } - - q_direction = &hQMetaData->q_direction[idx_d]; - for ( i = 0; i < coding_subbands; i++ ) + half_no_bands = no_bands / 2; + IF( sum_s( no_cv_vec, no_bands ) > MASA_COH_LIMIT_2IDX ) { - var_azi = var( q_direction->band_data[i].azimuth, no_frames ); + no_cb = 1; - if ( hrmasa_flag ) + FOR( j = 0; j < half_no_bands; j++ ) { - minimum_s( (int16_t *) ( q_direction->band_data[i].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); - min_index = min_index >> 1; + no_cb *= no_cv_vec[j]; } - else + no_bits_vec = (Word16) ceil_log_2( no_cb ); + no_cb = 1; + FOR( j = half_no_bands; j < no_bands; j++ ) { - min_index = q_direction->band_data[i].energy_ratio_index[0]; + no_cb *= no_cv_vec[j]; } - - if ( var_azi < MASA_DELTA_AZI_DCT0 ) + no_bits_vec1 = (Word16) ceil_log_2( no_cb ); + } + ELSE + { + no_cb = 1; + FOR( j = 0; j < no_bands; j++ ) { - idx_sub_cb = MASA_NO_CV_COH * min_index; + no_cb *= no_cv_vec[j]; } - else + no_bits_vec = (Word16) ceil_log_2( no_cb ); + no_bits_vec1 = 0; + } + IF( no_bits_vec1 > 0 ) + { + idx_fr = 0; + FOR( j = 0; j < no_bits_vec; j++ ) { - idx_sub_cb = MASA_NO_CV_COH * ( min_index + DIRAC_DIFFUSE_LEVELS ); /* NO_CV_COH = 8 */ + idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; } - dct_coh[i][0] = coherence_cb0_masa[idx_sub_cb + q_direction->coherence_band_data[i].spread_coherence_dct0_index]; + nbits += no_bits_vec; - if ( coding_subbands < coding_subbands_0 ) - { - assert( idx_d == 1 ); - dct_coh[i][1] = coherence_cb1_masa[MASA_grouping[two_dir_band[i]] * MASA_NO_CV_COH1 + q_direction->coherence_band_data[i].spread_coherence_dct1_index]; - } - else + decode_combined_index_fx( idx_fr, no_cv_vec, temp_index, half_no_bands ); + + idx_fr = 0; + FOR( j = 0; j < no_bits_vec1; j++ ) { - dct_coh[i][1] = coherence_cb1_masa[MASA_grouping[i] * MASA_NO_CV_COH1 + q_direction->coherence_band_data[i].spread_coherence_dct1_index]; + idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; } - - for ( j = 2; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + nbits += no_bits_vec1; + decode_combined_index_fx( idx_fr, &no_cv_vec[half_no_bands], &temp_index[half_no_bands], half_no_bands ); + } + ELSE + { + idx_fr = 0; + FOR( j = 0; j < no_bits_vec; j++ ) { - dct_coh[i][j] = 0; + idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; } + nbits += no_bits_vec; + decode_combined_index_fx( idx_fr, no_cv_vec, temp_index, no_bands ); + } - invdct4_transform( dct_coh[i], q_direction->coherence_band_data[i].spread_coherence ); + FOR( j = 0; j < no_bands; j++ ) + { + decoded_index[j] = temp_index[j]; } + nbits = *p_bit_pos - bit_pos; - return; -} + *p_bit_pos = bit_pos; + return nbits; +} +#endif /*-------------------------------------------------------------------* - * read_huf() + * read_coherence_data_hr_512() * - * Read Hufman code + * Read coherence data at HR *-------------------------------------------------------------------*/ /*! r: number of bits read */ -static ivas_error read_huf( - int16_t *num_bits_read, - const uint16_t *bitstream, /* i : bitstream to be read */ - uint16_t *out, /* o : decoded value */ - const int16_t start_pos, /* i : starting position for reading */ - const int16_t len, /* i : number of codewords */ - const int16_t *huff_code, /* i : Huffman table */ - const int16_t max_len /* i : maximum codeword length */ -) +static int16_t read_coherence_data_hr_512( + uint16_t *bitstream, /* i : bitstream */ + int16_t *p_bit_pos, /* i : position in the bitstream */ + IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata structure */ + const int16_t idx_dir, /* i : direction index */ + const int16_t nbits_coh ) { - int16_t done = 0, end_pos; - uint16_t ByteBuffer; - int16_t nbits, val; - uint16_t i; + int16_t j, k, i; + int16_t nbands, nblocks; + int16_t min_index, GR_param; + int16_t cb_size, nbits; + int16_t decoded_idx; + float delta; - end_pos = start_pos; - nbits = 0; - val = 0; - while ( ( done == 0 ) && ( nbits < max_len ) ) + nbands = hQMetaData->q_direction[idx_dir].cfg.nbands; + nblocks = hQMetaData->q_direction[idx_dir].cfg.nblocks; + + cb_size = 1 << nbits_coh; + delta = 256.0f / cb_size; + nbits = *p_bit_pos; + for ( k = 0; k < nblocks; k++ ) { - ByteBuffer = bitstream[end_pos--]; - val = val * 2 + ( ByteBuffer & 1 ); - nbits += 1; - for ( i = 0; i < len; i++ ) + /* read method */ + if ( bitstream[( *p_bit_pos )--] == 1 ) { - if ( val == huff_code[i] ) + /* average removed */ + /* read average index */ + min_index = 0; + for ( i = 0; i < nbits_coh; i++ ) { - *out = i; - done = 1; - break; + min_index = ( min_index << 1 ) + bitstream[( *p_bit_pos )--]; + } + /* read GR param */ + GR_param = bitstream[( *p_bit_pos )--]; + for ( j = 0; j < nbands; j++ ) + { + decoded_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, p_bit_pos, 2 * cb_size, GR_param ); + if ( decoded_idx % 2 ) + { + decoded_idx = ( ( decoded_idx + 1 ) >> 1 ) + min_index; + } + else + { + decoded_idx = -( decoded_idx >> 1 ) + min_index; + } + hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (uint8_t) ( decoded_idx * delta + delta / 2.0f ); + } + } + else + { + /* read min_index */ + min_index = 0; + for ( i = 0; i < nbits_coh; i++ ) + { + min_index = ( min_index << 1 ) + bitstream[( *p_bit_pos )--]; + } + + /* read GR param */ + GR_param = bitstream[( *p_bit_pos )--]; + for ( j = 0; j < nbands; j++ ) + { + decoded_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, p_bit_pos, cb_size - min_index, GR_param ) + min_index; + hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (uint8_t) ( decoded_idx * delta + delta / 2.0f ); } } } - *num_bits_read = end_pos; + nbits = nbits - *p_bit_pos; - return IVAS_ERR_OK; + return nbits; } - -/*-------------------------------------------------------------------* - * read_GR_min_removed_data() - * - * - *-------------------------------------------------------------------*/ - -static int16_t read_GR_min_removed_data( - uint16_t *bitstream, /* i : bitstream */ - int16_t *p_bit_pos, /* i : position in the bitstream */ - const int16_t *no_cv_vec, - const int16_t no_data, - int16_t *decoded_idx, - const int16_t no_symb ) +#ifdef IVAS_FLOAT_FIXED +static Word16 read_coherence_data_hr_512_fx( + UWord16 *bitstream, /* i : bitstream */ + Word16 *p_bit_pos, /* i : position in the bitstream */ + IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata structure */ + const Word16 idx_dir, /* i : direction index */ + const Word16 nbits_coh ) { - int16_t j; - int16_t bit_pos; - int16_t nbits, bits_GR; - uint16_t byteBuffer; - int16_t min_index; - - bit_pos = *p_bit_pos; - - /* read GR order */ - byteBuffer = bitstream[bit_pos--]; - nbits = 1; + Word16 j, k, i; + Word16 nbands, nblocks; + Word16 min_index, GR_param; + Word16 cb_size, nbits; + Word16 decoded_idx; + Word32 delta_fx, decoded_idx_fx; // q = 22, q = 9 - /* read min index */ - bits_GR = bit_pos; - min_index = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_symb, 0 ); - nbits += bits_GR - bit_pos; + nbands = hQMetaData->q_direction[idx_dir].cfg.nbands; + nblocks = hQMetaData->q_direction[idx_dir].cfg.nblocks; - /* read GR data */ - for ( j = 0; j < no_data; j++ ) + cb_size = 1 << nbits_coh; + delta_fx = L_shl( 256, 22 - nbits_coh ); + nbits = *p_bit_pos; + FOR( k = 0; k < nblocks; k++ ) { - bits_GR = bit_pos; - if ( no_cv_vec[j] > 1 ) + /* read method */ + IF( bitstream[( *p_bit_pos )--] == 1 ) { - decoded_idx[j] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_cv_vec[j] - min_index, ( byteBuffer & 1 ) ); - nbits += bits_GR - bit_pos; + /* average removed */ + /* read average index */ + min_index = 0; + FOR( i = 0; i < nbits_coh; i++ ) + { + min_index = add( shl( min_index, 1 ), bitstream[( *p_bit_pos )--] ); + } + /* read GR param */ + GR_param = bitstream[( *p_bit_pos )--]; + FOR( j = 0; j < nbands; j++ ) + { + decoded_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, p_bit_pos, 2 * cb_size, GR_param ); + IF( decoded_idx % 2 ) + { + decoded_idx = add( shr( add( decoded_idx, 1 ), 1 ), min_index ); + } + ELSE + { + decoded_idx = add( negate( shr( decoded_idx, 1 ) ), min_index ); + } + decoded_idx_fx = L_shl( decoded_idx, 9 ); + hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (uint8_t) L_add( Mpy_32_32( decoded_idx_fx, delta_fx ), L_shr( delta_fx, 23 ) ); + } } else { - decoded_idx[j] = 0; - } - } + /* read min_index */ + min_index = 0; + for ( i = 0; i < nbits_coh; i++ ) + { + min_index = add( shl( min_index, 1 ), bitstream[( *p_bit_pos )--] ); + } - for ( j = 0; j < no_data; j++ ) - { - if ( no_cv_vec[j] > 1 ) - { - decoded_idx[j] += min_index; + /* read GR param */ + GR_param = bitstream[( *p_bit_pos )--]; + for ( j = 0; j < nbands; j++ ) + { + decoded_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, p_bit_pos, cb_size - min_index, GR_param ) + min_index; + decoded_idx_fx = L_shl( decoded_idx, 9 ); + hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (uint8_t) L_add( Mpy_32_32( decoded_idx_fx, delta_fx ), L_shr( delta_fx, 23 ) ); + } } } - *p_bit_pos = bit_pos; + nbits = sub( nbits, *p_bit_pos ); return nbits; } +#endif - -/*-------------------------------------------------------------------* - * decode_fixed_rate_composed_index_coherence() - * +/*------------------------------------------------------------------- * + * read_coherence_data() * - *-------------------------------------------------------------------*/ + * Read coherence data + *------------------------------------------------------------------- */ -static int16_t decode_fixed_rate_composed_index_coherence( - uint16_t *bitstream, /* i : bitstream */ - int16_t *p_bit_pos, /* i : position in the bitstream */ - const int16_t no_bands, - int16_t *no_cv_vec, - uint16_t *decoded_index, - const int16_t no_symb ) +/*! r: number of bits read */ +static int16_t read_coherence_data( + uint16_t *bitstream, /* i : bitstream */ + int16_t *p_bit_pos, /* i : position in the bitstream */ + IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata structure */ + const int16_t idx_dir, /* i : direction index */ + const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ +) { - /* fixed rate */ + int16_t j; + int16_t no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; uint64_t no_cb; - uint16_t temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; - uint64_t idx_fr; - int16_t no_bits_vec1, half_no_bands; + int16_t no_bits_vec, nbits; + int16_t bits_GR; + uint16_t idx_dct1[MASA_MAXIMUM_CODING_SUBBANDS]; + uint16_t av_index; + int16_t no_bits_vec1; int16_t bit_pos; - int16_t nbits, bits_GR; - int16_t j; - int16_t no_vals_local; - int16_t no_bits_vec; + IVAS_QDIRECTION *q_direction; + int16_t coding_subbands; + uint64_t dct0_index; + int16_t decoded_idx[MASA_MAXIMUM_CODING_SUBBANDS]; + uint16_t byteBuffer; + int16_t idx_ER; + int16_t min_index; + int16_t extra_cv; + coding_subbands = hQMetaData->q_direction[idx_dir].cfg.nbands; + extra_cv = (int16_t) ( coding_subbands / MASA_FACTOR_CV_COH ); + q_direction = &( hQMetaData->q_direction[idx_dir] ); bit_pos = *p_bit_pos; - set_s( (int16_t *) temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); - - no_cb = 1; nbits = 0; - if ( no_bands > MASA_LIMIT_NO_BANDS_SUR_COH ) + + if ( q_direction->cfg.nblocks == 1 ) { - /* read 8-max_val with GR0 */ - bits_GR = bit_pos; - no_vals_local = no_symb - ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_symb, 0 ); - nbits += bits_GR - bit_pos; - for ( j = 0; j < no_bands; j++ ) + for ( j = 0; j < coding_subbands; j++ ) { - if ( no_cv_vec[j] > no_vals_local ) + if ( hrmasa_flag ) { - no_cv_vec[j] = no_vals_local; + idx_ER = 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> 1 ) + extra_cv; + } + else + { + idx_ER = 7 - q_direction->band_data[j].energy_ratio_index_mod[0] + extra_cv; } + no_cv_vec[j] = idx_ER + 1; } - } - half_no_bands = no_bands / 2; - if ( sum_s( no_cv_vec, no_bands ) > MASA_COH_LIMIT_2IDX ) - { - no_cb = 1; + if ( sum_s( no_cv_vec, coding_subbands ) == coding_subbands ) + { + for ( j = 0; j < coding_subbands; j++ ) + { + q_direction->coherence_band_data[j].spread_coherence[0] = 0; + } - for ( j = 0; j < half_no_bands; j++ ) + return 0; + } + byteBuffer = bitstream[bit_pos--]; + nbits += 1; + + if ( byteBuffer & 1 ) { - no_cb *= no_cv_vec[j]; + /* decode GR min removed */ + nbits += read_GR_min_removed_data( bitstream, &bit_pos, no_cv_vec, coding_subbands, decoded_idx, MASA_MAX_NO_CV_SUR_COH + extra_cv ); + for ( j = 0; j < coding_subbands; j++ ) + { + if ( no_cv_vec[j] > 1 ) + { + q_direction->coherence_band_data[j].spread_coherence[0] = (uint8_t) roundf( decoded_idx[j] * ( 255.0f / (float) ( 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> ( hrmasa_flag ) ) + coding_subbands / MASA_FACTOR_CV_COH ) ) ); + } + else + { + q_direction->coherence_band_data[j].spread_coherence[0] = 0; + } + } } - no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); - no_cb = 1; - for ( j = half_no_bands; j < no_bands; j++ ) + else { - no_cb *= no_cv_vec[j]; + uint16_t decoded_index[MASA_MAXIMUM_CODING_SUBBANDS]; + /* decode joint index */ +#ifdef IVAS_FLOAT_FIXED + nbits += decode_fixed_rate_composed_index_coherence_fx( bitstream, &bit_pos, coding_subbands, no_cv_vec, decoded_index, MASA_NO_CV_COH + coding_subbands / MASA_FACTOR_CV_COH ); +#else + nbits += decode_fixed_rate_composed_index_coherence( bitstream, &bit_pos, coding_subbands, no_cv_vec, decoded_index, MASA_NO_CV_COH + coding_subbands / MASA_FACTOR_CV_COH ); +#endif + for ( j = 0; j < coding_subbands; j++ ) + { + if ( no_cv_vec[j] > 1 ) + { + q_direction->coherence_band_data[j].spread_coherence[0] = (uint8_t) roundf( decoded_index[j] * ( 255.0f / (float) ( 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> ( hrmasa_flag ) ) + coding_subbands / MASA_FACTOR_CV_COH ) ) ); + } + else + { + q_direction->coherence_band_data[j].spread_coherence[0] = 0; + } + } } - no_bits_vec1 = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); } else { - no_cb = 1; - for ( j = 0; j < no_bands; j++ ) + for ( j = 0; j < coding_subbands; j++ ) { - no_cb *= no_cv_vec[j]; + if ( hrmasa_flag ) + { + minimum_s( (int16_t *) ( q_direction->band_data[j].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); + no_cv_vec[j] = len_cb_dct0_masa[min_index >> 1]; /* spread coherence DCT0*/ + } + else + { + no_cv_vec[j] = len_cb_dct0_masa[q_direction->band_data[j].energy_ratio_index[0]]; /* spread coherence DCT0*/ + } } - no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); - no_bits_vec1 = 0; - } - if ( no_bits_vec1 > 0 ) - { - idx_fr = 0; - for ( j = 0; j < no_bits_vec; j++ ) + + if ( sum_s( no_cv_vec, coding_subbands ) > MASA_COH_LIMIT_2IDX ) { - idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; - } + uint16_t spr_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; - nbits += no_bits_vec; + no_cb = 1; + for ( j = 0; j < coding_subbands / 2; j++ ) + { + no_cb *= no_cv_vec[j]; + } - decode_combined_index( idx_fr, no_cv_vec, temp_index, half_no_bands ); + no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + no_cb = 1; - idx_fr = 0; - for ( j = 0; j < no_bits_vec1; j++ ) - { - idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; - } - nbits += no_bits_vec1; - decode_combined_index( idx_fr, &no_cv_vec[half_no_bands], &temp_index[half_no_bands], half_no_bands ); - } - else - { - idx_fr = 0; - for ( j = 0; j < no_bits_vec; j++ ) - { - idx_fr = ( idx_fr << 1 ) + bitstream[bit_pos--]; - } - nbits += no_bits_vec; - decode_combined_index( idx_fr, no_cv_vec, temp_index, no_bands ); - } + for ( j = coding_subbands / 2; j < coding_subbands; j++ ) + { + no_cb *= no_cv_vec[j]; + } - for ( j = 0; j < no_bands; j++ ) - { - decoded_index[j] = temp_index[j]; - } - nbits = *p_bit_pos - bit_pos; + no_bits_vec1 = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + dct0_index = 0; - *p_bit_pos = bit_pos; + for ( j = 0; j < no_bits_vec; j++ ) + { + dct0_index = ( dct0_index << 1 ) + bitstream[bit_pos--]; + } - return nbits; -} + nbits += no_bits_vec; + set_s( (int16_t *) spr_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + decode_combined_index( dct0_index, no_cv_vec, spr_coh_temp_index, coding_subbands / 2 ); -/*-------------------------------------------------------------------* - * read_coherence_data_hr_512() - * - * Read coherence data at HR - *-------------------------------------------------------------------*/ + dct0_index = 0; + for ( j = 0; j < no_bits_vec1; j++ ) + { + dct0_index = ( dct0_index << 1 ) + bitstream[bit_pos--]; + } -/*! r: number of bits read */ -static int16_t read_coherence_data_hr_512( - uint16_t *bitstream, /* i : bitstream */ - int16_t *p_bit_pos, /* i : position in the bitstream */ - IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata structure */ - const int16_t idx_dir, /* i : direction index */ - const int16_t nbits_coh ) -{ - int16_t j, k, i; - int16_t nbands, nblocks; - int16_t min_index, GR_param; - int16_t cb_size, nbits; - int16_t decoded_idx; - float delta; + nbits += no_bits_vec1; - nbands = hQMetaData->q_direction[idx_dir].cfg.nbands; - nblocks = hQMetaData->q_direction[idx_dir].cfg.nblocks; + decode_combined_index( dct0_index, &no_cv_vec[coding_subbands / 2], &spr_coh_temp_index[coding_subbands / 2], coding_subbands / 2 ); - cb_size = 1 << nbits_coh; - delta = 256.0f / cb_size; - nbits = *p_bit_pos; - for ( k = 0; k < nblocks; k++ ) - { - /* read method */ - if ( bitstream[( *p_bit_pos )--] == 1 ) + for ( j = 0; j < coding_subbands; j++ ) + { + q_direction->coherence_band_data[j].spread_coherence_dct0_index = spr_coh_temp_index[j]; + } + } + else { - /* average removed */ - /* read average index */ - min_index = 0; - for ( i = 0; i < nbits_coh; i++ ) + /* spread coherence */ + uint16_t spr_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + + no_cb = 1; + + for ( j = 0; j < coding_subbands; j++ ) { - min_index = ( min_index << 1 ) + bitstream[( *p_bit_pos )--]; + no_cb *= no_cv_vec[j]; } - /* read GR param */ - GR_param = bitstream[( *p_bit_pos )--]; - for ( j = 0; j < nbands; j++ ) + + no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + + /* read joint index for DCT0 */ + no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + dct0_index = 0; + + for ( j = 0; j < no_bits_vec; j++ ) + { + dct0_index = ( dct0_index << 1 ) + bitstream[bit_pos--]; + } + + nbits += no_bits_vec; + + set_s( (int16_t *) spr_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + + decode_combined_index( dct0_index, no_cv_vec, spr_coh_temp_index, coding_subbands ); + + for ( j = 0; j < coding_subbands; j++ ) { - decoded_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, p_bit_pos, 2 * cb_size, GR_param ); - if ( decoded_idx % 2 ) - { - decoded_idx = ( ( decoded_idx + 1 ) >> 1 ) + min_index; - } - else - { - decoded_idx = -( decoded_idx >> 1 ) + min_index; - } - hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (uint8_t) ( decoded_idx * delta + delta / 2.0f ); + q_direction->coherence_band_data[j].spread_coherence_dct0_index = spr_coh_temp_index[j]; } } - else + + /* read GR data for DCT1 */ + for ( j = 0; j < coding_subbands; j++ ) { - /* read min_index */ - min_index = 0; - for ( i = 0; i < nbits_coh; i++ ) + bits_GR = bit_pos; + idx_dct1[j] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, 2 * MASA_NO_CV_COH1, 0 ); + nbits += bits_GR - bit_pos; + } + bits_GR = bit_pos; /* just to store the data */ + + /* read average index */ + read_huf( &bit_pos, bitstream, &av_index, bit_pos, MASA_NO_CV_COH1, huff_code_av_masa, 10 ); /* 10 is MAX_LEN*/ + nbits += ( bits_GR - bit_pos ); + + /* write indexes in metadata structure */ + for ( j = 0; j < coding_subbands; j++ ) + { + if ( idx_dct1[j] % 2 ) { - min_index = ( min_index << 1 ) + bitstream[( *p_bit_pos )--]; + q_direction->coherence_band_data[j].spread_coherence_dct1_index = ( idx_dct1[j] + 1 ) / 2 + av_index; } - - /* read GR param */ - GR_param = bitstream[( *p_bit_pos )--]; - for ( j = 0; j < nbands; j++ ) + else { - decoded_idx = ivas_qmetadata_DecodeExtendedGR( bitstream, p_bit_pos, cb_size - min_index, GR_param ) + min_index; - hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (uint8_t) ( decoded_idx * delta + delta / 2.0f ); + q_direction->coherence_band_data[j].spread_coherence_dct1_index = -idx_dct1[j] / 2 + av_index; } } } + nbits = *p_bit_pos - bit_pos; - nbits = nbits - *p_bit_pos; + *p_bit_pos = bit_pos; return nbits; } - -/*------------------------------------------------------------------- * - * read_coherence_data() - * - * Read coherence data - *------------------------------------------------------------------- */ - -/*! r: number of bits read */ -static int16_t read_coherence_data( - uint16_t *bitstream, /* i : bitstream */ - int16_t *p_bit_pos, /* i : position in the bitstream */ +#ifdef IVAS_FLOAT_FIXED +static Word16 read_coherence_data_fx( + UWord16 *bitstream, /* i : bitstream */ + Word16 *p_bit_pos, /* i : position in the bitstream */ IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata structure */ - const int16_t idx_dir, /* i : direction index */ - const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ + const Word16 idx_dir, /* i : direction index */ + const Word16 hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ ) { - int16_t j; - int16_t no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; - uint64_t no_cb; - int16_t no_bits_vec, nbits; - int16_t bits_GR; - uint16_t idx_dct1[MASA_MAXIMUM_CODING_SUBBANDS]; - uint16_t av_index; - int16_t no_bits_vec1; - int16_t bit_pos; + Word16 j; + Word16 no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord64 no_cb; + Word16 no_bits_vec, nbits; + Word16 bits_GR; + UWord16 idx_dct1[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 av_index; + Word16 no_bits_vec1; + Word16 bit_pos; IVAS_QDIRECTION *q_direction; - int16_t coding_subbands; - uint64_t dct0_index; - int16_t decoded_idx[MASA_MAXIMUM_CODING_SUBBANDS]; - uint16_t byteBuffer; - int16_t idx_ER; - int16_t min_index; - int16_t extra_cv; + Word16 coding_subbands; + UWord64 dct0_index; + Word16 decoded_idx[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 byteBuffer; + Word16 idx_ER; + Word16 min_index; + Word16 extra_cv; + Word16 num, den, q_num, q_den, q_res; + Word32 res; coding_subbands = hQMetaData->q_direction[idx_dir].cfg.nbands; extra_cv = (int16_t) ( coding_subbands / MASA_FACTOR_CV_COH ); @@ -3449,24 +6136,24 @@ static int16_t read_coherence_data( bit_pos = *p_bit_pos; nbits = 0; - if ( q_direction->cfg.nblocks == 1 ) + IF( q_direction->cfg.nblocks == 1 ) { - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { - if ( hrmasa_flag ) + IF( hrmasa_flag ) { idx_ER = 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> 1 ) + extra_cv; } - else + ELSE { idx_ER = 7 - q_direction->band_data[j].energy_ratio_index_mod[0] + extra_cv; } no_cv_vec[j] = idx_ER + 1; } - if ( sum_s( no_cv_vec, coding_subbands ) == coding_subbands ) + IF( sum_s( no_cv_vec, coding_subbands ) == coding_subbands ) { - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { q_direction->coherence_band_data[j].spread_coherence[0] = 0; } @@ -3476,138 +6163,152 @@ static int16_t read_coherence_data( byteBuffer = bitstream[bit_pos--]; nbits += 1; - if ( byteBuffer & 1 ) + IF( byteBuffer & 1 ) { /* decode GR min removed */ nbits += read_GR_min_removed_data( bitstream, &bit_pos, no_cv_vec, coding_subbands, decoded_idx, MASA_MAX_NO_CV_SUR_COH + extra_cv ); - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { - if ( no_cv_vec[j] > 1 ) + IF( no_cv_vec[j] > 1 ) { - q_direction->coherence_band_data[j].spread_coherence[0] = (uint8_t) roundf( decoded_idx[j] * ( 255.0f / (float) ( 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> ( hrmasa_flag ) ) + coding_subbands / MASA_FACTOR_CV_COH ) ) ); + num = decoded_idx[j] * 255; + den = 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> ( hrmasa_flag ) ) + coding_subbands / MASA_FACTOR_CV_COH; + q_den = norm_s( den ); + q_num = norm_s( num ) - 1; + res = div_s( num << q_num, den << q_den ); + q_res = 15 - q_den + q_num; + res = L_shl( res, 16 - q_res ); + q_direction->coherence_band_data[j].spread_coherence[0] = round_fx( res ); } - else + ELSE { q_direction->coherence_band_data[j].spread_coherence[0] = 0; } } } - else + ELSE { uint16_t decoded_index[MASA_MAXIMUM_CODING_SUBBANDS]; /* decode joint index */ - nbits += decode_fixed_rate_composed_index_coherence( bitstream, &bit_pos, coding_subbands, no_cv_vec, decoded_index, MASA_NO_CV_COH + coding_subbands / MASA_FACTOR_CV_COH ); - for ( j = 0; j < coding_subbands; j++ ) + nbits += decode_fixed_rate_composed_index_coherence_fx( bitstream, &bit_pos, coding_subbands, no_cv_vec, decoded_index, MASA_NO_CV_COH + coding_subbands / MASA_FACTOR_CV_COH ); + FOR( j = 0; j < coding_subbands; j++ ) { - if ( no_cv_vec[j] > 1 ) + IF( no_cv_vec[j] > 1 ) { - q_direction->coherence_band_data[j].spread_coherence[0] = (uint8_t) roundf( decoded_index[j] * ( 255.0f / (float) ( 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> ( hrmasa_flag ) ) + coding_subbands / MASA_FACTOR_CV_COH ) ) ); + num = decoded_index[j] * 255; + den = 7 - ( q_direction->band_data[j].energy_ratio_index_mod[0] >> ( hrmasa_flag ) ) + coding_subbands / MASA_FACTOR_CV_COH; + q_den = norm_s( den ); + q_num = norm_s( num ) - 1; + res = div_s( num << q_num, den << q_den ); + q_res = 15 - q_den + q_num; + res = L_shl( res, 16 - q_res ); + q_direction->coherence_band_data[j].spread_coherence[0] = round_fx( res ); } - else + ELSE { q_direction->coherence_band_data[j].spread_coherence[0] = 0; } } } } - else + ELSE { - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { - if ( hrmasa_flag ) + IF( hrmasa_flag ) { - minimum_s( (int16_t *) ( q_direction->band_data[j].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); + minimum_s( (Word16 *) ( q_direction->band_data[j].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); no_cv_vec[j] = len_cb_dct0_masa[min_index >> 1]; /* spread coherence DCT0*/ } - else + ELSE { no_cv_vec[j] = len_cb_dct0_masa[q_direction->band_data[j].energy_ratio_index[0]]; /* spread coherence DCT0*/ } } - if ( sum_s( no_cv_vec, coding_subbands ) > MASA_COH_LIMIT_2IDX ) + IF( sum_s( no_cv_vec, coding_subbands ) > MASA_COH_LIMIT_2IDX ) { - uint16_t spr_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 spr_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; no_cb = 1; - for ( j = 0; j < coding_subbands / 2; j++ ) + FOR( j = 0; j < coding_subbands / 2; j++ ) { no_cb *= no_cv_vec[j]; } - no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + no_bits_vec = ceil_log_2( no_cb ); // (int16_t)ceilf(logf((float)no_cb) * INV_LOG_2); no_cb = 1; - for ( j = coding_subbands / 2; j < coding_subbands; j++ ) + FOR( j = coding_subbands / 2; j < coding_subbands; j++ ) { no_cb *= no_cv_vec[j]; } - no_bits_vec1 = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + no_bits_vec1 = ceil_log_2( no_cb ); // (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); dct0_index = 0; - for ( j = 0; j < no_bits_vec; j++ ) + FOR( j = 0; j < no_bits_vec; j++ ) { dct0_index = ( dct0_index << 1 ) + bitstream[bit_pos--]; } nbits += no_bits_vec; - set_s( (int16_t *) spr_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + set_s( (Word16 *) spr_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); - decode_combined_index( dct0_index, no_cv_vec, spr_coh_temp_index, coding_subbands / 2 ); + decode_combined_index_fx( dct0_index, no_cv_vec, spr_coh_temp_index, coding_subbands / 2 ); dct0_index = 0; - for ( j = 0; j < no_bits_vec1; j++ ) + FOR( j = 0; j < no_bits_vec1; j++ ) { dct0_index = ( dct0_index << 1 ) + bitstream[bit_pos--]; } nbits += no_bits_vec1; - decode_combined_index( dct0_index, &no_cv_vec[coding_subbands / 2], &spr_coh_temp_index[coding_subbands / 2], coding_subbands / 2 ); + decode_combined_index_fx( dct0_index, &no_cv_vec[coding_subbands / 2], &spr_coh_temp_index[coding_subbands / 2], coding_subbands / 2 ); - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { q_direction->coherence_band_data[j].spread_coherence_dct0_index = spr_coh_temp_index[j]; } } - else + ELSE { /* spread coherence */ - uint16_t spr_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 spr_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; no_cb = 1; - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { no_cb *= no_cv_vec[j]; } - no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + no_bits_vec = ceil_log_2( no_cb ); // (int16_t)ceilf(logf((float)no_cb) * INV_LOG_2); - /* read joint index for DCT0 */ - no_bits_vec = (int16_t) ceilf( logf( (float) no_cb ) * INV_LOG_2 ); + /* read joint index for DCT0 */ + no_bits_vec = ceil_log_2( no_cb ); // (int16_t)ceilf(logf((float)no_cb) * INV_LOG_2); dct0_index = 0; - for ( j = 0; j < no_bits_vec; j++ ) + FOR( j = 0; j < no_bits_vec; j++ ) { dct0_index = ( dct0_index << 1 ) + bitstream[bit_pos--]; } nbits += no_bits_vec; - set_s( (int16_t *) spr_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + set_s( (Word16 *) spr_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); - decode_combined_index( dct0_index, no_cv_vec, spr_coh_temp_index, coding_subbands ); + decode_combined_index_fx( dct0_index, no_cv_vec, spr_coh_temp_index, coding_subbands ); - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { q_direction->coherence_band_data[j].spread_coherence_dct0_index = spr_coh_temp_index[j]; } } /* read GR data for DCT1 */ - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { bits_GR = bit_pos; idx_dct1[j] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, 2 * MASA_NO_CV_COH1, 0 ); @@ -3620,13 +6321,13 @@ static int16_t read_coherence_data( nbits += ( bits_GR - bit_pos ); /* write indexes in metadata structure */ - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { - if ( idx_dct1[j] % 2 ) + IF( idx_dct1[j] % 2 ) { q_direction->coherence_band_data[j].spread_coherence_dct1_index = ( idx_dct1[j] + 1 ) / 2 + av_index; } - else + ELSE { q_direction->coherence_band_data[j].spread_coherence_dct1_index = -idx_dct1[j] / 2 + av_index; } @@ -3638,7 +6339,7 @@ static int16_t read_coherence_data( return nbits; } - +#endif /*-------------------------------------------------------------------* * read_surround_coherence() @@ -3759,41 +6460,208 @@ static int16_t read_surround_coherence( hQMetaData->surcoh_band_data[j].sur_coherence_index = idx_sur_coh[j]; } - hQMetaData->surcoh_band_data[j].surround_coherence[0] = sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER[j]] * MASA_MAX_NO_CV_SUR_COH + hQMetaData->surcoh_band_data[j].sur_coherence_index]; - } - } - else - { - /* fixed rate */ - uint16_t sur_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; - set_s( (int16_t *) sur_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + hQMetaData->surcoh_band_data[j].surround_coherence[0] = sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER[j]] * MASA_MAX_NO_CV_SUR_COH + hQMetaData->surcoh_band_data[j].sur_coherence_index]; + } + } + else + { + /* fixed rate */ + uint16_t sur_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + set_s( (int16_t *) sur_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + +#ifdef IVAS_FLOAT_FIXED + decode_fixed_rate_composed_index_coherence_fx( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); +#else + decode_fixed_rate_composed_index_coherence( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); +#endif + + for ( j = 0; j < coding_subbands; j++ ) + { + hQMetaData->surcoh_band_data[j].sur_coherence_index = sur_coh_temp_index[j]; + } + + /* deindex surround coherence */ + for ( j = 0; j < coding_subbands; j++ ) + { + if ( no_cv_vec[j] > 1 ) + { + hQMetaData->surcoh_band_data[j].surround_coherence[0] = sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER[j]] * MASA_MAX_NO_CV_SUR_COH + hQMetaData->surcoh_band_data[j].sur_coherence_index]; + } + else + { + hQMetaData->surcoh_band_data[j].surround_coherence[0] = 0; + } + } + } + + for ( j = 0; j < coding_subbands; j++ ) + { + for ( k = 1; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + { + hQMetaData->surcoh_band_data[j].surround_coherence[k] = hQMetaData->surcoh_band_data[j].surround_coherence[0]; + } + } + + /* Replace return value with the actual read bits. bits_sur_coherence might show wrong count at this point. */ + bits_sur_coherence = *p_bit_pos - bit_pos; + *p_bit_pos = bit_pos; + + return bits_sur_coherence; +} + + +/*-------------------------------------------------------------------* + * read_surround_coherence_hr() + * + * + *-------------------------------------------------------------------*/ + +static int16_t read_surround_coherence_hr( + uint16_t *bitstream, /* i : bitstream */ + int16_t *p_bit_pos, /* i : position in the bitstream */ + IVAS_QMETADATA *hQMetaData /* i/o: quantized metadata structure */ +) +{ + int16_t coding_subbands; + int16_t no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t bit_pos; + float error_ratio_surr; + int16_t idx_ER[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t bits_sur_coherence, bits_GR; + int16_t j, k, sf; + uint16_t byteBuffer; + uint16_t idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; + IVAS_QDIRECTION *q_direction; + int16_t min_index; + int16_t d, idx; + coding_subbands = hQMetaData->q_direction[0].cfg.nbands; + q_direction = hQMetaData->q_direction; + + bits_sur_coherence = 0; + bit_pos = *p_bit_pos; + + for ( sf = 0; sf < hQMetaData->q_direction[0].cfg.nblocks; sf++ ) + { + d = 0; + for ( j = 0; j < coding_subbands; j++ ) + { + error_ratio_surr = 1.0f; + if ( hQMetaData->no_directions == 2 ) + { + d += hQMetaData->twoDirBands[j]; + idx = max( d - 1, 0 ); + error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[sf] - q_direction[1].band_data[idx].energy_ratio[sf] * hQMetaData->twoDirBands[j]; + } + else + { + error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[sf]; + } + + if ( error_ratio_surr <= 0 ) + { + error_ratio_surr = 0; + no_cv_vec[j] = 1; + idx_ER[j] = 0; + } + else + { + idx_ER[j] = 7; // masa_sq( error_ratio_surr, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); + no_cv_vec[j] = idx_cb_sur_coh_masa[idx_ER[j]] + 2; + } + } + + if ( sum_s( no_cv_vec, coding_subbands ) == coding_subbands ) + { + /* surround coherence is zero */ + for ( j = 0; j < coding_subbands; j++ ) + { + for ( k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + { + if ( hQMetaData->surcoh_band_data != NULL ) + { + hQMetaData->surcoh_band_data[j].surround_coherence[k] = 0; + } + } + } + } + else + { + /* read how the surround coherence is encoded */ + byteBuffer = bitstream[bit_pos--]; + bits_sur_coherence += 1; + + if ( byteBuffer & 1 ) + { + /* GR decoding */ + /* read GR order */ + byteBuffer = bitstream[bit_pos--]; + bits_sur_coherence += 1; - decode_fixed_rate_composed_index_coherence( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); + /* read min index */ + bits_GR = bit_pos; + min_index = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, MASA_MAX_NO_CV_SUR_COH, 0 ); + bits_sur_coherence += bits_GR - bit_pos; - for ( j = 0; j < coding_subbands; j++ ) - { - hQMetaData->surcoh_band_data[j].sur_coherence_index = sur_coh_temp_index[j]; - } + /* read GR data */ + for ( j = 0; j < coding_subbands; j++ ) + { + bits_GR = bit_pos; + /* decoding for min removed */ + if ( no_cv_vec[j] > 1 ) + { + idx_sur_coh[j] = ivas_qmetadata_DecodeExtendedGR( bitstream, &bit_pos, no_cv_vec[j] - min_index, ( byteBuffer & 1 ) ); + bits_sur_coherence += bits_GR - bit_pos; + } + else + { + idx_sur_coh[j] = 0; + } + } - /* deindex surround coherence */ - for ( j = 0; j < coding_subbands; j++ ) - { - if ( no_cv_vec[j] > 1 ) - { - hQMetaData->surcoh_band_data[j].surround_coherence[0] = sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER[j]] * MASA_MAX_NO_CV_SUR_COH + hQMetaData->surcoh_band_data[j].sur_coherence_index]; + for ( j = 0; j < coding_subbands; j++ ) + { + if ( no_cv_vec[j] > 1 ) + { + hQMetaData->surcoh_band_data[j].sur_coherence_index = idx_sur_coh[j] + min_index; + hQMetaData->surcoh_band_data[j].surround_coherence[sf] = sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER[j]] * MASA_MAX_NO_CV_SUR_COH + hQMetaData->surcoh_band_data[j].sur_coherence_index]; + } + else + { + hQMetaData->surcoh_band_data[j].sur_coherence_index = idx_sur_coh[j]; + hQMetaData->surcoh_band_data[j].surround_coherence[sf] = 0; + } + } } else { - hQMetaData->surcoh_band_data[j].surround_coherence[0] = 0; - } - } - } + /* fixed rate */ + uint16_t sur_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + set_s( (int16_t *) sur_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); - for ( j = 0; j < coding_subbands; j++ ) - { - for ( k = 1; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) - { - hQMetaData->surcoh_band_data[j].surround_coherence[k] = hQMetaData->surcoh_band_data[j].surround_coherence[0]; +#ifdef IVAS_FLOAT_FIXED + decode_fixed_rate_composed_index_coherence_fx( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); +#else + decode_fixed_rate_composed_index_coherence( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); +#endif + + for ( j = 0; j < coding_subbands; j++ ) + { + hQMetaData->surcoh_band_data[j].sur_coherence_index = sur_coh_temp_index[j]; + } + + /* deindex surround coherence */ + for ( j = 0; j < coding_subbands; j++ ) + { + if ( no_cv_vec[j] > 1 ) + { + hQMetaData->surcoh_band_data[j].surround_coherence[sf] = sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER[j]] * MASA_MAX_NO_CV_SUR_COH + hQMetaData->surcoh_band_data[j].sur_coherence_index]; + } + else + { + hQMetaData->surcoh_band_data[j].surround_coherence[sf] = 0; + } + } + } } } @@ -3804,31 +6672,25 @@ static int16_t read_surround_coherence( return bits_sur_coherence; } - -/*-------------------------------------------------------------------* - * read_surround_coherence_hr() - * - * - *-------------------------------------------------------------------*/ - -static int16_t read_surround_coherence_hr( - uint16_t *bitstream, /* i : bitstream */ - int16_t *p_bit_pos, /* i : position in the bitstream */ - IVAS_QMETADATA *hQMetaData /* i/o: quantized metadata structure */ -) +#ifdef IVAS_FLOAT_FIXED +static Word16 read_surround_coherence_hr_fx( + UWord16 *bitstream, /* i : bitstream */ + Word16 *p_bit_pos, /* i : position in the bitstream */ + IVAS_QMETADATA *hQMetaData, /* i/o: quantized metadata structure */ + Word16 *q ) { - int16_t coding_subbands; - int16_t no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t bit_pos; - float error_ratio_surr; - int16_t idx_ER[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t bits_sur_coherence, bits_GR; - int16_t j, k, sf; - uint16_t byteBuffer; - uint16_t idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 coding_subbands; + Word16 no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 bit_pos; + Word32 error_ratio_surr_fx; + Word16 idx_ER[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 bits_sur_coherence, bits_GR; + Word16 j, k, sf; + UWord16 byteBuffer; + UWord16 idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; IVAS_QDIRECTION *q_direction; - int16_t min_index; - int16_t d, idx; + Word16 min_index; + Word16 d, idx; coding_subbands = hQMetaData->q_direction[0].cfg.nbands; q_direction = hQMetaData->q_direction; @@ -3840,21 +6702,23 @@ static int16_t read_surround_coherence_hr( d = 0; for ( j = 0; j < coding_subbands; j++ ) { - error_ratio_surr = 1.0f; + error_ratio_surr_fx = 1 << *q; if ( hQMetaData->no_directions == 2 ) { d += hQMetaData->twoDirBands[j]; idx = max( d - 1, 0 ); - error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[sf] - q_direction[1].band_data[idx].energy_ratio[sf] * hQMetaData->twoDirBands[j]; + error_ratio_surr_fx = L_sub( + L_sub( 1 << *q, q_direction[0].band_data[j].energy_ratio_fx[sf] ), + q_direction[1].band_data[idx].energy_ratio_fx[sf] * hQMetaData->twoDirBands[j] ); } else { - error_ratio_surr = 1.0f - q_direction[0].band_data[j].energy_ratio[sf]; + error_ratio_surr_fx = L_sub( 1 << *q, q_direction[0].band_data[j].energy_ratio_fx[sf] ); } - if ( error_ratio_surr <= 0 ) + if ( error_ratio_surr_fx <= 53667 ) // Assuming max error of 10^(-4) in q = 29 => 10^(-4) * 2^(29) { - error_ratio_surr = 0; + error_ratio_surr_fx = 0; no_cv_vec[j] = 1; idx_ER[j] = 0; } @@ -3930,10 +6794,10 @@ static int16_t read_surround_coherence_hr( else { /* fixed rate */ - uint16_t sur_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; - set_s( (int16_t *) sur_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); + UWord16 sur_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; + set_s( (Word16 *) sur_coh_temp_index, 0, MASA_MAXIMUM_CODING_SUBBANDS ); - decode_fixed_rate_composed_index_coherence( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); + decode_fixed_rate_composed_index_coherence_fx( bitstream, &bit_pos, coding_subbands, no_cv_vec, sur_coh_temp_index, MASA_MAX_NO_CV_SUR_COH ); for ( j = 0; j < coding_subbands; j++ ) { @@ -3962,7 +6826,7 @@ static int16_t read_surround_coherence_hr( return bits_sur_coherence; } - +#endif /*-------------------------------------------------------------------* * decode_combined_index() @@ -3997,6 +6861,35 @@ static void decode_combined_index( return; } +#ifdef IVAS_FLOAT_FIXED +static void decode_combined_index_fx( + UWord64 comb_index, /* i : index to be decoded */ + const Word16 *no_cv_vec, /* i : number of codewords for each element*/ + UWord16 *index, /* o : decoded indexes */ + const Word16 len /* i : number of elements */ +) +{ + Word16 i; + UWord64 base[MASA_MAXIMUM_CODING_SUBBANDS + 1]; + + base[0] = 1; + FOR( i = 1; i < len; i++ ) + { + base[i] = base[i - 1] * no_cv_vec[i - 1]; + } + + FOR( i = len - 1; i > 0; i-- ) + { + index[i] = (UWord16) ( comb_index / base[i] ); + comb_index -= index[i] * base[i]; + } + + index[0] = (UWord16) comb_index; + + return; +} +#endif + static void read_stream_dct_coeffs_omasa( int16_t *q_idx, @@ -4095,6 +6988,105 @@ static void read_stream_dct_coeffs_omasa( return; } +#ifdef IVAS_FLOAT_FIXED +static void read_stream_dct_coeffs_omasa_fx( + Word16 *q_idx, + Word32 *q_dct_data_fx, + const Word16 len_stream, + UWord16 *bit_stream, + Word16 *index, + const Word16 first_line ) +{ + Word16 sign, nbits; + Word16 i, j, i_min; + + Word32 step; + Word16 GR1, GR2; + + step = STEP_M2T_FX; + nbits = 0; + sign = 1; + IF( first_line == 0 ) + { + /* read sign */ + sign = bit_stream[( *index )--]; + IF( sign == 0 ) + { + sign = -1; + } + nbits++; + } + + set_s( q_idx, 0, len_stream ); + /* read DCT 0 component */ + FOR( i = 0; i < BITS_MASA2TOTTAL_DCT0; i++ ) + { + q_idx[0] = add( shl( q_idx[0], 1 ), bit_stream[( *index )--] ); + } + q_idx[0] *= sign; + + IF( q_idx[0] != 0 ) + { + IF( len_stream >= 8 ) + { + /* read index of last index encoded with GR2 */ + i_min = 0; + j = 4; + FOR( i = 0; i < j; i++ ) + { + i_min = ( i_min << 1 ) + bit_stream[( *index )--]; + } + nbits += j; + /* read GR orders */ + GR1 = bit_stream[( *index )--] + 1; + IF( GR1 == 2 ) + { + GR2 = bit_stream[( *index )--]; + } + ELSE + { + GR2 = 0; + } + + /* read GR data */ + FOR( i = 1; i <= i_min; i++ ) + { + q_idx[i] = ivas_qmetadata_DecodeExtendedGR( bit_stream, index, 100, GR1 ); + } + FOR( i = i_min + 1; i < len_stream; i++ ) + { + q_idx[i] = ivas_qmetadata_DecodeExtendedGR( bit_stream, index, 100, GR2 ); + } + } + ELSE + { + /* read GR order (only one) */ + GR1 = bit_stream[( *index )--]; + FOR( i = 1; i < len_stream; i++ ) + { + q_idx[i] = ivas_qmetadata_DecodeExtendedGR( bit_stream, index, 100, GR1 ); + } + } + } + + /* deindex */ + q_dct_data_fx[0] = L_shl( Mpy_32_16_1( step, q_idx[0] ), 2 ); // q = 18 + FOR( i = 1; i < len_stream; i++ ) + { + IF( ( q_idx[i] % 2 ) == 0 ) + { + q_dct_data_fx[i] = L_shl( Mpy_32_16_1( step, negate( shr( q_idx[i], 1 ) ) ), 2 ); + } + ELSE + { + q_dct_data_fx[i] = L_shl( Mpy_32_16_1( step, shr( q_idx[i] + 1, 1 ) ), 2 ); + } + } + + return; +} +#endif + /*------------------------------------------------------------------------- * ivas_omasa_decode_masa_to_total() @@ -4160,7 +7152,6 @@ void ivas_omasa_decode_masa_to_total( printf( "Incorrect number of coefficients for OMASA.\n" ); break; } - k = 0; for ( i = 0; i < nblocks; i++ ) { @@ -4196,3 +7187,101 @@ void ivas_omasa_decode_masa_to_total( return; } + +#ifdef IVAS_FLOAT_FIXED +void ivas_omasa_decode_masa_to_total_fx( + UWord16 *bit_stream, + Word16 *index, + Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + const Word16 nbands, + const Word16 nblocks, + Word16 *q ) +{ + Word16 i, j, k; + Word16 q_idx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; + Word32 q_dct_data_fx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS], // q = 18 + dct_data_tmp_fx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; // q = 18 + Word16 n_streams, len_stream; + + /* Setup coding parameters */ + n_streams = 1; + len_stream = nbands * nblocks; + IF( len_stream == 32 ) + { + n_streams = 4; + len_stream = 8; + } + + set_s( q_idx, 0, nbands * nblocks ); + FOR( i = 0; i < n_streams; i++ ) + { + read_stream_dct_coeffs_omasa_fx( &q_idx[i * len_stream], &q_dct_data_fx[i * len_stream], len_stream, bit_stream, index, i == 0 ); + } + + /* inverse DCT2 transform */ + SWITCH( len_stream ) + { + case 4: + matrix_product_fx( dct4_fx, nblocks, nblocks, 1, q_dct_data_fx, nblocks, 1, 0, dct_data_tmp_fx ); + Copy32( dct_data_tmp_fx, q_dct_data_fx, nblocks ); + BREAK; + case 5: + matrix_product_fx( dct5_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + Copy32( dct_data_tmp_fx, q_dct_data_fx, nbands ); + BREAK; + case 8: + matrix_product_fx( dct8_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + Copy32( dct_data_tmp_fx, q_dct_data_fx, nbands ); + BREAK; + case 12: + matrix_product_fx( dct12_fx, nbands, nbands, 1, q_dct_data_fx, nbands, 1, 0, dct_data_tmp_fx ); + Copy32( dct_data_tmp_fx, q_dct_data_fx, nbands ); + BREAK; + case 20: + matrix_product_fx( dct5_fx, nbands, nbands, 1, q_dct_data_fx, nbands, nblocks, 0, dct_data_tmp_fx ); + matrix_product_fx( dct_data_tmp_fx, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data_fx ); /* reuse of variable*/ + BREAK; + case 32: + matrix_product_fx( dct8_fx, nbands, nbands, 1, q_dct_data_fx, nbands, nblocks, 0, dct_data_tmp_fx ); + matrix_product_fx( dct_data_tmp_fx, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data_fx ); + BREAK; + default: + printf( "Incorrect number of coefficients for OMASA.\n" ); + BREAK; + } + k = 0; + FOR( i = 0; i < nblocks; i++ ) + { + FOR( j = 0; j < nbands; j++ ) + { + masa_to_total_energy_ratio_fx[i][j] = L_max( 0, L_shl( q_dct_data_fx[k], *q - 18 ) ); + masa_to_total_energy_ratio_fx[i][j] = L_min( 1 << *q, masa_to_total_energy_ratio_fx[i][j] ); + k++; + } + } + + IF( nblocks == 1 ) + { + FOR( i = 1; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + FOR( j = 0; j < nbands; j++ ) + { + masa_to_total_energy_ratio_fx[i][j] = masa_to_total_energy_ratio_fx[0][j]; + } + } + } + + IF( nbands == 1 ) + { + FOR( j = 1; j < 5; j++ ) + { + FOR( i = 0; i < nblocks; i++ ) + { + masa_to_total_energy_ratio_fx[i][j] = masa_to_total_energy_ratio_fx[i][0]; + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_qspherical_dec.c b/lib_dec/ivas_qspherical_dec.c index a3dc21f0c3c12666c62a917f5f80c896c6433c42..8173a24f3ff6d942e6221bcbcb23e297829efac7 100644 --- a/lib_dec/ivas_qspherical_dec.c +++ b/lib_dec/ivas_qspherical_dec.c @@ -95,3 +95,58 @@ float deindex_elevation( return theta_hat; } + +#ifdef IVAS_FLOAT_FIXED +Word32 deindex_elevation_fx( + UWord16 *id_th, /* i : input index */ + const Word16 no_bits, /* i : number of bits for the spherical grid */ + const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ +) +{ + Word32 theta_hat_fx; + Word16 q_id_th = norm_l( *id_th ) - 1; + Word32 id_th_fx = L_shl( *id_th, q_id_th ); + + IF( *id_th == MASA_NO_INDEX ) + { + theta_hat_fx = 0; + } + ELSE + { + IF( mc_format != MC_LS_SETUP_INVALID ) + { + theta_hat_fx = L_shl( Mpy_32_32( id_th_fx, delta_theta_masa_fx[no_bits - 3] ), 31 - q_id_th ); + IF( theta_hat_fx > L_shl( 90, 22 ) ) + { + theta_hat_fx = L_shl( 90, 22 ); + } + } + ELSE + { + IF( *id_th % 2 == 0 ) + { + /* theta is negative */ + *id_th = *id_th / 2; + id_th_fx = id_th_fx / 2; + theta_hat_fx = L_negate( L_shl( Mpy_32_32( id_th_fx, delta_theta_masa_fx[no_bits - 3] ), 31 - q_id_th ) ); + IF( theta_hat_fx < L_shl( -90, 22 ) ) + { + theta_hat_fx = L_shl( -90, 22 ); + } + } + ELSE + { + *id_th = ( *id_th + 1 ) / 2; + id_th_fx = ( id_th_fx + ( 1 << q_id_th ) ) / 2; + theta_hat_fx = L_shl( Mpy_32_32( id_th_fx, delta_theta_masa_fx[no_bits - 3] ), 31 - q_id_th ); + IF( theta_hat_fx > L_shl( 90, 22 ) ) + { + theta_hat_fx = L_shl( 90, 22 ); + } + } + } + } + + return theta_hat_fx; +} +#endif \ No newline at end of file diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index d350ec18c0c086f0e13ac927225dfab56aa85820..3b04a0afcfc5d3e11b5922ac9bce0a4c03eaee7a 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -86,11 +86,11 @@ typedef struct stereo_dft_dec_data_struct const float *dft_trigo_8k; int16_t dft_trigo_step; - int16_t dft32ms_ovl; /* Overlap size */ - const float *win32ms; /* DFT window */ - const float *win32ms_12k8; /* DFT window */ - const float *win32ms_16k; /* DFT window */ - const float *win32ms_8k; /* DFT window */ + int16_t dft32ms_ovl; /* Overlap size */ + const float *win32ms; /* DFT window */ + const float *win32ms_12k8; /* DFT window */ + const float *win32ms_16k; /* DFT window */ + const float *win32ms_8k; /* DFT window */ int16_t dft32ms_ovl2; /* Overlap2 size */ const float *win232ms; /* DFT window */ @@ -98,7 +98,7 @@ typedef struct stereo_dft_dec_data_struct const float *win232ms_16k; /* DFT window */ const float *win232ms_8k; /* DFT window */ - const float *win_8k; /* DFT window residual */ + const float *win_8k; /* DFT window residual */ /*Bands*/ int16_t band_res[STEREO_DFT_DEC_DFT_NB]; @@ -266,18 +266,18 @@ typedef struct stereo_td_dec_data_structure int16_t tdm_SM_flag; /* current channel combination scheme flag */ int16_t tdm_use_IAWB_Ave_lpc; /* Flag to indicate the usage of mean inactive LP coefficients */ - int16_t tdm_lp_reuse_flag; /* Flag that indicate if it is possible to reuse the LP coefficient from the primary channel or not */ - int16_t tdm_low_rate_mode; /* secondary channel low rate mode flag */ + int16_t tdm_lp_reuse_flag; /* Flag that indicate if it is possible to reuse the LP coefficient from the primary channel or not */ + int16_t tdm_low_rate_mode; /* secondary channel low rate mode flag */ float tdm_Pri_pitch_buf[NB_SUBFR]; int16_t tdm_Pitch_reuse_flag; int16_t tdm_LRTD_flag; - int16_t flag_skip_DMX; /* flag that indicates whether the TD downmixing is skipped */ + int16_t flag_skip_DMX; /* flag that indicates whether the TD downmixing is skipped */ float TCX_old_syn_Overl[L_FRAME16k / 2]; /* past ovrl buffer for possible switching from TD stereo ACELP to MDCT stereo TCX frame */ - float prevSP_ratio; /* previous SP ratio */ - float SP_ratio_LT; /* longterm SP ratio */ - float c_LR_LT; /* left-right cross-correlation */ + float prevSP_ratio; /* previous SP ratio */ + float SP_ratio_LT; /* longterm SP ratio */ + float c_LR_LT; /* left-right cross-correlation */ } STEREO_TD_DEC_DATA, *STEREO_TD_DEC_DATA_HANDLE; @@ -298,7 +298,7 @@ typedef struct stereo_mdct_dec_data_structure int16_t global_ild[2]; /* Quantized ILD for the whole spectrum */ int16_t split_ratio; /* Ratio of bitrate (1 to 7), split_ratio = 8 * 1st chn bitrate / (1st + 2nd chn bitrate) */ - int16_t IGFStereoMode[2]; /* MDCT stereo mode for IGF */ + int16_t IGFStereoMode[2]; /* MDCT stereo mode for IGF */ int16_t use_itd; int16_t itd_mode; /*0/1*/ @@ -322,21 +322,21 @@ typedef struct stereo_mdct_dec_data_structure typedef struct stereo_tca_dec_data_structure { - int16_t refChanIndx; /* reference channel index in current frame */ - int16_t prevRefChanIndx; /* reference channel index in previous frame */ - int16_t indx_ica_NCShift; /* ICA target channel inter-channel corrstats */ - int16_t indx_ica_gD; /* ICA target gain */ - float targetGain; /* gain norm applied on target (or right) channel in current frame */ - float prevTargetGain; /* gain norm applied on target (or right) channel in previous frame */ + int16_t refChanIndx; /* reference channel index in current frame */ + int16_t prevRefChanIndx; /* reference channel index in previous frame */ + int16_t indx_ica_NCShift; /* ICA target channel inter-channel corrstats */ + int16_t indx_ica_gD; /* ICA target gain */ + float targetGain; /* gain norm applied on target (or right) channel in current frame */ + float prevTargetGain; /* gain norm applied on target (or right) channel in previous frame */ - int16_t corrLagStats; /* corr lag stats in current frame */ - int16_t prevCorrLagStats; /* corr lag stats in previous frame */ + int16_t corrLagStats; /* corr lag stats in current frame */ + int16_t prevCorrLagStats; /* corr lag stats in previous frame */ int16_t interp_dec_prevNCShift; /* NC Shift in previous frame */ int16_t interp_dec_switch_to_zero_diff; /* switch flag for interpolation */ - float memChanL[L_DEC_MEM_LEN_ICA]; /* left channel input to correct at the cross-over */ - float memChanR[L_DEC_MEM_LEN_ICA]; /* right channel input to correct at the cross-over */ + float memChanL[L_DEC_MEM_LEN_ICA]; /* left channel input to correct at the cross-over */ + float memChanR[L_DEC_MEM_LEN_ICA]; /* right channel input to correct at the cross-over */ } STEREO_TCA_DEC_DATA, *STEREO_TCA_DEC_HANDLE; @@ -457,7 +457,7 @@ typedef struct dirac_output_synthesis_cov_state_structure float *diffuse_power_factor; /* only pointer to local buffers */ - float *direct_responses; /* direct responses for DOA of current frame. Size: num_freq_bands*num_channels. */ + float *direct_responses; /* direct responses for DOA of current frame. Size: num_freq_bands*num_channels. */ float *direct_responses_square; float *diffuse_responses_square; /* squared diffuse responses. Size: num_channels. */ @@ -705,8 +705,8 @@ typedef struct cpe_dec_data_structure int32_t element_brate; /* CPE element total bitrate in bps */ int32_t last_element_brate; /* last CPE element total bitrate in bps */ - int16_t element_mode; /* element mode, in CPE it can be IVAS_CPE_DFT, IVAS_CPE_TD or IVAS_CPE_MDCT */ - int16_t last_element_mode; /* last element mode */ + int16_t element_mode; /* element mode, in CPE it can be IVAS_CPE_DFT, IVAS_CPE_TD or IVAS_CPE_MDCT */ + int16_t last_element_mode; /* last element mode */ int16_t stereo_switching_counter; int16_t NbFrameMod; @@ -724,7 +724,7 @@ typedef struct cpe_dec_data_structure STEREO_ICBWE_DEC_HANDLE hStereoICBWE; /* Stereo inter-channel BWE data handle */ STEREO_CNG_DEC_HANDLE hStereoCng; /* Stereo CNG data structure */ - int16_t nchan_out; /* number of output channels (1: mono dmx, 2: default stereo) */ + int16_t nchan_out; /* number of output channels (1: mono dmx, 2: default stereo) */ float prev_hb_synth[CPE_CHANNELS][NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )]; float prev_synth[CPE_CHANNELS][NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS )]; @@ -760,7 +760,7 @@ typedef struct mct_dec_block_data_struct typedef struct mct_dec_data_structure { - int16_t nchan_out_woLFE; /* number of active channels within multi-channel configuration */ + int16_t nchan_out_woLFE; /* number of active channels within multi-channel configuration */ int16_t currBlockDataCnt; int16_t bitsChannelPairIndex; /* bits needed to code channel pair index, depends on number of active channels */ MCT_DEC_BLOCK_DATA_HANDLE hBlockData[MCT_MAX_BLOCKS]; @@ -874,7 +874,9 @@ typedef struct ivas_masa_ism_data_structure int16_t elevation_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR]; float energy_ratio_ism[MAX_NUM_OBJECTS][MAX_PARAM_SPATIAL_SUBFRAMES + DELAY_MASA_PARAM_DEC_SFR][CLDFB_NO_CHANNELS_MAX]; float masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; - +#ifdef IVAS_FLOAT_FIXED + Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; +#endif int16_t azimuth_ism_edited[MAX_NUM_OBJECTS]; int16_t elevation_ism_edited[MAX_NUM_OBJECTS]; uint8_t ism_is_edited[MAX_NUM_OBJECTS]; @@ -906,16 +908,16 @@ typedef struct ivas_masa_ism_data_structure typedef struct decoder_tc_buffer_structure { - float *tc_buffer; /* the buffer itself */ + float *tc_buffer; /* the buffer itself */ float *tc[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc */ // VE2SB: TBV - TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ - int16_t nchan_transport_jbm; /* number of TCs after TC decoding */ - int16_t nchan_transport_internal; /* total number of TC buffer channels, can include e.g. TD decorr data */ - int16_t nchan_buffer_full; /* number of channels to be fully buffered */ - int16_t n_samples_available; /* samples still available for rendering in the current frame */ - int16_t n_samples_buffered; /* full number of samples in the buffer (including spill to next frame) */ - int16_t n_samples_rendered; /* samples already rendered in the current frame */ - int16_t n_samples_granularity; /* render granularity */ + TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ + int16_t nchan_transport_jbm; /* number of TCs after TC decoding */ + int16_t nchan_transport_internal; /* total number of TC buffer channels, can include e.g. TD decorr data */ + int16_t nchan_buffer_full; /* number of channels to be fully buffered */ + int16_t n_samples_available; /* samples still available for rendering in the current frame */ + int16_t n_samples_buffered; /* full number of samples in the buffer (including spill to next frame) */ + int16_t n_samples_rendered; /* samples already rendered in the current frame */ + int16_t n_samples_granularity; /* render granularity */ int16_t n_samples_flushed; int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; int16_t nb_subframes; @@ -947,8 +949,6 @@ typedef struct jbm_metadata_structure } JBM_METADATA, *JBM_METADATA_HANDLE; - - /*----------------------------------------------------------------------------------* * Decoder configuration structure *----------------------------------------------------------------------------------*/ @@ -971,9 +971,9 @@ typedef struct decoder_config_structure int16_t Opt_ExternalOrientation; /* indiates whether external orientations are used */ int16_t Opt_dpid_on; /* indicates whether Directivity pattern option is used */ int16_t Opt_aeid_on; /* indicates whether Acoustic environment option is used */ - int16_t Opt_tsm; /* indicates whether time scaling modification is activated */ + int16_t Opt_tsm; /* indicates whether time scaling modification is activated */ IVAS_RENDER_FRAMESIZE render_framesize; - int16_t Opt_delay_comp; /* flag indicating delay compensation active */ + int16_t Opt_delay_comp; /* flag indicating delay compensation active */ } DECODER_CONFIG, *DECODER_CONFIG_HANDLE;