From b807c11f3e9610b628f02b35277ae178eb009dec Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Mon, 22 Jan 2024 10:12:37 +0530 Subject: [PATCH 1/2] Metadata decode changes [x] Few functions in ivas_qmetadata_com, ivas_qmetadata_dec, ivas_dirac_dec and ivas_spar_decoder converted to fixed. [x] Few intermediate float functions are present which needs to be cleaned up/updated. [x] Partial metadata path up. --- lib_com/cnst.h | 5 + lib_com/ivas_cnst.h | 1 + lib_com/ivas_dirac_com.c | 4 +- lib_com/ivas_masa_com.c | 315 ++-- lib_com/ivas_prot.h | 24 +- lib_com/ivas_prot_fx.h | 6 + lib_com/ivas_qmetadata_com.c | 77 + lib_com/ivas_qspherical_com.c | 73 +- lib_com/ivas_rom_com.c | 114 ++ lib_com/ivas_rom_com.h | 6 + lib_com/ivas_stat_com.h | 4 + lib_com/prot_fx1.h | 58 +- lib_com/prot_fx2.h | 13 + lib_com/tools_fx.c | 158 ++ lib_dec/ivas_dirac_dec.c | 217 ++- lib_dec/ivas_masa_dec.c | 150 +- lib_dec/ivas_qmetadata_dec.c | 2945 ++++++++++++++++++++++----------- lib_dec/ivas_spar_decoder.c | 40 +- 18 files changed, 2924 insertions(+), 1286 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index d4e8d02b4..84ea9e34b 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -119,10 +119,15 @@ #define ONE_IN_Q30 1073741824 #define ONE_IN_Q31 0x7fffffff +#define MAX_WORD16 32767 +#define ONE_IN_Q62 (Word64)0x4000000000000000 /*----------------------------------------------------------------------------------* * General constants *----------------------------------------------------------------------------------*/ +#define DEGREE_180_Q_22 754974720 +#define DEGREE_360_Q_22 1509949440 + #define MODE1 1 #define MODE2 2 diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 39e8a6d88..acade335c 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -903,6 +903,7 @@ typedef enum { #define DIRAC_LOW_BANDRES_STEP 2 /* always combine two bands for low band resolution in the DirAC parameter coding */ #define DIRAC_NO_COL_AVG_DIFF 32 /* Number of slots for averaging intensity vector for diffuseness computation */ #define DIRAC_DIFFUSE_LEVELS 8 /* Size of the diffuseness alphabet (constant value) */ +#define INV_DIRAC_DIFFUSE_LEVELS_Q13 1170 /* 1/(DIRAC_DIFFUSE_LEVELS - 1) in Q13 */ #define DIRAC_DITH_SEED 29680 #define DIRAC_MAX_BITS 512 /* Maximum number of bits for DirAC side information per frame */ #define MAX_NUM_ENC_CLDFB_INSTANCES 8 /* Maximum Cldfb instances in DirAC encoder */ diff --git a/lib_com/ivas_dirac_com.c b/lib_com/ivas_dirac_com.c index 378e679f4..d1576eb8f 100644 --- a/lib_com/ivas_dirac_com.c +++ b/lib_com/ivas_dirac_com.c @@ -883,9 +883,7 @@ void deindex_spherical_component_fx( 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 ); + *az_fx = L_shl((*az_idx) * (-180), 22); *el_fx = 0; *el_idx = 0; BREAK; diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index 6a5f2529a..4c519ae45 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -389,9 +389,17 @@ void masa_sample_rate_band_correction( for ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) { hQMetaData->q_direction[0].band_data[band].azimuth[sf] = 0.0f; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = 0; +#endif hQMetaData->q_direction[0].band_data[band].elevation[sf] = 0.0f; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = 0; +#endif hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = 0.0f; - +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = 0; +#endif if ( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL ) { hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = 0u; @@ -400,8 +408,17 @@ void masa_sample_rate_band_correction( if ( hQMetaData->no_directions == 2 ) { hQMetaData->q_direction[1].band_data[band].azimuth[sf] = 0.0f; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf] = 0; +#endif hQMetaData->q_direction[1].band_data[band].elevation[sf] = 0.0f; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[1].band_data[band].elevation_fx[sf] = 0; +#endif hQMetaData->q_direction[1].band_data[band].energy_ratio[sf] = 0.0f; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[sf] = 0; +#endif if ( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL ) { @@ -791,152 +808,156 @@ 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 +void deindex_sph_idx_fx( + const uint16_t sphIndex, /* i : Spherical index */ + const SPHERICAL_GRID_DATA *gridData, /* i : Prepared spherical grid */ + Word32 *theta_fx, /* o : Elevation */ + Word32 *phi_fx /* o : Azimuth */ +) +{ + // temp conversion as function using sin and cos + float theta = (float) *theta_fx / ( 1 << 22 ); + float phi = (float) *phi_fx / ( 1 << 22 ); + + + float ba_crt, del_crt, div_crt, a4_crt; + float estim; + int32_t base_low, base_up; + int16_t n_crt; + int16_t id_th; + int16_t sign_theta; + int16_t id_phi; + int16_t no_th = gridData->no_theta; + const int16_t *n = gridData->no_phi; + const float ba[3] = { 2.137991118026424e+02f, 1.244854404591542e+02f, 1.228408647140870e+02f }; + const float del[3] = { 7.998262115303199e+05f, 1.300883976959332e+06f, 1.424072242426373e+06f }; + const float div[3] = { -0.237662341081474f, -0.100938185496887f, -0.092050209205032f }; + const float a4[3] = { -8.415300425381099f, -19.814106922515204f, -21.727272727270197f }; + const uint16_t limit_index1 = 64964, limit_index2 = 47870; + + if ( sphIndex >= limit_index1 ) + { + ba_crt = ba[2]; + div_crt = div[2]; + a4_crt = a4[2]; + del_crt = del[2]; + } + else if ( sphIndex >= limit_index2 ) + { + ba_crt = ba[1]; + div_crt = div[1]; + a4_crt = a4[1]; + del_crt = del[1]; + } + else + { + ba_crt = ba[0]; + div_crt = div[0]; + a4_crt = a4[0]; + del_crt = del[0]; + } + estim = ba_crt + div_crt * 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; + } + } + } + *theta_fx = theta * ( 1 << 22 ); + *phi_fx = phi * ( 1 << 22 ); + return; +} /*--------------------------------------------------------------- * valid_ratio_index() diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index bc9f951e2..54b681adb 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3225,6 +3225,12 @@ void deindex_sph_idx( float *theta, /* o : Elevation */ float *phi /* o : Azimuth */ ); +void deindex_sph_idx_fx( + const uint16_t sphIndex, /* i : Spherical index */ + const SPHERICAL_GRID_DATA *gridData, /* i : Prepared spherical grid */ + Word32 *theta_fx, /* o : Elevation */ + Word32 *phi_fx /* o : Azimuth */ +); /*! r: output index for direction */ uint16_t index_theta_phi_16( @@ -3335,6 +3341,11 @@ void ivas_qmetadata_azimuth_elevation_to_direction_vector( const float el, /* i : elevation */ float *dv /* o : direction vector */ ); +void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( + const Word32 az, /* i : azimuth */ + const Word32 el, /* i : elevation */ + Word32 *dv /* o : direction vector */ +); void ivas_qmetadata_direction_vector_to_azimuth_elevation( const float *dv, /* i : direction vector */ @@ -3342,6 +3353,12 @@ void ivas_qmetadata_direction_vector_to_azimuth_elevation( float *el /* o : elevation */ ); +void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( + const Word32 *dv, /* i : direction vector */ + const Word32 div_q, + Word32 *az, /* o : azimuth */ + Word32 *el /* o : elevation */ +); ivas_error only_reduce_bits_direction( int16_t *reduce_bits_out, IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ @@ -3433,7 +3450,12 @@ int16_t quantize_phi( float *phi_hat, /* o : quantized azimuth */ const int16_t n /* i : azimuth codebook size */ ); - +int16_t quantize_phi_fx( + Word32 phi, /* i : azimuth value */ + const int16_t flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */ + Word32 *phi_hat, /* o : quantized azimuth */ + const int16_t n /* i : azimuth codebook size */ +); /*! r: decoded elevation value */ float deindex_elevation( uint16_t *id_th, /* i : input index */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 8c9eb3c7c..c52d0f012 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -367,4 +367,10 @@ Word16 read_flag_EC_DFT( ); #endif +Word16 masa_sq_fx( + const Word32 in, /* i : input value */ + const Word32 *threshold, /* i : partition */ + const Word16 cb_sz /* i : codebook size */ +); + #endif \ No newline at end of file diff --git a/lib_com/ivas_qmetadata_com.c b/lib_com/ivas_qmetadata_com.c index 7ca4a37cd..2438b98b9 100644 --- a/lib_com/ivas_qmetadata_com.c +++ b/lib_com/ivas_qmetadata_com.c @@ -38,6 +38,7 @@ #include "ivas_rom_com.h" #include "ivas_prot.h" #include "prot.h" +#include "prot_fx1.h" #include "cnst.h" #include "wmc_auto.h" @@ -144,8 +145,17 @@ ivas_error ivas_qmetadata_allocate_memory( for ( j = 0; j < nbands; j++ ) { set_zero( hQMetaData->q_direction[dir].band_data[j].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef IVAS_FLOAT_FIXED + set32_fx( hQMetaData->q_direction[dir].band_data[j].elevation_fx,0, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif set_zero( hQMetaData->q_direction[dir].band_data[j].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef IVAS_FLOAT_FIXED + set32_fx( hQMetaData->q_direction[dir].band_data[j].azimuth_fx,0, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif set_zero( hQMetaData->q_direction[dir].band_data[j].energy_ratio, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef IVAS_FLOAT_FIXED + set32_fx( hQMetaData->q_direction[dir].band_data[j].energy_ratio_fx,0, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif } } @@ -280,6 +290,26 @@ int16_t masa_sq( return -1; } +#ifdef IVAS_FLOAT_FIXED +Word16 masa_sq_fx( + const Word32 in, /* i : input value */ + const Word32 *threshold, /* i : partition */ + const Word16 cb_sz /* i : codebook size */ +) +{ + Word16 i; + + FOR( i = 0; i < cb_sz; i++ ) + { + IF( LT_32( in, threshold[i + 1] ) ) + { + return i; + } + } + + return -1; +} +#endif // IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * only_reduce_bits_direction() @@ -621,6 +651,30 @@ void ivas_qmetadata_azimuth_elevation_to_direction_vector( return; } +void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( + const Word32 az, /* i : azimuth */ + const Word32 el, /* i : elevation */ + Word32 *dv /* o : direction vector */ +) +{ + float radius_length; + + float temp_az, temp_el; + float temp_dv[3]; + temp_az = (float)az / (1 << 22); + temp_el = (float)el / (1 << 22); + temp_dv[2] = sinf(temp_el * PI_OVER_180); + radius_length = cosf(temp_el * PI_OVER_180); + temp_dv[0] = radius_length * cosf(temp_az * PI_OVER_180); + temp_dv[1] = radius_length * sinf(temp_az * PI_OVER_180); + + dv[0] = (Word32)(temp_dv[0] * (1 << 30)); + dv[1] = (Word32)(temp_dv[1] * (1 << 30)); + dv[2] = (Word32)(temp_dv[2] * (1 << 30)); + + return; +} + /*------------------------------------------------------------------------- * ivas_qmetadata_direction_vector_to_azimuth_elevation() * @@ -642,6 +696,29 @@ void ivas_qmetadata_direction_vector_to_azimuth_elevation( return; } +void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( + const Word32 *dv, /* i : direction vector */ + const Word32 dv_q, + Word32 *az, /* o : azimuth */ + Word32 *el /* o : elevation */ +) +{ + /* note: dv does not need to have unit L_2 norm, because the conversion is scale invariant */ + + + float temp_dv[3]; + temp_dv[0] = (float)dv[0] / (1 << dv_q); + temp_dv[1] = (float)dv[1] / (1 << dv_q); + temp_dv[2] = (float)dv[2] / (1 << dv_q); + float temp_az, temp_el; + temp_el = atan2f(temp_dv[2], sqrtf(temp_dv[0] * temp_dv[0] + temp_dv[1] * temp_dv[1])) * _180_OVER_PI; + temp_az = atan2f(temp_dv[1], temp_dv[0]) * _180_OVER_PI; + + *az = (Word32)(temp_az * (1 << 22)); + *el = (Word32)(temp_el * (1 << 22)); + return; +} + /*------------------------------------------------------------------------- * ivas_get_df_ratio_bits_hodirac() diff --git a/lib_com/ivas_qspherical_com.c b/lib_com/ivas_qspherical_com.c index 9ef7a7a7e..2815c2662 100644 --- a/lib_com/ivas_qspherical_com.c +++ b/lib_com/ivas_qspherical_com.c @@ -213,8 +213,8 @@ void small_reduction_direction( * Quantize azimuth. * Input phi expected to be an angle in degree between 0 and 360. *-----------------------------------------------------------------------*/ - /*! r: index azimuth */ + int16_t quantize_phi( float phi, /* i : azimuth value */ const int16_t flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */ @@ -282,8 +282,79 @@ int16_t quantize_phi( return id_phi; } +#ifdef IVAS_FLOAT_FIXED +Word16 quantize_phi_fx( + Word32 phi, /* i : azimuth value */ + const Word16 flag_delta, /* i : flag indicating if the azimuth codebook is translated or not */ + Word32 *phi_hat, /* o : quantized azimuth */ + const Word16 n /* i : azimuth codebook size */ +) +{ + Word16 id_phi; + Word32 dd_fx; + Word32 delta_phi_fx; + Word32 inv_delta_phi_fx; + Word32 temp_res; + + delta_phi_fx = delta_phi_val[n]; + inv_delta_phi_fx = inv_delta_phi_val[n]; + IF ( n == 1 ) + { + *phi_hat = 0; + + return 0; + } + + IF ( ( flag_delta == 1 ) && ( n > 2 ) ) + { + dd_fx = dd_val[n]; + } + ELSE + { + dd_fx = 0; + } + + temp_res = Mpy_32_32( L_sub( L_sub( phi, DEGREE_180_Q_22 ), dd_fx ), inv_delta_phi_fx ); + id_phi = round_fx( L_shr( temp_res, 22 - 16 ) ); + assert( L_sub( L_abs( temp_res ), abs( id_phi ) * ONE_IN_Q22 ) <= ONE_IN_Q21 ); + + IF ( id_phi + ( n >> 1 ) < 0 ) + { + id_phi += 1; + } + + IF ( id_phi - ( n >> 1 ) >= 0 ) + { + id_phi = -( n >> 1 ); + } + + IF ( id_phi == -( ( n >> 1 ) + ( n % 2 ) ) ) + { + id_phi += ( n % 2 ); + } + ELSE + { + IF ( id_phi == ( ( n >> 1 ) + ( n % 2 ) ) ) + { + IF ( n % 2 ) + { + id_phi -= 1; + } + ELSE + { + id_phi = -id_phi; + } + } + } + + *phi_hat = L_add( L_add( ( id_phi * delta_phi_fx ), dd_fx ), DEGREE_180_Q_22 ); + id_phi += ( n >> 1 ); + + return id_phi; +} +#endif /*-----------------------------------------------------------------------* * companding_azimuth() * diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index cb0a240d8..15b707d3f 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -855,6 +855,21 @@ const float diffuseness_thresholds[DIRAC_DIFFUSE_LEVELS + 1] = 2.0f /* out-of-range large value to make searching easier */ }; +#ifdef IVAS_FLOAT_FIXED +const Word32 diffuseness_thresholds_fx[DIRAC_DIFFUSE_LEVELS + 1] = +{ + 0, + 20447232, + 67633152, + 128188416, + 237502464, + 428605440, + 587988992, + 788791296, + MAX_32 /* out-of-range large value to make searching easier */ +}; +#endif // IVAS_FLOAT_FIXED + const int16_t DirAC_band_grouping_12[12 + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 11, 17, 25, 40, 60 @@ -2566,6 +2581,45 @@ const float diffuseness_thresholds_hr[HR_MASA_ER_LEVELS + 1] = 0.8673095703125f, 2.0f /* out-of-range large value to make searching easier */ }; +const Word64 diffuseness_reconstructions_hr_fx[HR_MASA_ER_LEVELS] = { /* Q62 */ + 0, + 65865144550293504, + 138485688541642752, + 239816680157478912, + 355502895585558528, + 485544334825881600, + 667940119734386688, + 902690250311073792, + 1225260573621485568, + 1635651089665622016, + 2011983133527769088, + 2354256705207926784, + 2741003323208368128, + 3172222987529093120, + 3693796119373938688, + 4305722718742904832, +}; + +const Word32 diffuseness_thresholds_hr_fx[HR_MASA_ER_LEVELS + 1] = { /* Q30 */ + 0, + 10223616, + 20447232, + 44040192, + 67633152, + 97910784, + 128188416, + 182845440, + 237502464, + 333053952, + 428605440, + 508297216, + 587988992, + 688390144, + 788791296, + 931266560, + MAX_32 /* out-of-range large value to make searching easier */ +}; + const int16_t bits_direction_masa[DIRAC_DIFFUSE_LEVELS] = { 11, @@ -2842,6 +2896,66 @@ 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 }; +const Word32 delta_phi_val[90] = +{ 0, 1509949440, 754974720, 503316480, 377487360, 301989888, +251658240, 215707056, 188743680, 167772160, 150994944, +137268128, 125829120, 116149960, 107853528, 100663296, +94371840, 88820552, 83886080, 79471024, 75497472, +71902352, 68634064, 65649976, 62914560, 60397976, +58074980, 55924052, 53926764, 52067224, 50331648, +48708048, 47185920, 45756044, 44410276, 43141412, +41943040, 40809444, 39735512, 38716652, 37748736, +36828036, 35951176, 35115104, 34317032, 33554432, +32824988, 32126584, 31457280, 30815294, 30198988, +29606852, 29037490, 28489612, 27962026, 27453626, +26963382, 26490342, 26033612, 25592364, 25165824, +24753270, 24354024, 23967452, 23592960, 23229992, +22878022, 22536558, 22205138, 21883326, 21570706, +21266894, 20971520, 20684238, 20404722, 20132660, +19867756, 19609732, 19358326, 19113284, 18874368, +18641352, 18414018, 18192162, 17975588, 17764112, +17557552, 17355740, 17158516, 16965724 }; + +const Word32 inv_delta_phi_val[90] = +{ 0, 5965232, 11930464, 17895697, 23860929, 29826161, +35791394, 41756626, 47721858, 53687091, 59652323, +65617555, 71582788, 77548020, 83513252, 89478485, +95443717, 101408950, 107374182, 113339414, 119304647, +125269879, 131235111, 137200344, 143165576, 149130808, +155096041, 161061273, 167026505, 172991738, 178956970, +184922203, 190887435, 196852667, 202817900, 208783132, +214748364, 220713597, 226678829, 232644061, 238609294, +244574526, 250539758, 256504991, 262470223, 268435456, +274400688, 280365920, 286331153, 292296385, 298261617, +304226850, 310192082, 316157314, 322122547, 328087779, +334053011, 340018244, 345983476, 351948708, 357913941, +363879173, 369844406, 375809638, 381774870, 387740103, +393705335, 399670567, 405635800, 411601032, 417566264, +423531497, 429496729, 435461961, 441427194, 447392426, +453357659, 459322891, 465288123, 471253356, 477218588, +483183820, 489149053, 495114285, 501079517, 507044750, +513009982, 518975214, 524940447, 530905679, }; + +const Word32 dd_val[90] = +{ 0, 754974720, 377487360, 251658240, 188743680, 150994944, +125829120, 107853528, 94371840, 83886080, 75497472, +68634064, 62914560, 58074980, 53926764, 50331648, +47185920, 44410276, 41943040, 39735512, 37748736, +35951176, 34317032, 32824988, 31457280, 30198988, +29037490, 27962026, 26963382, 26033612, 25165824, +24354024, 23592960, 22878022, 22205138, 21570706, +20971520, 20404722, 19867756, 19358326, 18874368, +18414018, 17975588, 17557552, 17158516, 16777216, +16412494, 16063292, 15728640, 15407647, 15099494, +14803426, 14518745, 14244806, 13981013, 13726813, +13481691, 13245171, 13016806, 12796182, 12582912, +12376635, 12177012, 11983726, 11796480, 11614996, +11439011, 11268279, 11102569, 10941663, 10785353, +10633447, 10485760, 10342119, 10202361, 10066330, +9933878, 9804866, 9679163, 9556642, 9437184, +9320676, 9207009, 9096081, 8987794, 8882056, +8778776, 8677870, 8579258, 8482862 }; + #ifdef IVAS_FLOAT_FIXED const Word32 cb_azi_chan_fx[] = { 0, 125829120, 461373440, 566231040 }; #endif diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 6e2a7bae4..04b80872e 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -152,6 +152,7 @@ extern const int16_t dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1]; #ifdef IVAS_FLOAT_FIXED extern const Word32 diffuseness_reconstructions_fx[DIRAC_DIFFUSE_LEVELS]; +extern const Word32 diffuseness_thresholds_fx[DIRAC_DIFFUSE_LEVELS + 1]; #endif extern const float diffuseness_reconstructions[DIRAC_DIFFUSE_LEVELS]; @@ -308,6 +309,8 @@ extern const uint8_t masa_twodir_bands_joined[]; extern const float diffuseness_reconstructions_hr[HR_MASA_ER_LEVELS]; extern const float diffuseness_thresholds_hr[HR_MASA_ER_LEVELS + 1]; +extern const Word64 diffuseness_reconstructions_hr_fx[HR_MASA_ER_LEVELS]; +extern const Word32 diffuseness_thresholds_hr_fx[HR_MASA_ER_LEVELS + 1]; /* Multi-channel input and output setups */ extern const float ls_azimuth_CICP2[2]; @@ -324,6 +327,9 @@ extern const float ls_azimuth_CICP19[11]; extern const float ls_elevation_CICP19[11]; extern const float cb_azi_chan[]; +extern const Word32 delta_phi_val[90]; +extern const Word32 inv_delta_phi_val[90]; +extern const Word32 dd_val[90]; #ifdef IVAS_FLOAT_FIXED extern const Word32 cb_azi_chan_fx[]; #endif diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 60c309854..c94c94d72 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -547,7 +547,11 @@ typedef struct ivas_masa_qmetadata_frame_struct int16_t sba_inactive_mode; /* Status values on metadata quality */ int16_t ec_flag; +#ifndef IVAS_FLOAT_FIXED float dir_comp_ratio; +#else + Word16 dir_comp_ratio_fx; +#endif uint8_t is_masa_ivas_format; } IVAS_QMETADATA, *IVAS_QMETADATA_HANDLE; diff --git a/lib_com/prot_fx1.h b/lib_com/prot_fx1.h index 7759ee870..8f69b205e 100644 --- a/lib_com/prot_fx1.h +++ b/lib_com/prot_fx1.h @@ -300,11 +300,59 @@ void fir_fx( const Word16 x[], /* i : input vector , Word16 shift /* i : difference between Q15 and scaling of h[] */ ); -Word16 squant_fx( /* o: index of the winning codeword */ - const Word16 x, /* i: scalar value to quantize */ - Word16 *xq, /* o: quantized value */ - const Word16 cb[], /* i: codebook */ - const Word16 cbsize /* i: codebook size */ + +void fir_fx(const Word16 x[], /* i : input vector Qx*/ + const Word16 h[], /* i : impulse response of the FIR filter Q12*/ + Word16 y[], /* o : output vector (result of filtering) Qx*/ + Word16 mem[], /* i/o: memory of the input signal (L samples) Qx*/ + const Word16 L, /* i : input vector size */ + const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */ + const Word16 upd /* i : 1 = update the memory, 0 = not */ + , Word16 shift /* i : difference between Q15 and scaling of h[] */ +); + +void v_add_32( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +); + +void v_shr_32( + Word32 x1[], /* i : Input vector 1 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N, /* i : Vector length */ + Word16 shift /*shift value*/ +); + +void v_sub_32( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N /* i : Vector length */ +); + + +void v_add_16( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +); + +void v_sub_16( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N /* i : Vector length */ +); + + +Word16 squant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize */ + Word16* xq, /* o: quantized value */ + const Word16 cb[], /* i: codebook */ + const Word16 cbsize /* i: codebook size */ ); void pz_filter_dp_fx( const Word16 b[], diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index d906fcb3e..3c1f56148 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -126,6 +126,19 @@ void Copy( Word16 y[], /* o : output vector */ const Word16 L /* i : vector length */ ); + +void set64_fx( + Word64 y[], /* i/o: Vector to set */ + const Word64 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +); + +void Copy64( + const Word64 x[], /* i : input vector */ + Word64 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +); + void Copy_pword( const PWord16 x[], /* i : input vector */ PWord16 y[], /* o : output vector */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 702b456e1..e3d99e01d 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -45,6 +45,7 @@ #include "stl.h" #include #include "cnst.h" +#include "prot_fx.h" #include "prot_fx1.h" #include "prot_fx2.h" #include "basop_util.h" @@ -315,6 +316,51 @@ void Copy( } } } +/*-------------------------------------------------------------------* + * Copy64: + * + * Copy vector x[] to y[] (64 bits) + *-------------------------------------------------------------------*/ +void Copy64( + const Word64 x[], /* i : input vector */ + Word64 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +) +{ + Word16 i; + IF( y < x ) + { + FOR( i = 0; i < L; i++ ) + { + y[i] = x[i]; + move64(); + } + } + ELSE + { + FOR( i = L - 1; i >= 0; i-- ) + { + y[i] = x[i]; + move64(); + } + } +} + +void set64_fx( + Word64 y[], /* i/o: Vector to set */ + const Word64 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +) +{ + Word16 i; + FOR( i = 0; i < N; i++ ) + { + y[i] = a; + move64(); + } + + return; +} void Copy_pword( const PWord16 x[], /* i : input vector */ @@ -1967,6 +2013,118 @@ void fir_fx( const Word16 x[], /* i : input vector } } +/*-------------------------------------------------------------------* + * v_add_32() + * + * Addition of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_add_32( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = x1[i] + x2[i]; + } + + return; +} + +void v_shr_32( + Word32 x1[], /* i : Input vector 1 */ + Word32 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N, /* i : Vector length */ + Word16 shift /*shift value*/ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = L_shr( x1[i], shift ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * v_sub_32() + * + * Subtraction of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_sub_32( + const Word32 x1[], /* i : Input vector 1 */ + const Word32 x2[], /* i : Input vector 2 */ + Word32 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = x1[i] - x2[i]; + } + + return; +} + + +/*-------------------------------------------------------------------* + * v_add_16() + * + * Addition of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_add_16( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = x1[i] + x2[i]; + } + + return; +} + + +/*-------------------------------------------------------------------* + * v_sub_16() + * + * Subtraction of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void v_sub_16( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ + const Word16 N /* i : Vector length */ +) +{ + Word16 i; + + for ( i = 0; i < N; i++ ) + { + y[i] = x1[i] - x2[i]; + } + + return; +} + /*--------------------------------------------------------------------------------*/ /* squant_fx() */ diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index ec74f1b1a..86245537b 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -36,6 +36,8 @@ #include #include "cnst.h" #include "prot.h" +#include "prot_fx1.h" +#include "prot_fx2.h" #include "ivas_prot.h" #include "ivas_prot_rend.h" #include "ivas_cnst.h" @@ -948,7 +950,144 @@ void ivas_dirac_dec_close( * * Read DirAC parameters from the bitstream *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_dirac_dec_read_BS( + const Word32 ivas_total_brate, /* i : IVAS total bitrate */ + Decoder_State *st, /* i/o: decoder state structure */ + DIRAC_DEC_HANDLE hDirAC, /* i/o: decoder DirAC handle */ + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, /* i/o: common spatial rendering data handle */ + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata */ + Word16 *nb_bits, /* o : number of bits read */ + const Word16 last_bit_pos, /* i : last read bitstream position */ + const Word16 hodirac_flag, /* i : flag to indicate HO-DirAC mode */ + Word16 *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ +) +{ + Word16 i, j, b, dir, orig_dirac_bands; + Word16 next_bit_pos_orig; + + IF( !st->bfi && ivas_total_brate > IVAS_SID_5k2 ) + { + next_bit_pos_orig = st->next_bit_pos; + st->next_bit_pos = (Word16) ( ivas_total_brate / FRAMES_PER_SEC - 1 ); + IF( last_bit_pos > 0 ) + { + st->next_bit_pos = last_bit_pos; + } + /* 1 bit flag for signaling metadata to read */ + b = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits )++; + + IF( b == 1 ) /* WB 4TCs condition, no other metadata to read*/ + { + orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; + + hQMetaData->sba_inactive_mode = 1; + + /* if we start with a SID frame, we need to init the azi/ele arrays.*/ + IF( st->ini_frame == 0 ) + { + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + set32_fx( hQMetaData->q_direction[0].band_data[b].azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set32_fx( hQMetaData->q_direction[0].band_data[b].elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT ); + + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth_fx[i] = hQMetaData->q_direction[0].band_data[1].azimuth_fx[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation_fx[i] = hQMetaData->q_direction[0].band_data[1].elevation_fx[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio_fx[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio_fx[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio_index[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio_index[0]; + } + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + FOR( j = orig_dirac_bands - 2; j >= 0; j-- ) + { + hQMetaData->q_direction[0].band_data[j].azimuth_fx[i] = hQMetaData->q_direction[0].band_data[0].azimuth_fx[0]; + hQMetaData->q_direction[0].band_data[j].elevation_fx[i] = hQMetaData->q_direction[0].band_data[0].elevation_fx[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio_fx[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio_index[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio_index[0]; + } + } + + hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + } + ELSE + { + hQMetaData->sba_inactive_mode = 0; + hQMetaData->is_masa_ivas_format = 0; + IF( hQMetaData->useLowerRes ) + { + hQMetaData->q_direction[0].cfg.nblocks = 1; + } + ELSE + { + hQMetaData->q_direction[0].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; + } + *nb_bits += ivas_qmetadata_dec_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), hodirac_flag ); + } + + st->next_bit_pos = next_bit_pos_orig; + } + ELSE IF( !st->bfi && ivas_total_brate == IVAS_SID_5k2 ) + { + next_bit_pos_orig = st->next_bit_pos; + + /* subtract mode signaling bits, since bitstream was moved after mode reading */ + st->next_bit_pos = (Word16) ( ivas_total_brate / FRAMES_PER_SEC - 1 - SID_FORMAT_NBITS ); + /* 1 bit flag for signaling metadata to read */ + b = st->bit_stream[( st->next_bit_pos )--]; + ( *nb_bits )++; + hQMetaData->sba_inactive_mode = 1; + orig_dirac_bands = hQMetaData->q_direction[0].cfg.nbands; + + /* if we start with a SID frame, we need to init the azi/ele arrays.*/ + IF( st->ini_frame == 0 ) + { + FOR( dir = 0; dir < hQMetaData->no_directions; dir++ ) + { + FOR( b = 0; b < hQMetaData->q_direction[dir].cfg.nbands; b++ ) + { + set32_fx( hQMetaData->q_direction[dir].band_data[b].azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set32_fx( hQMetaData->q_direction[dir].band_data[b].elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + *nb_bits += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), 0, NULL, SBA_FORMAT ); + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].azimuth_fx[i] = hQMetaData->q_direction[0].band_data[1].azimuth_fx[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].elevation_fx[i] = hQMetaData->q_direction[0].band_data[1].elevation_fx[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio_fx[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio_fx[0]; + hQMetaData->q_direction[0].band_data[orig_dirac_bands - 1].energy_ratio_index[i] = hQMetaData->q_direction[0].band_data[1].energy_ratio_index[0]; + } + FOR( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + FOR( j = orig_dirac_bands - 2; j >= 0; j-- ) + { + hQMetaData->q_direction[0].band_data[j].azimuth_fx[i] = hQMetaData->q_direction[0].band_data[0].azimuth_fx[0]; + hQMetaData->q_direction[0].band_data[j].elevation_fx[i] = hQMetaData->q_direction[0].band_data[0].elevation_fx[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio_fx[0]; + hQMetaData->q_direction[0].band_data[j].energy_ratio_index[i] = hQMetaData->q_direction[0].band_data[0].energy_ratio_index[0]; + } + } + + hQMetaData->q_direction->cfg.nbands = orig_dirac_bands; + + st->next_bit_pos = next_bit_pos_orig; + } + + IF( hDirAC != NULL && hSpatParamRendCom != NULL ) + { + ivas_qmetadata_to_dirac_fx( hQMetaData, hDirAC, NULL, hSpatParamRendCom, ivas_total_brate, SBA_FORMAT, hodirac_flag, dirac_to_spar_md_bands, 30 ); + } + return; +} +#else void ivas_dirac_dec_read_BS( const int32_t ivas_total_brate, /* i : IVAS total bitrate */ Decoder_State *st, /* i/o: decoder state structure */ @@ -1080,84 +1219,14 @@ void ivas_dirac_dec_read_BS( st->next_bit_pos = next_bit_pos_orig; } - if (hDirAC != NULL && hSpatParamRendCom != NULL) + if ( hDirAC != NULL && hSpatParamRendCom != NULL ) { -#ifdef IVAS_FLOAT_FIXED - //Word32 q = 15; - - //if (hQMetaData->q_direction[0].band_data != NULL) { - // for (int sf = 0; sf < hQMetaData->q_direction[0].cfg.nblocks; sf++) - // { - // for (j = 0; j < hQMetaData->q_direction[0].cfg.nbands; j++) - // { - // if (fabs(hQMetaData->q_direction[0].band_data[j].energy_ratio[sf]) >= 1) - // { - // q = min(q, norm_l((Word32)hQMetaData->q_direction[0].band_data[j].energy_ratio[sf])); - // } - // } - // } - //} - // - //if (hQMetaData->q_direction[1].band_data != NULL) { - // for (int sf = 0; sf < hQMetaData->q_direction[1].cfg.nblocks; sf++) - // { - // for (j = 0; j < hQMetaData->q_direction[1].cfg.nbands; j++) - // { - // if (fabs(hQMetaData->q_direction[1].band_data[j].energy_ratio[sf]) >= 1) - // { - // q = min(q, norm_l((Word32)hQMetaData->q_direction[1].band_data[j].energy_ratio[sf])); - // } - // } - // } - //} - //q -= 1; // guarded bits - //if (hQMetaData->q_direction[0].band_data != NULL) { - // for (int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++) - // { - // for (j = 0; j < hQMetaData->q_direction[0].cfg.nbands; j++) - // { - // hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[sf] = float_to_fix(hQMetaData->q_direction[0].band_data[j].energy_ratio[sf], q); - // } - // } - //} - - //if (hQMetaData->q_direction[1].band_data != NULL) { - // for (int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++) - // { - // for (j = 0; j < hQMetaData->q_direction[1].cfg.nbands; j++) - // { - // hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[sf] = float_to_fix(hQMetaData->q_direction[1].band_data[j].energy_ratio[sf], q); - // } - // } - //} - - for (int d = 0; d < hQMetaData->no_directions; d++) - { - IVAS_QDIRECTION *q_direction; - q_direction = &hQMetaData->q_direction[d]; - int nbands = q_direction->cfg.nbands; - //int nblocks = q_direction->cfg.nblocks; - FOR( j = 0; j < nbands; j++) - { - FOR(Word16 k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++) - { - q_direction->band_data[j].elevation_fx[k] = (Word32)(q_direction->band_data[j].elevation[k] * (1 << 22)); - q_direction->band_data[j].azimuth_fx[k] = (Word32)(q_direction->band_data[j].azimuth[k] * (1 << 22)); - q_direction->band_data[j].energy_ratio_fx[k] = (Word32)(q_direction->band_data[j].energy_ratio[k] * (1 << 30)); - } - } - } - - ivas_qmetadata_to_dirac_fx(hQMetaData, hDirAC, NULL, hSpatParamRendCom, ivas_total_brate, SBA_FORMAT, hodirac_flag, dirac_to_spar_md_bands, 30); - -#else - ivas_qmetadata_to_dirac(hQMetaData, hDirAC, NULL, hSpatParamRendCom, ivas_total_brate, SBA_FORMAT, hodirac_flag, dirac_to_spar_md_bands); -#endif - + ivas_qmetadata_to_dirac( hQMetaData, hDirAC, NULL, hSpatParamRendCom, ivas_total_brate, SBA_FORMAT, hodirac_flag, dirac_to_spar_md_bands ); } + return; } - +#endif /*-----------------------------------------------------------------------* * ivas_qmetadata_to_dirac() * diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index d4f669746..822d2ef96 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -349,7 +349,23 @@ ivas_error ivas_masa_decode( { masa_total_brate = calculate_cpe_brate_MASA_ISM( st_ivas->ism_mode, ivas_total_brate, st_ivas->nchan_ism ); } - +#ifdef IVAS_FLOAT_FIXED + // To do remove this code + for ( int d = 0; d < hQMetaData->no_directions; d++ ) + { + IVAS_QDIRECTION *q_direction; + q_direction = &hQMetaData->q_direction[d]; + int nbands = hQMetaData->q_direction[0].cfg.nbands; + 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] = (Word32) ( q_direction->band_data[j].elevation[k] * ( 1 << 22 ) ); + q_direction->band_data[j].azimuth_fx[k] = (Word32) ( q_direction->band_data[j].azimuth[k] * ( 1 << 22 ) ); + } + } + } +#endif if ( masa_total_brate >= IVAS_384k ) { if ( masa_total_brate >= IVAS_512k ) @@ -365,7 +381,25 @@ ivas_error ivas_masa_decode( { *nb_bits_read += ivas_qmetadata_dec_decode( hQMetaData, st->bit_stream, &st->next_bit_pos, 0 ); } +#ifdef IVAS_FLOAT_FIXED + // To do remove this code + for ( int d = 0; d < hQMetaData->no_directions; d++ ) + { + IVAS_QDIRECTION *q_direction; + q_direction = &hQMetaData->q_direction[d]; + int nbands = hQMetaData->q_direction[0].cfg.nbands; + 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] / ( 1 << 22 ) ); + q_direction->band_data[j].azimuth[k] = ( (float) q_direction->band_data[j].azimuth_fx[k] / ( 1 << 22 ) ); + q_direction->band_data[j].energy_ratio[k] = ( (float) q_direction->band_data[j].energy_ratio_fx[k] / ( 1 << 30 ) ); + } + } + } +#endif if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) { /* Modify spatial metadata based on the MASA-to-total energy ratios */ @@ -375,7 +409,11 @@ ivas_error ivas_masa_decode( /* Get direction decoding quality. EC 1 and 2 are handled by the default value. */ if ( hQMetaData->ec_flag == 2 ) { +#ifndef IVAS_FLOAT_FIXED hMasa->data.dir_decode_quality = hQMetaData->dir_comp_ratio; +#else + hMasa->data.dir_decode_quality = (float)hQMetaData->dir_comp_ratio_fx/(1<<15); +#endif } hMasa->config.coherencePresent = !hQMetaData->all_coherence_zero; @@ -431,7 +469,43 @@ ivas_error ivas_masa_decode( } tmp_elem_mode = -1; +#ifdef IVAS_FLOAT_FIXED + for (int d = 0; d < hQMetaData->no_directions; d++) + { + IVAS_QDIRECTION *q_direction; + q_direction = &hQMetaData->q_direction[d]; + int nbands = hQMetaData->q_direction[0].cfg.nbands; + 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] = (Word32)(q_direction->band_data[j].elevation[k] * (1 << 22)); + q_direction->band_data[j].azimuth_fx[k] = (Word32)(q_direction->band_data[j].azimuth[k] * (1 << 22)); + q_direction->band_data[j].energy_ratio_fx[k] = (Word32)(q_direction->band_data[j].energy_ratio[k] * (1 << 30)); + } + } + } +#endif *nb_bits_read += ivas_qmetadata_dec_sid_decode( hQMetaData, st->bit_stream, &( st->next_bit_pos ), st_ivas->nchan_transport, &tmp_elem_mode, ivas_format ); +#ifdef IVAS_FLOAT_FIXED + for (int d = 0; d < hQMetaData->no_directions; d++) + { + IVAS_QDIRECTION *q_direction; + q_direction = &hQMetaData->q_direction[d]; + int nbands = hQMetaData->q_direction[0].cfg.nbands; + 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] / (1 << 22)); + q_direction->band_data[j].azimuth[k] = ((float)q_direction->band_data[j].azimuth_fx[k] / (1 << 22)); + q_direction->band_data[j].energy_ratio[k] = ((float)q_direction->band_data[j].energy_ratio_fx[k] / (1 << 30)); + + } + } + } +#endif if ( st_ivas->nchan_transport == 2 ) { assert( st_ivas->nCPE > 0 ); @@ -455,52 +529,6 @@ ivas_error ivas_masa_decode( dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */ #ifdef IVAS_FLOAT_FIXED - //Word32 q = 15; - - //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 (fabs(hQMetaData->q_direction[0].band_data[j].energy_ratio[sf]) >= 1) - // { - // q = min(q, norm_l((Word32)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 (fabs(hQMetaData->q_direction[1].band_data[j].energy_ratio[sf]) >= 1) - // { - // q = min(q, norm_l((Word32)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] = float_to_fix(hQMetaData->q_direction[0].band_data[j].energy_ratio[sf], 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] = float_to_fix(hQMetaData->q_direction[1].band_data[j].energy_ratio[sf], q); - // } - //} - //if (hQMetaData->no_directions == 2 && (hMasa != NULL && ivas_total_brate > IVAS_SID_5k2)) { - // for (int sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++) - // { - // for (int j = 0; j < hMasa->config.numCodingBands; j++) - // { - // hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[sf] = float_to_fix(hQMetaData->q_direction[1].band_data[j].energy_ratio[sf], q); - // } - // } - //} for (int d = 0; d < hQMetaData->no_directions; d++) { IVAS_QDIRECTION *q_direction; @@ -975,9 +1003,18 @@ static void replicate_subframes( for ( dir = 0; dir < ndirs; dir++ ) { hQMetaData->q_direction[dir].band_data[band].azimuth[sf] = hQMetaData->q_direction[dir].band_data[band].azimuth[0]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[dir].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[dir].band_data[band].azimuth_fx[0]; +#endif hQMetaData->q_direction[dir].band_data[band].elevation[sf] = hQMetaData->q_direction[dir].band_data[band].elevation[0]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[dir].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[dir].band_data[band].elevation_fx[0]; +#endif hQMetaData->q_direction[dir].band_data[band].spherical_index[sf] = hQMetaData->q_direction[dir].band_data[band].spherical_index[0]; hQMetaData->q_direction[dir].band_data[band].energy_ratio[sf] = hQMetaData->q_direction[dir].band_data[band].energy_ratio[0]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[dir].band_data[band].energy_ratio_fx[sf] = hQMetaData->q_direction[dir].band_data[band].energy_ratio_fx[0]; +#endif if ( hQMetaData->q_direction[dir].coherence_band_data != NULL ) { @@ -1011,10 +1048,20 @@ static void restore_lowbitrate_masa( { for ( band = 0; band < numCodingBands; band++ ) { + hQMetaData->q_direction[0].band_data[band].azimuth[sf] = hQMetaData->q_direction[0].band_data[band].azimuth[0]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[0].band_data[band].azimuth_fx[0]; +#endif hQMetaData->q_direction[0].band_data[band].elevation[sf] = hQMetaData->q_direction[0].band_data[band].elevation[0]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[0].band_data[band].elevation_fx[0]; +#endif hQMetaData->q_direction[0].band_data[band].spherical_index[sf] = hQMetaData->q_direction[0].band_data[band].spherical_index[0]; hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = hQMetaData->q_direction[0].band_data[band].energy_ratio[0]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0]; +#endif if ( hQMetaData->q_direction[0].coherence_band_data != NULL ) { hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[0]; @@ -1036,9 +1083,18 @@ static void restore_lowbitrate_masa( for ( band = 1; band < numCodingBands; band++ ) { hQMetaData->q_direction[0].band_data[band].azimuth[sf] = hQMetaData->q_direction[0].band_data[0].azimuth[sf]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[0].band_data[0].azimuth_fx[sf]; +#endif hQMetaData->q_direction[0].band_data[band].elevation[sf] = hQMetaData->q_direction[0].band_data[0].elevation[sf]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[0].band_data[0].elevation_fx[sf]; +#endif hQMetaData->q_direction[0].band_data[band].spherical_index[sf] = hQMetaData->q_direction[0].band_data[0].spherical_index[sf]; hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = hQMetaData->q_direction[0].band_data[0].energy_ratio[sf]; +#ifdef IVAS_FLOAT_FIXED + hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = hQMetaData->q_direction[0].band_data[0].energy_ratio_fx[sf]; +#endif if ( hQMetaData->q_direction[0].coherence_band_data != NULL ) { hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[0].coherence_band_data[0].spread_coherence[sf]; diff --git a/lib_dec/ivas_qmetadata_dec.c b/lib_dec/ivas_qmetadata_dec.c index 6e6b7b380..23c701e6a 100644 --- a/lib_dec/ivas_qmetadata_dec.c +++ b/lib_dec/ivas_qmetadata_dec.c @@ -42,135 +42,69 @@ #include "prot.h" #include "prot_fx1.h" +#include "prot_fx2.h" +#include "ivas_prot_fx.h" /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED static Word16 ivas_qmetadata_entropy_decode_diffuseness( UWord16 *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 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 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 - -#ifndef IVAS_FLOAT_FIXED -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 ); - -static int16_t read_common_direction( uint16_t *bitstream, IVAS_QDIRECTION *q_direction, const int16_t j, const int16_t no_subframes, const int16_t bits_total, int16_t *pbit_pos ); - - -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 ); -#endif - -static int16_t decode_fixed_rate( IVAS_QDIRECTION *q_direction, const uint16_t *bitstream, int16_t *pbit_pos, const int16_t b, const int16_t nblocks ); - -#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 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 decode_azimuth_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, Word16 *pbit_pos, const Word16 idx_subband, const Word16 masa_subframes ); - +static Word16 decode_fixed_rate_fx( IVAS_QDIRECTION *q_direction, const UWord16 *bitstream, Word16 *pbit_pos, const Word16 b, const Word16 nblocks ); +static Word16 ivas_qmetadata_entropy_decode_diffuseness_hr_512( UWord16 *bitstream, Word16 *index, IVAS_QDIRECTION *q_direction ); +static Word16 ivas_qmetadata_entropy_decode_dir_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, Word16 *index, const UWord16 diffuseness_index_max_ec_frame, const Word16 nbands, const Word16 start_band, const Word16 hrmasa_flag ); +static Word16 read_surround_coherence_hr_fx( UWord16 *bitstream, Word16 *p_bit_pos, IVAS_QMETADATA *hQMetaData, Word64 energy_ratio[][MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_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, Word16 idx_d, const Word16 no_frames, const Word16 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 ); +static Word16 ivas_qmetadata_raw_decode_dir_512_fx( IVAS_QDIRECTION *q_direction, UWord16 *bitstream, Word16 *index, const Word16 nbands, const Word16 start_band, const SPHERICAL_GRID_DATA *sph_grid16 ); +static Word16 read_surround_coherence( UWord16 *bitstream, Word16 *p_bit_pos, IVAS_QMETADATA *hQMetaData ); +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 ); +const Word16 inv_dfRatio_qsteps[9] = { 0, 0, ONE_IN_Q14, 0, 5461, 0, 0, 0, 2341 }; // Q14 -#endif - -#ifndef IVAS_FLOAT_FIXED +#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 ); +static int16_t ivas_qmetadata_entropy_decode_df_ratio( uint16_t *bitstream, int16_t *index, IVAS_QDIRECTION *q_direction, int16_t *dfRatio_bits ); +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 ); +static uint16_t ivas_qmetadata_DecodeQuasiUniform( const uint16_t *bitstream, int16_t *index, const uint16_t alphabet_size ); +static int16_t ivas_qmetadata_ReorderElevationDecoded( const int16_t elev_dist, const int16_t elev_avg, const int16_t elev_alph ); +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 ); +static int16_t read_common_direction( uint16_t *bitstream, IVAS_QDIRECTION *q_direction, const int16_t j, const int16_t no_subframes, const int16_t bits_total, int16_t *pbit_pos ); +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 ); +static int16_t decode_fixed_rate( IVAS_QDIRECTION *q_direction, const uint16_t *bitstream, int16_t *pbit_pos, const int16_t b, const int16_t nblocks ); +static int16_t ivas_qmetadata_entropy_decode_diffuseness_hr_512( uint16_t *bitstream, int16_t *index, IVAS_QDIRECTION *q_direction ); +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 read_surround_coherence_hr( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData ); 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 ); - static void set_zero_direction( IVAS_QDIRECTION *q_direction, const int16_t idx_band, const int16_t len ); - 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 ); -#endif - -#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 - -#ifndef IVAS_FLOAT_FIXED -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 ); -#endif - -static int16_t read_surround_coherence( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData ); - -#ifndef IVAS_FLOAT_FIXED static void decode_spread_coherence( IVAS_QMETADATA_HANDLE hQMetaData, int16_t idx_d, const int16_t no_frames, const int16_t hrmasa_flag ); - static void decode_combined_index( uint64_t comb_index, const int16_t *no_cv_vec, uint16_t *index, const int16_t len ); - static int16_t ivas_diffuseness_huff_ec_decode( const uint16_t *bitstream, int16_t *index, int16_t av ); - static int16_t read_GR_min_removed_data( uint16_t *bitstream, int16_t *p_bit_pos, const int16_t *no_cv_vec, const int16_t no_data, int16_t *decoded_idx, const int16_t no_symb ); - 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 ); -#endif - -#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 ); - -static int16_t read_surround_coherence_hr( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData ); - -#ifndef IVAS_FLOAT_FIXED static int16_t read_coherence_data_hr_512( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData, const int16_t idx_dir, const int16_t nbits_coh ); - static void read_stream_dct_coeffs_omasa( int16_t *q_idx, float *q_dct_data, const int16_t len_stream, uint16_t *bit_stream, int16_t *index, const int16_t first_line ); +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 ); +static int16_t read_surround_coherence( uint16_t *bitstream, int16_t *p_bit_pos, IVAS_QMETADATA *hQMetaData ); +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 ); +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 ); #endif @@ -183,41 +117,41 @@ static void read_stream_dct_coeffs_omasa( int16_t *q_idx, float *q_dct_data, con * * Main function for decoding Spatial Metadata *-----------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED /*! r: number of bits read */ -int16_t ivas_qmetadata_dec_decode( +Word16 ivas_qmetadata_dec_decode( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: hQMetaData handle */ - uint16_t *bitstream, /* i : bitstream */ - int16_t *index, /* i/o: bitstream position */ - const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, /* i/o: bitstream position */ + const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */ ) { - int16_t d, b, m; - uint16_t diffuseness_index_max_ec_frame; - uint16_t diffuseness_index_max_ec_frame_pre[QMETADATA_MAX_NO_DIRECTIONS]; - int16_t bits_dir_raw_pre[QMETADATA_MAX_NO_DIRECTIONS]; - int16_t dir2band; - int16_t bits_diff_sum; - int16_t bits_diff, bits_coherence; - int16_t bits_dir_raw; - int16_t bits_dir; - int16_t nbands, nblocks, start_band; + Word16 d, b, m; + UWord16 diffuseness_index_max_ec_frame; + UWord16 diffuseness_index_max_ec_frame_pre[QMETADATA_MAX_NO_DIRECTIONS]; + Word16 bits_dir_raw_pre[QMETADATA_MAX_NO_DIRECTIONS]; + Word16 dir2band; + Word16 bits_diff_sum; + Word16 bits_diff, bits_coherence; + Word16 bits_dir_raw; + Word16 bits_dir; + Word16 nbands, nblocks, start_band; IVAS_QDIRECTION *q_direction; - int16_t start_index_0; - int16_t total_bits_1dir; - int16_t signal_bits; - int16_t bits_no_dirs_coh, bits_sur_coherence; - uint16_t all_coherence_zero; - int16_t ec_flag; - int16_t raw_flag[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t diff_bits; - int16_t dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t no_TF; - int16_t p[MASA_MAXIMUM_CODING_SUBBANDS], dif_p[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t bits_dir_target; - int16_t bits_dir_used; - int16_t reduce_bits; - int16_t ind_order[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 start_index_0; + Word16 total_bits_1dir; + Word16 signal_bits; + Word16 bits_no_dirs_coh, bits_sur_coherence; + UWord16 all_coherence_zero; + Word16 ec_flag; + Word16 raw_flag[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 diff_bits; + Word16 dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 no_TF; + Word16 p[MASA_MAXIMUM_CODING_SUBBANDS], dif_p[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 bits_dir_target; + Word16 bits_dir_used; + Word16 reduce_bits; + Word16 ind_order[MASA_MAXIMUM_CODING_SUBBANDS]; ec_flag = 0; @@ -226,25 +160,25 @@ int16_t ivas_qmetadata_dec_decode( /*Coherence flag decoding*/ bits_no_dirs_coh = 0; all_coherence_zero = 1; - if ( hQMetaData->coherence_flag ) + IF( hQMetaData->coherence_flag ) { /* read if coherence is zero */ all_coherence_zero = bitstream[( *index )--]; bits_no_dirs_coh += 1; } - hQMetaData->all_coherence_zero = (uint8_t) all_coherence_zero; + hQMetaData->all_coherence_zero = (UWord8) all_coherence_zero; - if ( hQMetaData->no_directions == 2 ) + IF( hQMetaData->no_directions == 2 ) { /* Read which bands have 2 directions */ hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands; - set_c( (int8_t *) hQMetaData->twoDirBands, 0, hQMetaData->q_direction[0].cfg.nbands ); + set_c( (Word8 *) hQMetaData->twoDirBands, 0, hQMetaData->q_direction[0].cfg.nbands ); d = *index; dif_p[0] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 0 ); p[0] = dif_p[0]; hQMetaData->twoDirBands[p[0]] = 1; - for ( b = 1; b < hQMetaData->numTwoDirBands; b++ ) + FOR( b = 1; b < hQMetaData->numTwoDirBands; b++ ) { dif_p[b] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 0 ); p[b] = p[b - 1] + dif_p[b] + 1; @@ -256,15 +190,15 @@ int16_t ivas_qmetadata_dec_decode( bits_diff_sum = 0; bits_diff_sum += ivas_qmetadata_entropy_decode_diffuseness( bitstream, index, &( hQMetaData->q_direction[0] ), &diffuseness_index_max_ec_frame_pre[0] ); - if ( hodirac_flag ) + IF( hodirac_flag ) { - if ( hQMetaData->no_directions == 2 ) + IF( hQMetaData->no_directions == 2 ) { /* Calculate bits for dfRatio */ dir2band = 0; - for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->twoDirBands[b] == 1 ) + IF( hQMetaData->twoDirBands[b] == 1 ) { dfRatio_bits[dir2band] = ivas_get_df_ratio_bits_hodirac( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] ); dir2band++; @@ -274,15 +208,15 @@ int16_t ivas_qmetadata_dec_decode( bits_diff_sum += ivas_qmetadata_entropy_decode_df_ratio( bitstream, index, &( hQMetaData->q_direction[1] ), dfRatio_bits ); } } - else + ELSE { - if ( hQMetaData->no_directions == 2 ) + IF( hQMetaData->no_directions == 2 ) { /* Calculate bits for dfRatio */ dir2band = 0; - for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->twoDirBands[b] == 1 ) + IF( hQMetaData->twoDirBands[b] == 1 ) { dfRatio_bits[dir2band] = ivas_get_df_ratio_bits( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] ); dir2band++; @@ -294,80 +228,84 @@ int16_t ivas_qmetadata_dec_decode( } /* Calculate direct-to-total energy ratios for both directions from diffuse-to-total ratio and distribution factor of direct-to-total ratios */ - if ( hQMetaData->no_directions == 2 ) + IF( hQMetaData->no_directions == 2 ) { dir2band = 0; - for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->twoDirBands[b] == 1 ) + IF( hQMetaData->twoDirBands[b] == 1 ) { - float diffRatio, dfRatio, dir1ratio, dir2ratio; - int16_t dfRatio_qsteps; + Word32 diffRatio_fx, dir1ratio_fx, dir2ratio_fx; + Word16 dfRatio_fx; + Word16 dfRatio_qsteps; + + diffRatio_fx = diffuseness_reconstructions_fx[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; // Q30 - diffRatio = diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; dfRatio_qsteps = 1 << dfRatio_bits[dir2band]; /* already encoded as total and ratios in HO-DirAC */ - if ( hodirac_flag ) + IF( hodirac_flag ) { - dfRatio = usdequant( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0], 0.0f, 1.f / ( dfRatio_qsteps - 1 ) ); - dir1ratio = 1.f - diffRatio; - dir2ratio = dfRatio; + + dfRatio_fx = usdequant_fx( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0], 0 /* Q15 */, inv_dfRatio_qsteps[dfRatio_qsteps] ); // Q15 + dir1ratio_fx = L_sub( ONE_IN_Q30, diffRatio_fx ); + dir2ratio_fx = L_shl( (Word32) dfRatio_fx, Q15 ); } - else + ELSE { - dfRatio = usdequant( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0], 0.5f, 0.5f / ( dfRatio_qsteps - 1 ) ); + dfRatio_fx = usdequant_fx( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0], shr( MAX_16, 1 ), shr( inv_dfRatio_qsteps[dfRatio_qsteps], 1 ) ); // Q15 - dir1ratio = dfRatio * ( 1.0f - diffRatio ); - dir2ratio = ( 1.0f - diffRatio ) - dir1ratio; + dir1ratio_fx = Mpy_32_16_1( L_sub( ONE_IN_Q30, diffRatio_fx ), dfRatio_fx ); // Q30 + dir2ratio_fx = L_sub( L_sub( ONE_IN_Q30, diffRatio_fx ), dir1ratio_fx ); // Q30 } /* Requantize the 1 - dirRatio separately for each direction to obtain inverted dirRatio index. These are used in further decoding. */ - hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] = masa_sq( 1.0f - dir1ratio, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); - if ( hodirac_flag ) + + hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] = masa_sq_fx( L_sub( ONE_IN_Q30, dir1ratio_fx ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); + IF( hodirac_flag ) { - float tmp; - hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0] = usquant( dir2ratio, &tmp, 0.0f, 1.f / ( DIRAC_DIFFUSE_LEVELS - 1 ), DIRAC_DIFFUSE_LEVELS ); + Word16 tmp_fx; + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0] = usquant_fx( extract_h( dir2ratio_fx ), &tmp_fx, 0, INV_DIRAC_DIFFUSE_LEVELS_Q13, DIRAC_DIFFUSE_LEVELS ); } - else + ELSE { - hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0] = masa_sq( 1.0f - dir2ratio, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0] = masa_sq_fx( L_sub( ONE_IN_Q30, dir2ratio_fx ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); } - for ( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { - hQMetaData->q_direction[0].band_data[b].energy_ratio[m] = dir1ratio; + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[m] = dir1ratio_fx; // Q30 hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; } - for ( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + FOR( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) { - hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[m] = dir2ratio; + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[m] = dir2ratio_fx; hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[m] = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0]; } dir2band++; } - else + ELSE { /* 1dir band */ - hQMetaData->q_direction[0].band_data[b].energy_ratio[0] = 1.0f - diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; - for ( m = 1; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[0] = L_sub( ONE_IN_Q30, diffuseness_reconstructions_fx[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]] ); + FOR( m = 1; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { - hQMetaData->q_direction[0].band_data[b].energy_ratio[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio[0]; + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[0]; hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; } } } } - else + ELSE { /* With 1dir band, the decoded index is directly diffuseness and we can decode to direct-to-total ratio with 1 - diff. */ - for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - hQMetaData->q_direction[0].band_data[b].energy_ratio[0] = 1.0f - diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; - for ( m = 1; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[0] = L_sub( ONE_IN_Q30, diffuseness_reconstructions_fx[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]] ); + FOR( m = 1; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { - hQMetaData->q_direction[0].band_data[b].energy_ratio[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio[0]; + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[0]; hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; } } @@ -378,25 +316,25 @@ int16_t ivas_qmetadata_dec_decode( bits_dir_raw_pre[0] = 0; bits_dir_raw_pre[1] = 0; dir2band = 0; - for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->no_directions == 2 && hQMetaData->twoDirBands[b] == 1 ) + IF( hQMetaData->no_directions == 2 && hQMetaData->twoDirBands[b] == 1 ) { - int16_t index_dirRatio1Inv, index_dirRatio2Inv, index_dirRatio1Inv_mod, index_dirRatio2Inv_mod; + Word16 index_dirRatio1Inv, index_dirRatio2Inv, index_dirRatio1Inv_mod, index_dirRatio2Inv_mod; index_dirRatio1Inv = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; index_dirRatio2Inv = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0]; masa_compensate_two_dir_energy_ratio_index( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); - for ( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { hQMetaData->q_direction[0].band_data[b].energy_ratio_index_mod[m] = index_dirRatio1Inv_mod; hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m] = bits_direction_masa[index_dirRatio1Inv_mod]; bits_dir_raw_pre[0] += hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m]; } - for ( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + FOR( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) { hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index_mod[m] = index_dirRatio2Inv_mod; hQMetaData->q_direction[1].band_data[dir2band].bits_sph_idx[m] = bits_direction_masa[index_dirRatio2Inv_mod]; @@ -405,9 +343,9 @@ int16_t ivas_qmetadata_dec_decode( dir2band++; } - else + ELSE { - for ( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { hQMetaData->q_direction[0].band_data[b].energy_ratio_index_mod[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m] = bits_direction_masa[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; @@ -416,44 +354,44 @@ int16_t ivas_qmetadata_dec_decode( } } - if ( hQMetaData->no_directions == 2 ) + IF( hQMetaData->no_directions == 2 ) { no_TF = hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks + hQMetaData->q_direction[1].cfg.nbands * hQMetaData->q_direction[1].cfg.nblocks; - if ( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff_sum >= MASA_MIN_BITS_SURR_COH ) ) + IF( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff_sum >= MASA_MIN_BITS_SURR_COH ) ) { bits_sur_coherence = read_surround_coherence( bitstream, index, hQMetaData ); } - else + ELSE { bits_sur_coherence = 0; /*Surround coherence*/ - for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->surcoh_band_data != NULL ) { - set_c( (int8_t *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_c( (Word8 *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); } } } bits_no_dirs_coh += bits_sur_coherence; total_bits_1dir = ( ( hQMetaData->metadata_max_bits - bits_no_dirs_coh ) * hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks ) / no_TF; } - else + ELSE { no_TF = hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks; - if ( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff_sum >= MASA_MIN_BITS_SURR_COH ) ) + IF( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff_sum >= MASA_MIN_BITS_SURR_COH ) ) { bits_sur_coherence = read_surround_coherence( bitstream, index, hQMetaData ); } - else + ELSE { bits_sur_coherence = 0; /*Surround coherence*/ - for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->surcoh_band_data != NULL ) { - set_c( (int8_t *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_c( (Word8 *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); } } } @@ -465,7 +403,7 @@ int16_t ivas_qmetadata_dec_decode( bits_dir_target = 0; bits_dir_used = 0; - for ( d = 0; d < hQMetaData->no_directions; d++ ) + FOR( d = 0; d < hQMetaData->no_directions; d++ ) { q_direction = &hQMetaData->q_direction[d]; nbands = q_direction->cfg.nbands; @@ -473,11 +411,11 @@ int16_t ivas_qmetadata_dec_decode( start_band = q_direction->cfg.start_band; diffuseness_index_max_ec_frame = diffuseness_index_max_ec_frame_pre[0]; - if ( d == 0 ) + IF( d == 0 ) { bits_diff = bits_diff_sum; } - else + ELSE { bits_diff = 0; } @@ -486,27 +424,23 @@ int16_t ivas_qmetadata_dec_decode( /* Read coherence, if any */ bits_coherence = 0; - if ( all_coherence_zero == 0 ) + 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 + ELSE { /*Surround coherence*/ - for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->surcoh_band_data != NULL ) { - set_c( (int8_t *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_c( (Word8 *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); } - if ( hQMetaData->q_direction[d].coherence_band_data != NULL ) + IF( hQMetaData->q_direction[d].coherence_band_data != NULL ) { - set_c( (int8_t *) hQMetaData->q_direction[d].coherence_band_data[b].spread_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + set_c( (Word8 *) hQMetaData->q_direction[d].coherence_band_data[b].spread_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); } } } @@ -517,13 +451,13 @@ int16_t ivas_qmetadata_dec_decode( /* Read EC signaling */ ec_flag = 0; - if ( total_bits_1dir + bits_sur_coherence <= hQMetaData->qmetadata_max_bit_req ) + IF( total_bits_1dir + bits_sur_coherence <= hQMetaData->qmetadata_max_bit_req ) { ec_flag = bitstream[( *index )--]; signal_bits++; - if ( nblocks > 1 ) + IF( nblocks > 1 ) { - if ( ec_flag ) + IF( ec_flag ) { ec_flag += bitstream[( *index )--]; signal_bits++; @@ -532,83 +466,26 @@ int16_t ivas_qmetadata_dec_decode( } /* Decode quantized directions frame-wise */ - if ( ec_flag == 0 ) /* EC 1*/ + IF( ec_flag == 0 ) /* EC 1*/ { bits_dir = 0; raw_flag[0] = bitstream[( *index )--]; bits_dir++; - if ( raw_flag[0] == 0 ) + IF( raw_flag[0] == 0 ) { - bits_dir += ivas_qmetadata_entropy_decode_dir( q_direction, bitstream, index, diffuseness_index_max_ec_frame, nbands, start_band, 0 ); + bits_dir += ivas_qmetadata_entropy_decode_dir_fx( q_direction, bitstream, index, diffuseness_index_max_ec_frame, nbands, start_band, 0 ); } - else + 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] = (Word32)(q_direction->band_data[j].elevation[k] * ( 1 << 22 )); - q_direction->band_data[j].azimuth_fx[k] = (Word32)(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 */ - else if ( ec_flag == 1 && ( nblocks > 1 ) ) /* EC2 */ + ELSE IF( ec_flag == 1 && ( nblocks > 1 ) ) /* EC2 */ { bits_dir = 0; - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { raw_flag[b] = bitstream[( *index )--]; bits_dir++; @@ -617,13 +494,13 @@ int16_t ivas_qmetadata_dec_decode( /* Read EC bits*/ diff_bits = bits_diff + bits_coherence + signal_bits - total_bits_1dir; - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( raw_flag[b] == 0 ) + IF( raw_flag[b] == 0 ) { - bits_dir += ivas_qmetadata_entropy_decode_dir( q_direction, bitstream, index, diffuseness_index_max_ec_frame, b + 1, b, 0 ); + bits_dir += ivas_qmetadata_entropy_decode_dir_fx( q_direction, bitstream, index, diffuseness_index_max_ec_frame, b + 1, b, 0 ); } - else + ELSE { diff_bits += q_direction->band_data[b].bits_sph_idx[0] * q_direction->cfg.nblocks; } @@ -631,15 +508,15 @@ int16_t ivas_qmetadata_dec_decode( diff_bits += bits_dir; /* Small requantization?*/ - if ( q_direction->not_in_2D > 0 ) + IF( q_direction->not_in_2D > 0 ) { /* This is not an ideal solution but mirrors better encoder */ - int16_t i, j; - uint16_t bits_temp[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 i, j; + UWord16 bits_temp[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; - for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ ) + FOR( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ ) { - for ( j = 0; j < q_direction->cfg.nblocks; j++ ) + FOR( j = 0; j < q_direction->cfg.nblocks; j++ ) { bits_temp[i][j] = q_direction->band_data[i].bits_sph_idx[j]; } @@ -647,9 +524,9 @@ int16_t ivas_qmetadata_dec_decode( small_reduction_direction( q_direction, bits_temp, raw_flag, &diff_bits ); - for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ ) + FOR( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ ) { - for ( j = 0; j < q_direction->cfg.nblocks; j++ ) + FOR( j = 0; j < q_direction->cfg.nblocks; j++ ) { q_direction->band_data[i].bits_sph_idx[j] = bits_temp[i][j]; } @@ -657,50 +534,30 @@ int16_t ivas_qmetadata_dec_decode( } /* Read raw-coded bits*/ - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( raw_flag[b] ) + 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 } } } /* Decode requantized directions */ - else /* EC3 */ + ELSE /* EC3 */ { - int16_t dummy; + Word16 dummy; ec_flag = 2; - if ( hQMetaData->is_masa_ivas_format == 0 ) + IF( hQMetaData->is_masa_ivas_format == 0 ) { reduce_bits = bits_dir_raw - ( total_bits_1dir - bits_diff - bits_coherence - signal_bits ); ind_order[0] = -1; } - else + ELSE { ind_order[0] = 0; reduce_bits = min( nbands * nblocks + MASA_BIT_REDUCT_PARAM, bits_dir_raw - ( total_bits_1dir - bits_diff - bits_coherence - signal_bits ) ); - if ( reduce_bits > bits_dir_raw - nbands * nblocks ) + IF( reduce_bits > bits_dir_raw - nbands * nblocks ) { reduce_bits = bits_dir_raw - nbands * nblocks; } @@ -708,166 +565,1034 @@ 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++ ) + bits_dir = read_directions_fx( q_direction, (UWord8) nbands, (UWord8) nblocks, bitstream, index, ind_order ); + } + + IF( bits_coherence > 0 ) + { + IF( nblocks > 1 ) { - FOR( Word16 k = 0; k < nblocks; k++ ) - { - q_direction->band_data[j].elevation_fx[k] = (Word32)(q_direction->band_data[j].elevation[k] * ( 1 << 22 )); - q_direction->band_data[j].azimuth_fx[k] = (Word32)(q_direction->band_data[j].azimuth[k] * ( 1 << 22 )); - } + decode_spread_coherence_fx( hQMetaData, d, nblocks, 0 ); } - bits_dir = read_directions_fx( q_direction, (uint8_t) nbands, (uint8_t) nblocks, bitstream, index, ind_order ); - FOR( Word16 j = 0; j < nbands; j++ ) + } + ELSE + { + FOR( b = start_band; b < nbands; b++ ) { - FOR( Word16 k = 0; k < nblocks; k++ ) + IF( q_direction->coherence_band_data != NULL ) { - 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 ); + set_c( (Word8 *) q_direction->coherence_band_data[b].spread_coherence, 0, nblocks ); } } -#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( d == 0 ) + { + total_bits_1dir = hQMetaData->metadata_max_bits - ( start_index_0 - *index ); } - if ( bits_coherence > 0 ) + bits_dir_target += bits_dir_raw; + bits_dir_used += bits_dir; + } + /* move 2 dir data to its correct subband */ + IF( hQMetaData->no_directions == 2 ) + { + d = hQMetaData->q_direction[1].cfg.nbands - 1; + nblocks = hQMetaData->q_direction[0].cfg.nblocks; + + FOR( b = hQMetaData->q_direction[0].cfg.nbands - 1; b >= 0; b-- ) { - if ( nblocks > 1 ) + IF( hQMetaData->twoDirBands[b] == 1 ) { -#ifdef IVAS_FLOAT_FIXED - for ( int i = 0; i < q_direction->cfg.nbands; i++ ) + Copy32( hQMetaData->q_direction[1].band_data[d].azimuth_fx, hQMetaData->q_direction[1].band_data[b].azimuth_fx, nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[d].elevation_fx, hQMetaData->q_direction[1].band_data[b].elevation_fx, nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[d].energy_ratio_fx, hQMetaData->q_direction[1].band_data[b].energy_ratio_fx, nblocks ); + + IF( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] < 7 ) { - for ( int j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + FOR( m = 0; m < nblocks; m++ ) { - q_direction->band_data[i].azimuth_fx[j] = (Word32)(q_direction->band_data[i].azimuth[j] * ( 1 << 22 )); + Word32 a1 = hQMetaData->q_direction[1].band_data[b].azimuth_fx[m]; + a1 = L_shr( hQMetaData->q_direction[1].band_data[b].azimuth_fx[m], 1 ); + Word32 b1 = hQMetaData->q_direction[0].band_data[b].azimuth_fx[m]; + b1 = L_shr( hQMetaData->q_direction[0].band_data[b].azimuth_fx[m], 1 ); + Word32 c = L_shr( DEGREE_180_Q_22, 1 ); + a1 = L_add( a1, L_sub( b1, c ) ); + IF( a1 >= L_shr( DEGREE_180_Q_22, 1 ) ) + { + a1 = L_sub( a1, L_shr( DEGREE_360_Q_22, 1 ) ); + } + IF( a1 < L_shr( -DEGREE_180_Q_22, 1 ) ) + { + a1 = L_add( a1, L_shr( DEGREE_360_Q_22, 1 ) ); + } + + hQMetaData->q_direction[1].band_data[b].azimuth_fx[m] = L_shl( a1, 1 ); } } - decode_spread_coherence_fx( hQMetaData, d, nblocks, 0 ); - for ( int i = 0; i < q_direction->cfg.nbands; i++ ) + + IF( hQMetaData->q_direction[1].coherence_band_data != NULL ) { - 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 ); - } + mvc2c( hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, nblocks ); + } + d--; + } + ELSE + { + set32_fx( hQMetaData->q_direction[1].band_data[b].azimuth_fx, 0, nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[b].elevation_fx, 0, nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[b].energy_ratio_fx, 0, nblocks ); + + IF( hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + set_c( (Word8 *) hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, 0, nblocks ); } -#else - decode_spread_coherence( hQMetaData, d, nblocks, 0 ); -#endif } } - else + + /* Scale energy ratios that sum to over one */ + IF( !hodirac_flag ) { - for ( b = start_band; b < nbands; b++ ) + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - if ( q_direction->coherence_band_data != NULL ) + Word32 ratioSum_flt_fx; + + ratioSum_flt_fx = L_add( hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[0], hQMetaData->q_direction[1].band_data[b].energy_ratio_fx[0] ); + + IF( GT_32( ratioSum_flt_fx, ONE_IN_Q30 ) ) { - set_c( (int8_t *) q_direction->coherence_band_data[b].spread_coherence, 0, nblocks ); + set32_fx( hQMetaData->q_direction[0].band_data[b].energy_ratio_fx, L_shl( (Word32) divide3232( hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[0], ratioSum_flt_fx ), 15 ) /* Q30 */, nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[b].energy_ratio_fx, L_shl( (Word32) divide3232( hQMetaData->q_direction[1].band_data[b].energy_ratio_fx[0], ratioSum_flt_fx ), 15 ) /* Q30 */, nblocks ); } } } - if ( d == 0 ) + } + + /* Store status information for renderer use */ + hQMetaData->ec_flag = ec_flag; + + IF( bits_dir_used > bits_dir_target ) + { + hQMetaData->dir_comp_ratio_fx = MAX_WORD16; + } + ELSE + { + hQMetaData->dir_comp_ratio_fx = divide3232( bits_dir_used, bits_dir_target ); + } + return ( start_index_0 - *index ); +} +#else +int16_t ivas_qmetadata_dec_decode( + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: hQMetaData handle */ + uint16_t *bitstream, /* i : bitstream */ + int16_t *index, /* i/o: bitstream position */ + const int16_t hodirac_flag /* i : flag to indicate HO-DirAC mode */ +) +{ + int16_t d, b, m; + uint16_t diffuseness_index_max_ec_frame; + uint16_t diffuseness_index_max_ec_frame_pre[QMETADATA_MAX_NO_DIRECTIONS]; + int16_t bits_dir_raw_pre[QMETADATA_MAX_NO_DIRECTIONS]; + int16_t dir2band; + int16_t bits_diff_sum; + int16_t bits_diff, bits_coherence; + int16_t bits_dir_raw; + int16_t bits_dir; + int16_t nbands, nblocks, start_band; + IVAS_QDIRECTION *q_direction; + int16_t start_index_0; + int16_t total_bits_1dir; + int16_t signal_bits; + int16_t bits_no_dirs_coh, bits_sur_coherence; + uint16_t all_coherence_zero; + int16_t ec_flag; + int16_t raw_flag[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t diff_bits; + int16_t dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t no_TF; + int16_t p[MASA_MAXIMUM_CODING_SUBBANDS], dif_p[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t bits_dir_target; + int16_t bits_dir_used; + int16_t reduce_bits; + int16_t ind_order[MASA_MAXIMUM_CODING_SUBBANDS]; + + + ec_flag = 0; + start_index_0 = *index; + + /*Coherence flag decoding*/ + bits_no_dirs_coh = 0; + all_coherence_zero = 1; + if ( hQMetaData->coherence_flag ) + { + /* read if coherence is zero */ + all_coherence_zero = bitstream[( *index )--]; + bits_no_dirs_coh += 1; + } + + hQMetaData->all_coherence_zero = (uint8_t) all_coherence_zero; + + if ( hQMetaData->no_directions == 2 ) + { + /* Read which bands have 2 directions */ + hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands; + set_c( (int8_t *) hQMetaData->twoDirBands, 0, hQMetaData->q_direction[0].cfg.nbands ); + d = *index; + dif_p[0] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 0 ); + p[0] = dif_p[0]; + hQMetaData->twoDirBands[p[0]] = 1; + for ( b = 1; b < hQMetaData->numTwoDirBands; b++ ) { - total_bits_1dir = hQMetaData->metadata_max_bits - ( start_index_0 - *index ); + dif_p[b] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 0 ); + p[b] = p[b - 1] + dif_p[b] + 1; + hQMetaData->twoDirBands[p[b]] = 1; } + bits_no_dirs_coh += ( d - *index ); + } - bits_dir_target += bits_dir_raw; - bits_dir_used += bits_dir; + bits_diff_sum = 0; + bits_diff_sum += ivas_qmetadata_entropy_decode_diffuseness( bitstream, index, &( hQMetaData->q_direction[0] ), &diffuseness_index_max_ec_frame_pre[0] ); + + if ( hodirac_flag ) + { + if ( hQMetaData->no_directions == 2 ) + { + /* Calculate bits for dfRatio */ + dir2band = 0; + for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + if ( hQMetaData->twoDirBands[b] == 1 ) + { + dfRatio_bits[dir2band] = ivas_get_df_ratio_bits_hodirac( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] ); + dir2band++; + } + } + + bits_diff_sum += ivas_qmetadata_entropy_decode_df_ratio( bitstream, index, &( hQMetaData->q_direction[1] ), dfRatio_bits ); + } } + else + { + if ( hQMetaData->no_directions == 2 ) + { + /* Calculate bits for dfRatio */ + dir2band = 0; + for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + if ( hQMetaData->twoDirBands[b] == 1 ) + { + dfRatio_bits[dir2band] = ivas_get_df_ratio_bits( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] ); + dir2band++; + } + } - /* move 2 dir data to its correct subband */ + bits_diff_sum += ivas_qmetadata_entropy_decode_df_ratio( bitstream, index, &( hQMetaData->q_direction[1] ), dfRatio_bits ); + } + } + + /* Calculate direct-to-total energy ratios for both directions from diffuse-to-total ratio and distribution factor of direct-to-total ratios */ if ( hQMetaData->no_directions == 2 ) { - d = hQMetaData->q_direction[1].cfg.nbands - 1; - nblocks = hQMetaData->q_direction[0].cfg.nblocks; - - for ( b = hQMetaData->q_direction[0].cfg.nbands - 1; b >= 0; b-- ) + dir2band = 0; + for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { if ( hQMetaData->twoDirBands[b] == 1 ) { - mvr2r( hQMetaData->q_direction[1].band_data[d].azimuth, hQMetaData->q_direction[1].band_data[b].azimuth, nblocks ); - mvr2r( hQMetaData->q_direction[1].band_data[d].elevation, hQMetaData->q_direction[1].band_data[b].elevation, nblocks ); - mvr2r( hQMetaData->q_direction[1].band_data[d].energy_ratio, hQMetaData->q_direction[1].band_data[b].energy_ratio, nblocks ); + float diffRatio, dfRatio, dir1ratio, dir2ratio; + int16_t dfRatio_qsteps; - if ( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] < 7 ) + diffRatio = diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; + dfRatio_qsteps = 1 << dfRatio_bits[dir2band]; + /* already encoded as total and ratios in HO-DirAC */ + if ( hodirac_flag ) { - for ( m = 0; m < nblocks; m++ ) - { - hQMetaData->q_direction[1].band_data[b].azimuth[m] += hQMetaData->q_direction[0].band_data[b].azimuth[m] - 180; - if ( hQMetaData->q_direction[1].band_data[b].azimuth[m] >= 180 ) - { - hQMetaData->q_direction[1].band_data[b].azimuth[m] -= 360; - } - if ( hQMetaData->q_direction[1].band_data[b].azimuth[m] < -180 ) - { - hQMetaData->q_direction[1].band_data[b].azimuth[m] += 360; - } + dfRatio = usdequant( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0], 0.0f, 1.f / ( dfRatio_qsteps - 1 ) ); + dir1ratio = 1.f - diffRatio; + dir2ratio = dfRatio; + } + else + { + dfRatio = usdequant( hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0], 0.5f, 0.5f / ( dfRatio_qsteps - 1 ) ); + + dir1ratio = dfRatio * ( 1.0f - diffRatio ); + dir2ratio = ( 1.0f - diffRatio ) - dir1ratio; + } + + /* Requantize the 1 - dirRatio separately for each direction to obtain inverted dirRatio index. These are used in further decoding. */ + hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] = masa_sq( 1.0f - dir1ratio, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); + if ( hodirac_flag ) + { + float tmp; + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0] = usquant( dir2ratio, &tmp, 0.0f, 1.f / ( DIRAC_DIFFUSE_LEVELS - 1 ), DIRAC_DIFFUSE_LEVELS ); + } + else + { + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0] = masa_sq( 1.0f - dir2ratio, diffuseness_thresholds, DIRAC_DIFFUSE_LEVELS ); + } + + for ( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio[m] = dir1ratio; + hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; + } + + for ( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio[m] = dir2ratio; + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[m] = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0]; + } + + dir2band++; + } + else + { + /* 1dir band */ + hQMetaData->q_direction[0].band_data[b].energy_ratio[0] = 1.0f - diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; + for ( m = 1; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio[0]; + hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; + } + } + } + } + else + { + /* With 1dir band, the decoded index is directly diffuseness and we can decode to direct-to-total ratio with 1 - diff. */ + for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio[0] = 1.0f - diffuseness_reconstructions[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; + for ( m = 1; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio[0]; + hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; + } + } + } + + /* To decode directions correctly for 2dir bands, we need to obtain the compensated direct-to-total ratios and their + * corresponding inverted indices. */ + bits_dir_raw_pre[0] = 0; + bits_dir_raw_pre[1] = 0; + dir2band = 0; + for ( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + if ( hQMetaData->no_directions == 2 && hQMetaData->twoDirBands[b] == 1 ) + { + int16_t index_dirRatio1Inv, index_dirRatio2Inv, index_dirRatio1Inv_mod, index_dirRatio2Inv_mod; + + index_dirRatio1Inv = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; + index_dirRatio2Inv = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0]; + + masa_compensate_two_dir_energy_ratio_index( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); + + for ( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio_index_mod[m] = index_dirRatio1Inv_mod; + hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m] = bits_direction_masa[index_dirRatio1Inv_mod]; + bits_dir_raw_pre[0] += hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m]; + } + + for ( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index_mod[m] = index_dirRatio2Inv_mod; + hQMetaData->q_direction[1].band_data[dir2band].bits_sph_idx[m] = bits_direction_masa[index_dirRatio2Inv_mod]; + bits_dir_raw_pre[1] += hQMetaData->q_direction[1].band_data[dir2band].bits_sph_idx[m]; + } + + dir2band++; + } + else + { + for ( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio_index_mod[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; + hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m] = bits_direction_masa[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]]; + bits_dir_raw_pre[0] += hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m]; + } + } + } + + if ( hQMetaData->no_directions == 2 ) + { + no_TF = hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks + hQMetaData->q_direction[1].cfg.nbands * hQMetaData->q_direction[1].cfg.nblocks; + if ( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff_sum >= MASA_MIN_BITS_SURR_COH ) ) + { + bits_sur_coherence = read_surround_coherence( bitstream, index, hQMetaData ); + } + else + { + bits_sur_coherence = 0; + /*Surround coherence*/ + for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + if ( hQMetaData->surcoh_band_data != NULL ) + { + set_c( (int8_t *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + bits_no_dirs_coh += bits_sur_coherence; + total_bits_1dir = ( ( hQMetaData->metadata_max_bits - bits_no_dirs_coh ) * hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks ) / no_TF; + } + else + { + no_TF = hQMetaData->q_direction[0].cfg.nbands * hQMetaData->q_direction[0].cfg.nblocks; + if ( ( all_coherence_zero == 0 ) && ( hQMetaData->metadata_max_bits - bits_no_dirs_coh - 4.3f * no_TF - bits_diff_sum >= MASA_MIN_BITS_SURR_COH ) ) + { + bits_sur_coherence = read_surround_coherence( bitstream, index, hQMetaData ); + } + else + { + bits_sur_coherence = 0; + /*Surround coherence*/ + for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + if ( hQMetaData->surcoh_band_data != NULL ) + { + set_c( (int8_t *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + bits_no_dirs_coh += bits_sur_coherence; + + total_bits_1dir = hQMetaData->metadata_max_bits - bits_no_dirs_coh; + } + + bits_dir_target = 0; + bits_dir_used = 0; + + for ( d = 0; d < hQMetaData->no_directions; d++ ) + { + q_direction = &hQMetaData->q_direction[d]; + nbands = q_direction->cfg.nbands; + nblocks = q_direction->cfg.nblocks; + start_band = q_direction->cfg.start_band; + + diffuseness_index_max_ec_frame = diffuseness_index_max_ec_frame_pre[0]; + if ( d == 0 ) + { + bits_diff = bits_diff_sum; + } + else + { + bits_diff = 0; + } + bits_dir_raw = bits_dir_raw_pre[d]; + + /* Read coherence, if any */ + bits_coherence = 0; + + if ( all_coherence_zero == 0 ) + { + bits_coherence = read_coherence_data( bitstream, index, hQMetaData, d, 0 ); + } + else + { + /*Surround coherence*/ + for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + if ( hQMetaData->surcoh_band_data != NULL ) + { + set_c( (int8_t *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + + if ( hQMetaData->q_direction[d].coherence_band_data != NULL ) + { + set_c( (int8_t *) hQMetaData->q_direction[d].coherence_band_data[b].spread_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + + /* Read 2D signaling*/ + q_direction->not_in_2D = bitstream[( *index )--]; + signal_bits = 1; + + /* Read EC signaling */ + ec_flag = 0; + if ( total_bits_1dir + bits_sur_coherence <= hQMetaData->qmetadata_max_bit_req ) + { + ec_flag = bitstream[( *index )--]; + signal_bits++; + if ( nblocks > 1 ) + { + if ( ec_flag ) + { + ec_flag += bitstream[( *index )--]; + signal_bits++; + } + } + } + + /* Decode quantized directions frame-wise */ + if ( ec_flag == 0 ) /* EC 1*/ + { + bits_dir = 0; + raw_flag[0] = bitstream[( *index )--]; + bits_dir++; + + if ( raw_flag[0] == 0 ) + { + bits_dir += ivas_qmetadata_entropy_decode_dir( q_direction, bitstream, index, diffuseness_index_max_ec_frame, nbands, start_band, 0 ); + } + else + { + bits_dir += ivas_qmetadata_raw_decode_dir( q_direction, bitstream, index, nbands, start_band, 0 ); + } + } + /* Decode quantized directions band-wise */ + else if ( ec_flag == 1 && ( nblocks > 1 ) ) /* EC2 */ + { + bits_dir = 0; + for ( b = start_band; b < nbands; b++ ) + { + raw_flag[b] = bitstream[( *index )--]; + bits_dir++; + } + + /* Read EC bits*/ + diff_bits = bits_diff + bits_coherence + signal_bits - total_bits_1dir; + + for ( b = start_band; b < nbands; b++ ) + { + if ( raw_flag[b] == 0 ) + { + bits_dir += ivas_qmetadata_entropy_decode_dir( q_direction, bitstream, index, diffuseness_index_max_ec_frame, b + 1, b, 0 ); + } + else + { + diff_bits += q_direction->band_data[b].bits_sph_idx[0] * q_direction->cfg.nblocks; + } + } + diff_bits += bits_dir; + + /* Small requantization?*/ + if ( q_direction->not_in_2D > 0 ) + { + /* This is not an ideal solution but mirrors better encoder */ + int16_t i, j; + uint16_t bits_temp[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + + for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ ) + { + for ( j = 0; j < q_direction->cfg.nblocks; j++ ) + { + bits_temp[i][j] = q_direction->band_data[i].bits_sph_idx[j]; + } + } + + small_reduction_direction( q_direction, bits_temp, raw_flag, &diff_bits ); + + for ( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ ) + { + for ( j = 0; j < q_direction->cfg.nblocks; j++ ) + { + q_direction->band_data[i].bits_sph_idx[j] = bits_temp[i][j]; + } + } + } + + /* Read raw-coded bits*/ + for ( b = start_band; b < nbands; b++ ) + { + if ( raw_flag[b] ) + { + bits_dir += ivas_qmetadata_raw_decode_dir( q_direction, bitstream, index, b + 1, b, 0 ); + } + } + } + /* Decode requantized directions */ + else /* EC3 */ + { + int16_t dummy; + ec_flag = 2; + + if ( hQMetaData->is_masa_ivas_format == 0 ) + { + reduce_bits = bits_dir_raw - ( total_bits_1dir - bits_diff - bits_coherence - signal_bits ); + ind_order[0] = -1; + } + else + { + ind_order[0] = 0; + reduce_bits = min( nbands * nblocks + MASA_BIT_REDUCT_PARAM, bits_dir_raw - ( total_bits_1dir - bits_diff - bits_coherence - signal_bits ) ); + if ( reduce_bits > bits_dir_raw - nbands * nblocks ) + { + reduce_bits = bits_dir_raw - nbands * nblocks; + } + } + only_reduce_bits_direction( &dummy, q_direction, reduce_bits, nbands, nblocks, ind_order ); + + /* Read directions */ + bits_dir = read_directions( q_direction, (uint8_t) nbands, (uint8_t) nblocks, bitstream, index, ind_order ); + } + + if ( bits_coherence > 0 ) + { + if ( nblocks > 1 ) + { + decode_spread_coherence( hQMetaData, d, nblocks, 0 ); + } + } + else + { + for ( b = start_band; b < nbands; b++ ) + { + if ( q_direction->coherence_band_data != NULL ) + { + set_c( (int8_t *) q_direction->coherence_band_data[b].spread_coherence, 0, nblocks ); + } + } + } + if ( d == 0 ) + { + total_bits_1dir = hQMetaData->metadata_max_bits - ( start_index_0 - *index ); + } + + bits_dir_target += bits_dir_raw; + bits_dir_used += bits_dir; + } + + /* move 2 dir data to its correct subband */ + if ( hQMetaData->no_directions == 2 ) + { + d = hQMetaData->q_direction[1].cfg.nbands - 1; + nblocks = hQMetaData->q_direction[0].cfg.nblocks; + + for ( b = hQMetaData->q_direction[0].cfg.nbands - 1; b >= 0; b-- ) + { + if ( hQMetaData->twoDirBands[b] == 1 ) + { + mvr2r( hQMetaData->q_direction[1].band_data[d].azimuth, hQMetaData->q_direction[1].band_data[b].azimuth, nblocks ); + mvr2r( hQMetaData->q_direction[1].band_data[d].elevation, hQMetaData->q_direction[1].band_data[b].elevation, nblocks ); + mvr2r( hQMetaData->q_direction[1].band_data[d].energy_ratio, hQMetaData->q_direction[1].band_data[b].energy_ratio, nblocks ); + + if ( hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0] < 7 ) + { + for ( m = 0; m < nblocks; m++ ) + { + hQMetaData->q_direction[1].band_data[b].azimuth[m] += hQMetaData->q_direction[0].band_data[b].azimuth[m] - 180; + if ( hQMetaData->q_direction[1].band_data[b].azimuth[m] >= 180 ) + { + hQMetaData->q_direction[1].band_data[b].azimuth[m] -= 360; + } + if ( hQMetaData->q_direction[1].band_data[b].azimuth[m] < -180 ) + { + hQMetaData->q_direction[1].band_data[b].azimuth[m] += 360; + } + } + } + + if ( hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + mvc2c( hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, nblocks ); + } + d--; + } + else + { + set_f( hQMetaData->q_direction[1].band_data[b].azimuth, 0.0f, nblocks ); + set_f( hQMetaData->q_direction[1].band_data[b].elevation, 0.0f, nblocks ); + set_f( hQMetaData->q_direction[1].band_data[b].energy_ratio, 0.0f, nblocks ); + + if ( hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + set_c( (int8_t *) hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, 0, nblocks ); + } + } + } + + /* Scale energy ratios that sum to over one */ + if ( !hodirac_flag ) + { + for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + float ratioSum; + + ratioSum = hQMetaData->q_direction[0].band_data[b].energy_ratio[0] + hQMetaData->q_direction[1].band_data[b].energy_ratio[0]; + + if ( ratioSum > 1.0f ) + { + set_f( hQMetaData->q_direction[0].band_data[b].energy_ratio, hQMetaData->q_direction[0].band_data[b].energy_ratio[0] / ratioSum, nblocks ); + set_f( hQMetaData->q_direction[1].band_data[b].energy_ratio, hQMetaData->q_direction[1].band_data[b].energy_ratio[0] / ratioSum, nblocks ); + } + } + } + } + + /* Store status information for renderer use */ + hQMetaData->ec_flag = ec_flag; + + hQMetaData->dir_comp_ratio = (float) bits_dir_used / (float) bits_dir_target; + + if ( hQMetaData->dir_comp_ratio > 1.0f ) + { + hQMetaData->dir_comp_ratio = 1.0f; + } + + return ( start_index_0 - *index ); +} + +#endif + +/*-----------------------------------------------------------------------* + * ivas_qmetadata_dec_decode_hr_384_512() + * + * Main function for decoding Spatial Metadata at HRs + *-----------------------------------------------------------------------*/ + +/*! r: number of bits read */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_qmetadata_dec_decode_hr_384_512( + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: hQMetaData handle */ + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, /* i/o: bitstream position */ + const SPHERICAL_GRID_DATA *sph_grid16, /* i : spherical grid for deindexing */ + const Word16 bits_sph_idx, + const Word16 bits_sp_coh, + const UWord8 ncoding_bands_config ) +{ + Word16 d, b, m; + Word16 nbands, start_band; + IVAS_QDIRECTION *q_direction; + Word16 start_index_0; + UWord16 all_coherence_zero; + Word16 p[MASA_MAXIMUM_CODING_SUBBANDS], dif_p[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 codedBands, sf_nbands0, sf_nbands1; + sf_nbands1 = 1; + Word64 W_nrg_ratio[2][MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + + start_index_0 = *index; + /* read number of higher inactive/not encoded bands */ + IF( bitstream[( *index )--] ) + { + codedBands = MASA_MAXIMUM_CODING_SUBBANDS - ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 1 ) - 1; + } + ELSE + { + codedBands = MASA_MAXIMUM_CODING_SUBBANDS; + } + FOR( b = codedBands; b < ncoding_bands_config; b++ ) + { + FOR( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ ) + { + + hQMetaData->q_direction[0].band_data[b].azimuth_fx[m] = 0; + hQMetaData->q_direction[0].band_data[b].elevation_fx[m] = 0; + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[m] = 0; + W_nrg_ratio[0][b][m] = 0; + + IF( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL ) + { + hQMetaData->q_direction[0].coherence_band_data[b].spread_coherence[m] = 0u; + } + + IF( hQMetaData->no_directions == 2 ) + { + + hQMetaData->q_direction[1].band_data[b].azimuth_fx[m] = 0; + hQMetaData->q_direction[1].band_data[b].elevation_fx[m] = 0; + hQMetaData->q_direction[1].band_data[b].energy_ratio_fx[m] = 0; + W_nrg_ratio[1][b][m] = 0; + + IF( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence[m] = 0u; + } + } + + IF( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL ) + { + hQMetaData->surcoh_band_data[b].surround_coherence[m] = 0u; + } + } + + IF( hQMetaData->no_directions == 2 ) + { + hQMetaData->twoDirBands[b] = 0; + } + } + sf_nbands0 = hQMetaData->q_direction[0].cfg.nbands; + + hQMetaData->q_direction[0].cfg.nbands = codedBands; + + /*Coherence flag decoding*/ + all_coherence_zero = 1; + IF( hQMetaData->coherence_flag ) + { + /* read if coherence is zero */ + all_coherence_zero = bitstream[( *index )--]; + } + + hQMetaData->all_coherence_zero = (UWord8) all_coherence_zero; + + IF( hQMetaData->no_directions == 2 ) + { + set_c( (Word8 *) hQMetaData->twoDirBands, 1, hQMetaData->q_direction[0].cfg.nbands ); + } + + IF( bits_sph_idx == 11 && hQMetaData->no_directions == 2 ) + { + /* Read which bands have 2 directions */ + hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands; + sf_nbands1 = hQMetaData->q_direction[1].cfg.nbands; + IF( hQMetaData->q_direction[1].cfg.nbands > codedBands ) + { + hQMetaData->q_direction[1].cfg.nbands = codedBands; + } + set_c( (Word8 *) hQMetaData->twoDirBands, 0, hQMetaData->q_direction[0].cfg.nbands ); + d = *index; + dif_p[0] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 0 ); + p[0] = dif_p[0]; + hQMetaData->twoDirBands[p[0]] = 1; + FOR( b = 1; b < hQMetaData->q_direction[1].cfg.nbands; b++ ) + { + dif_p[b] = ivas_qmetadata_DecodeExtendedGR( bitstream, index, MASA_MAXIMUM_CODING_SUBBANDS, 0 ); + p[b] = p[b - 1] + dif_p[b] + 1; + hQMetaData->twoDirBands[p[b]] = 1; + } + } + + IF( bits_sph_idx == 16 && hQMetaData->no_directions == 2 ) + { + sf_nbands1 = hQMetaData->q_direction[1].cfg.nbands; + IF( hQMetaData->q_direction[1].cfg.nbands > codedBands ) + { + hQMetaData->q_direction[1].cfg.nbands = codedBands; + } + } + 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] ) ); + } + + + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + W_nrg_ratio[0][b][m] = W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[hQMetaData->q_direction[0].band_data[b].energy_ratio_index[m]] ); + } + } + IF( hQMetaData->no_directions == 2 ) + { + Word32 ratioSum; + IF( bits_sph_idx == 16 ) + { + FOR( b = hQMetaData->q_direction[1].cfg.start_band; b < hQMetaData->q_direction[1].cfg.nbands; b++ ) + { + FOR( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + { + W_nrg_ratio[1][b][m] = W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[hQMetaData->q_direction[1].band_data[b].energy_ratio_index[m]] ); + + /* Scale energy ratios that sum to over one */ + ratioSum = W_round64_L( W_add( W_nrg_ratio[0][b][m], W_nrg_ratio[1][b][m] ) ); + + IF( GT_32( ratioSum, ONE_IN_Q30 ) ) + { + W_nrg_ratio[0][b][m] = W_shl( (Word64) ( W_nrg_ratio[0][b][m] / ratioSum ), 30 ); // Q62 + W_nrg_ratio[1][b][m] = W_shl( (Word64) ( W_nrg_ratio[1][b][m] / ratioSum ), 30 ); // Q62 + } + } + } + } + ELSE + { + Word16 pos_2dir_band[MASA_MAXIMUM_CODING_SUBBANDS]; + d = 0; + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + IF( hQMetaData->twoDirBands[b] == 1 ) + { + pos_2dir_band[d] = b; + d++; + } + ELSE + { + pos_2dir_band[d] = 0; + } + } + FOR( b = hQMetaData->q_direction[1].cfg.start_band; b < hQMetaData->q_direction[1].cfg.nbands; b++ ) + { + FOR( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + { + + W_nrg_ratio[1][b][m] = W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[hQMetaData->q_direction[1].band_data[b].energy_ratio_index[m]] ); + + ratioSum = W_round64_L( W_add( W_nrg_ratio[0][pos_2dir_band[b]][m], W_nrg_ratio[1][b][m] ) ); + + IF( GT_32( ratioSum, ONE_IN_Q30 ) ) + { + W_nrg_ratio[0][pos_2dir_band[b]][m] = W_shl( (Word64) ( W_nrg_ratio[0][pos_2dir_band[b]][m] / ratioSum ), 30 ); + W_nrg_ratio[1][b][m] = W_shl( (Word64) ( W_nrg_ratio[1][b][m] / ratioSum ), 30 ); + } + } + } + } + } + + IF( hQMetaData->no_directions == 2 ) + { + FOR( b = hQMetaData->q_direction[1].cfg.start_band; b < hQMetaData->q_direction[1].cfg.nbands; b++ ) + { + FOR( m = 0; m < hQMetaData->q_direction[1].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[1].band_data[b].energy_ratio_index_mod[m] = hQMetaData->q_direction[1].band_data[b].energy_ratio_index[m]; + hQMetaData->q_direction[1].band_data[b].bits_sph_idx[m] = bits_sph_idx; + } + } + } + + FOR( b = hQMetaData->q_direction[0].cfg.start_band; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio_index_mod[m] = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; + hQMetaData->q_direction[0].band_data[b].bits_sph_idx[m] = bits_sph_idx; + } + } + + IF( all_coherence_zero == 0 ) + { + read_surround_coherence_hr_fx( bitstream, index, hQMetaData, W_nrg_ratio ); + } + ELSE + { + /*Surround coherence*/ + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + IF( hQMetaData->surcoh_band_data != NULL ) + { + set_c( (Word8 *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + + FOR( d = 0; d < hQMetaData->no_directions; d++ ) + { + q_direction = &hQMetaData->q_direction[d]; + nbands = q_direction->cfg.nbands; + start_band = q_direction->cfg.start_band; + + /* 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 + { + /*Surround coherence*/ + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + { + IF( hQMetaData->surcoh_band_data != NULL ) + { + set_c( (Word8 *) hQMetaData->surcoh_band_data[b].surround_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + + IF( hQMetaData->q_direction[d].coherence_band_data != NULL ) + { + set_c( (Word8 *) hQMetaData->q_direction[d].coherence_band_data[b].spread_coherence, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + } + } + + /* Decode quantized directions frame-wise */ + + ivas_qmetadata_raw_decode_dir_512_fx( q_direction, bitstream, index, nbands, start_band, sph_grid16 ); + } + + IF( hQMetaData->no_directions == 2 ) + { + /* move 2 dir data to its correct subband */ + IF( bits_sph_idx == 11 ) + { + Word16 nblocks; + d = hQMetaData->q_direction[1].cfg.nbands - 1; + nblocks = hQMetaData->q_direction[0].cfg.nblocks; + + FOR( b = hQMetaData->q_direction[0].cfg.nbands - 1; b >= 0; b-- ) + { + IF( hQMetaData->twoDirBands[b] == 1 ) + { + + Copy32( hQMetaData->q_direction[1].band_data[d].azimuth_fx, hQMetaData->q_direction[1].band_data[b].azimuth_fx, nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[d].elevation_fx, hQMetaData->q_direction[1].band_data[b].elevation_fx, nblocks ); + Copy32( hQMetaData->q_direction[1].band_data[d].energy_ratio_fx, hQMetaData->q_direction[1].band_data[b].energy_ratio_fx, nblocks ); + Copy64( W_nrg_ratio[1][d], W_nrg_ratio[1][b], nblocks ); + + IF( hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + mvc2c( hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, nblocks ); } + d--; } - - if ( hQMetaData->q_direction[1].coherence_band_data != NULL ) + ELSE { - mvc2c( hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, nblocks ); - } - d--; - } - else - { - set_f( hQMetaData->q_direction[1].band_data[b].azimuth, 0.0f, nblocks ); - set_f( hQMetaData->q_direction[1].band_data[b].elevation, 0.0f, nblocks ); - set_f( hQMetaData->q_direction[1].band_data[b].energy_ratio, 0.0f, nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[b].azimuth_fx, 0, nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[b].elevation_fx, 0, nblocks ); + set32_fx( hQMetaData->q_direction[1].band_data[b].energy_ratio_fx, 0, nblocks ); + set64_fx( W_nrg_ratio[1][b], 0, nblocks ); - if ( hQMetaData->q_direction[1].coherence_band_data != NULL ) - { - set_c( (int8_t *) hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, 0, nblocks ); + IF( hQMetaData->q_direction[1].coherence_band_data != NULL ) + { + set_c( (Word8 *) hQMetaData->q_direction[1].coherence_band_data[b].spread_coherence, 0, nblocks ); + } } } } /* Scale energy ratios that sum to over one */ - if ( !hodirac_flag ) + FOR( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) { - for ( b = 0; b < hQMetaData->q_direction[0].cfg.nbands; b++ ) + FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { - float ratioSum; - - ratioSum = hQMetaData->q_direction[0].band_data[b].energy_ratio[0] + hQMetaData->q_direction[1].band_data[b].energy_ratio[0]; - - if ( ratioSum > 1.0f ) + Word32 ratioSum; + ratioSum = W_round64_L( W_add( W_nrg_ratio[0][b][m], W_nrg_ratio[1][b][m] ) ); + IF( GT_32( ratioSum, ONE_IN_Q30 ) ) { - set_f( hQMetaData->q_direction[0].band_data[b].energy_ratio, hQMetaData->q_direction[0].band_data[b].energy_ratio[0] / ratioSum, nblocks ); - set_f( hQMetaData->q_direction[1].band_data[b].energy_ratio, hQMetaData->q_direction[1].band_data[b].energy_ratio[0] / ratioSum, nblocks ); + W_nrg_ratio[0][b][m] = W_shl( (Word64) ( W_nrg_ratio[0][b][m] / ratioSum ), 30 ); + W_nrg_ratio[1][b][m] = W_shl( (Word64) ( W_nrg_ratio[1][b][m] / ratioSum ), 30 ); } } } } + FOR( b = 0; b < MASA_MAXIMUM_CODING_SUBBANDS; b++ ) + { + FOR( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ ) + { + hQMetaData->q_direction[0].band_data[b].energy_ratio_fx[m] = W_round64_L( W_nrg_ratio[0][b][m] ); + } + } + IF( hQMetaData->no_directions == 2 ) + { + FOR( b = 0; b < MASA_MAXIMUM_CODING_SUBBANDS; b++ ) + { + FOR( m = 0; m < MAX_PARAM_SPATIAL_SUBFRAMES; m++ ) + { + hQMetaData->q_direction[1].band_data[b].energy_ratio_fx[m] = W_round64_L( W_nrg_ratio[1][b][m] ); + } + } + } /* Store status information for renderer use */ - hQMetaData->ec_flag = ec_flag; + hQMetaData->ec_flag = 0; + hQMetaData->dir_comp_ratio_fx = MAX_WORD16; - hQMetaData->dir_comp_ratio = (float) bits_dir_used / (float) bits_dir_target; - if ( hQMetaData->dir_comp_ratio > 1.0f ) + hQMetaData->q_direction[0].cfg.nbands = sf_nbands0; + IF( hQMetaData->no_directions == 2 ) { - hQMetaData->dir_comp_ratio = 1.0f; + hQMetaData->q_direction[1].cfg.nbands = sf_nbands1; } return ( start_index_0 - *index ); } - - -/*-----------------------------------------------------------------------* - * ivas_qmetadata_dec_decode_hr_384_512() - * - * Main function for decoding Spatial Metadata at HRs - *-----------------------------------------------------------------------*/ - -/*! r: number of bits read */ +#else int16_t ivas_qmetadata_dec_decode_hr_384_512( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: hQMetaData handle */ uint16_t *bitstream, /* i : bitstream */ @@ -1076,58 +1801,7 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( if ( all_coherence_zero == 0 ) { -#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 { @@ -1150,11 +1824,7 @@ 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 { @@ -1253,6 +1923,7 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( return ( start_index_0 - *index ); } +#endif /*-----------------------------------------------------------------------* @@ -1262,6 +1933,236 @@ int16_t ivas_qmetadata_dec_decode_hr_384_512( *-----------------------------------------------------------------------*/ /*! r: number of bits written */ +#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] = L_sub( ONE_IN_Q30, 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 ); + + ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( avg_azimuth_fx, avg_elevation_fx, avg_direction_vector_fx ); + ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[b].azimuth_fx[nblocks - 1], q_direction->band_data[b].elevation_fx[nblocks - 1], direction_vector_fx ); + + v_shr_32( direction_vector_fx, direction_vector_fx, 3, 5 ); + v_shr_32( avg_direction_vector_fx, avg_direction_vector_fx, 3, 5 ); + FOR( m = 0; m < nblocks - 1; m++ ) + { + v_add_32( direction_vector_fx, avg_direction_vector_fx, direction_vector_fx, 3 ); + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( direction_vector_fx, 30 - 5, &q_direction->band_data[b].azimuth_fx[m], &q_direction->band_data[b].elevation_fx[m] ); + } + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector_fx, 30 - 5, &q_direction->band_data[b].azimuth_fx[nblocks - 1], &q_direction->band_data[b].elevation_fx[nblocks - 1] ); + } + } + ELSE + { + FOR( b = start_band; b < nbands; b++ ) + { + Word32 temp_result; + 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 ); + + temp_result = div_s( ( q_direction->band_data[b].azimuth_index[0] << 6 ), ( q_direction->band_data[b].azimuth_m_alphabet[0] << 6 ) ); + temp_result = Mpy_32_16_1( DEGREE_360_Q_22, (Word16) temp_result ); + avg_azimuth_fx = temp_result - DEGREE_180_Q_22; + + avg_elevation_fx = 0; + + ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( avg_azimuth_fx, avg_elevation_fx, avg_direction_vector_fx ); + ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[b].azimuth_fx[nblocks - 1], q_direction->band_data[b].elevation_fx[nblocks - 1], direction_vector_fx ); + + v_shr_32( direction_vector_fx, direction_vector_fx, 3, 5 ); + v_shr_32( avg_direction_vector_fx, avg_direction_vector_fx, 3, 5 ); + FOR( m = 0; m < nblocks - 1; m++ ) + { + v_add_32( direction_vector_fx, avg_direction_vector_fx, direction_vector_fx, 3 ); + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( direction_vector_fx, 30 - 5, &q_direction->band_data[b].azimuth_fx[m], &q_direction->band_data[b].elevation_fx[m] ); + } + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector_fx, 30 - 5, &q_direction->band_data[b].azimuth_fx[nblocks - 1], &q_direction->band_data[b].elevation_fx[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 ); +} + +#else int16_t ivas_qmetadata_dec_sid_decode( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ uint16_t *bitstream, /* i : bitstream */ @@ -1485,233 +2386,7 @@ 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 - - +#endif /*-----------------------------------------------------------------------* * Local function definitions for diffuseness/energy ratios *-----------------------------------------------------------------------*/ @@ -1835,7 +2510,7 @@ static Word16 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 */ @@ -1844,7 +2519,7 @@ static Word16 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 */ @@ -1930,7 +2605,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 */ @@ -1939,7 +2614,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 */ @@ -2172,7 +2847,7 @@ static Word16 ivas_qmetadata_entropy_decode_df_ratio( 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 */ @@ -2181,7 +2856,7 @@ static Word16 ivas_qmetadata_entropy_decode_df_ratio( 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 */ @@ -2280,7 +2955,7 @@ static int16_t ivas_qmetadata_entropy_decode_df_ratio( 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 */ @@ -2289,7 +2964,7 @@ static int16_t ivas_qmetadata_entropy_decode_df_ratio( 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 */ @@ -2309,37 +2984,37 @@ static int16_t ivas_qmetadata_entropy_decode_df_ratio( *-----------------------------------------------------------------------*/ /*------------------------------------------------------------------------- - * ivas_qmetadata_entropy_decode_dir() + * ivas_qmetadata_entropy_decode_dir_fx() * * Main function for entropy decoding of the directions *------------------------------------------------------------------------*/ - -static int16_t ivas_qmetadata_entropy_decode_dir( +#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 uint16_t diffuseness_index_max_ec_frame, - const int16_t nbands, - const int16_t start_band, - const int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ + 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; - int16_t diff_idx; - int16_t diff_idx_min; - int16_t nblocks; - int16_t index_start; + Word16 b, m; + Word16 diff_idx; + Word16 diff_idx_min; + Word16 nblocks; + Word16 index_start; - uint16_t gr_param_elev, gr_param_azith; - int16_t bands_entropic[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t elev_alph[MASA_MAXIMUM_CODING_SUBBANDS]; - int16_t azith_alph[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + 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]; - int16_t avg_elevation_alphabet, avg_azimuth_alphabet; - int16_t avg_elevation_idx, avg_azimuth_index; - int16_t avg_elevation_index_projected, avg_azimuth_index_projected; - float direction_vector[3], avg_direction_vector[3], avg_azimuth, avg_elevation; - int16_t use_adapt_avg, idx; + Word16 avg_elevation_alphabet, avg_azimuth_alphabet; + Word16 avg_elevation_idx, avg_azimuth_index; + Word16 avg_elevation_index_projected, avg_azimuth_index_projected; + Word32 direction_vector_fx[3], avg_direction_vector_fx[3], avg_azimuth_fx, avg_elevation_fx; + Word16 use_adapt_avg, idx; index_start = *index; nblocks = q_direction->cfg.nblocks; @@ -2349,48 +3024,48 @@ static int16_t ivas_qmetadata_entropy_decode_dir( /*Raw coding for high diffuseness*/ for ( b = start_band; b < nbands; b++ ) { - if ( hrmasa_flag ) + IF( hrmasa_flag ) { diff_idx = 0; } - else + ELSE { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } diff_idx_min = min( diff_idx_min, diff_idx ); - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { elev_alph[b] = no_theta_masa[bits_direction_masa[diff_idx] - 3]; } - else + 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 ) + 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 ) + IF( q_direction->not_in_2D > 0 ) { - decode_fixed_rate( q_direction, bitstream, index, b, nblocks ); + decode_fixed_rate_fx( q_direction, bitstream, index, b, nblocks ); } - else + ELSE { /* in 2D */ - for ( m = 0; m < nblocks; m++ ) + FOR( m = 0; m < nblocks; m++ ) { - q_direction->band_data[b].elevation[m] = 0.f; + q_direction->band_data[b].elevation_fx[m] = 0; 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 ); + 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 ); } } } - else + ELSE { bands_entropic[b] = 1; } @@ -2399,14 +3074,14 @@ static int16_t ivas_qmetadata_entropy_decode_dir( /*EC for the low diffuseness*/ /*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 ) + IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { 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 { 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 ); @@ -2414,90 +3089,90 @@ static int16_t ivas_qmetadata_entropy_decode_dir( } gr_param_elev = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, 4 + 1 ); - if ( gr_param_elev == 4 ) /* all the elevation distances are zero */ + IF( gr_param_elev == 4 ) /* all the elevation distances are zero */ { - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( bands_entropic[b] ) + IF( bands_entropic[b] ) { - int16_t tmp_index; - if ( hrmasa_flag ) + Word16 tmp_index; + IF( hrmasa_flag ) { diff_idx = 0; } - else + ELSE { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + 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 + ELSE { avg_elevation_index_projected = ivas_dirac_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); /*reorder elevation indexing*/ tmp_index = avg_elevation_index_projected - ( elev_alph[b] >> 1 ); - if ( tmp_index < 0 ) + IF( tmp_index < 0 ) { tmp_index = tmp_index * -2; } - else if ( tmp_index > 0 ) + ELSE IF( tmp_index > 0 ) { tmp_index = tmp_index * 2 - 1; } avg_elevation_index_projected = tmp_index; } - for ( m = 0; m < nblocks; m++ ) + 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 ) + 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 + 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 ); + q_direction->band_data[b].elevation_fx[m] = deindex_elevation_fx( &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); } } } } - else + ELSE { - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( bands_entropic[b] ) + IF( bands_entropic[b] ) { - if ( hrmasa_flag ) + IF( hrmasa_flag ) { diff_idx = 0; } - else + ELSE { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } - for ( m = 0; m < nblocks; m++ ) + FOR( m = 0; m < nblocks; m++ ) { - int16_t tmp_index; - if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + 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 ) + IF( tmp_index % 2 ) { tmp_index = avg_elevation_index_projected + ( ( tmp_index + 1 ) >> 1 ); } - else + ELSE { tmp_index = avg_elevation_index_projected - ( tmp_index >> 1 ); } @@ -2506,7 +3181,7 @@ static int16_t ivas_qmetadata_entropy_decode_dir( /*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 + ELSE { avg_elevation_index_projected = ivas_dirac_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); @@ -2515,11 +3190,11 @@ static int16_t ivas_qmetadata_entropy_decode_dir( /*reorder elevation indexing*/ tmp_index = tmp_index - ( elev_alph[b] >> 1 ); - if ( tmp_index < 0 ) + IF( tmp_index < 0 ) { tmp_index = tmp_index * -2; } - else if ( tmp_index > 0 ) + ELSE IF( tmp_index > 0 ) { tmp_index = tmp_index * 2 - 1; } @@ -2530,43 +3205,43 @@ static int16_t ivas_qmetadata_entropy_decode_dir( } /*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 ); + q_direction->band_data[b].elevation_fx[m] = deindex_elevation_fx( &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); } } } } } - else + ELSE { - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( bands_entropic[b] ) + IF( bands_entropic[b] ) { - if ( hrmasa_flag ) + IF( hrmasa_flag ) { diff_idx = 0; } - else + ELSE { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } - for ( m = 0; m < nblocks; m++ ) + 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 ) + 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 + 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 ); + q_direction->band_data[b].elevation_fx[m] = deindex_elevation_fx( &q_direction->band_data[b].elevation_index[m], q_direction->band_data[b].bits_sph_idx[m], q_direction->cfg.mc_ls_setup ); } } } @@ -2579,41 +3254,41 @@ static int16_t ivas_qmetadata_entropy_decode_dir( 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 */ + IF( gr_param_azith == 5 ) /* all the azimuth distances are zero */ { - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( bands_entropic[b] ) + IF( bands_entropic[b] ) { - for ( m = 0; m < nblocks; m++ ) + 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 ) + IF( azith_alph[b][m] == 1 ) { - q_direction->band_data[b].azimuth[m] = 0.f; + q_direction->band_data[b].azimuth_fx[m] = 0; } - else + 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 ); + 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], q_direction->band_data[b].elevation_index[m], 0, q_direction->cfg.mc_ls_setup ); } } } } } - else + ELSE { - set_zero( avg_direction_vector, 3 ); + set32_fx( avg_direction_vector_fx, 0, 3 ); use_adapt_avg = 0; idx = 0; - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - if ( bands_entropic[b] ) + IF( bands_entropic[b] ) { - for ( m = 0; m < nblocks; m++ ) + 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 ) ) + 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 )--; @@ -2622,34 +3297,39 @@ static int16_t ivas_qmetadata_entropy_decode_dir( 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 ) + IF( azith_alph[b][m] == 1 ) { - q_direction->band_data[b].azimuth[m] = 0.f; + q_direction->band_data[b].azimuth_fx[m] = 0; } - else + 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 ); + 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], 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( ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) && ( nblocks > 1 ) ) { - if ( idx < MASA_LIMIT_IDX_AVG_AZI ) + 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 ); + ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[b].azimuth_fx[m], q_direction->band_data[b].elevation_fx[m], direction_vector_fx ); + v_shr_32( direction_vector_fx, direction_vector_fx, 3, 5 ); + v_add_32( avg_direction_vector_fx, direction_vector_fx, avg_direction_vector_fx, 3 ); } - else + ELSE { - if ( use_adapt_avg == 1 ) + IF( use_adapt_avg == 1 ) { - if ( m == 0 ) + IF( m == 0 ) { - v_multc( avg_direction_vector, 0.5f, avg_direction_vector, 3 ); + FOR( Word16 l = 0; l < 3; l++ ) + { + avg_direction_vector_fx[l] = L_shr( avg_direction_vector_fx[l], 1 ); + } } /*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 ); + ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[b].azimuth_fx[m], q_direction->band_data[b].elevation_fx[m], direction_vector_fx ); + v_shr_32( direction_vector_fx, direction_vector_fx, 3, 5 ); + v_add_32( avg_direction_vector_fx, direction_vector_fx, avg_direction_vector_fx, 3 ); + ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector_fx, 30 - 5, &avg_azimuth_fx, &avg_elevation_fx ); + avg_azimuth_index = quantize_phi_fx( L_add( avg_azimuth_fx, DEGREE_180_Q_22 ), 0, &avg_azimuth_fx, avg_azimuth_alphabet ); } } idx++; @@ -2661,34 +3341,33 @@ static int16_t ivas_qmetadata_entropy_decode_dir( return ( index_start - *index ); } - -#ifdef IVAS_FLOAT_FIXED_1 -static Word16 ivas_qmetadata_entropy_decode_dir_fx( +#else +static int16_t ivas_qmetadata_entropy_decode_dir( IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ - 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*/ + uint16_t *bitstream, /* i : 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 /* i : flag indicating high-rate MASA MD coding*/ ) { - Word16 b, m; - Word16 diff_idx; - Word16 diff_idx_min; - Word16 nblocks; - Word16 index_start; + int16_t b, m; + int16_t diff_idx; + int16_t diff_idx_min; + int16_t nblocks; + int16_t 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]; + uint16_t gr_param_elev, gr_param_azith; + int16_t bands_entropic[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t elev_alph[MASA_MAXIMUM_CODING_SUBBANDS]; + int16_t 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; + int16_t avg_elevation_alphabet, avg_azimuth_alphabet; + int16_t avg_elevation_idx, avg_azimuth_index; + int16_t 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; + int16_t use_adapt_avg, idx; index_start = *index; nblocks = q_direction->cfg.nblocks; @@ -2696,39 +3375,39 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( diff_idx_min = DIRAC_DIFFUSE_LEVELS; /*Raw coding for high diffuseness*/ - FOR( b = start_band; b < nbands; b++ ) + for ( b = start_band; b < nbands; b++ ) { - IF( hrmasa_flag ) + if ( hrmasa_flag ) { diff_idx = 0; } - ELSE + else { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } diff_idx_min = min( diff_idx_min, diff_idx ); - IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { elev_alph[b] = no_theta_masa[bits_direction_masa[diff_idx] - 3]; } - ELSE + 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 ) + 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 ) + if ( q_direction->not_in_2D > 0 ) { decode_fixed_rate( q_direction, bitstream, index, b, nblocks ); } - ELSE + else { /* in 2D */ - FOR( m = 0; m < nblocks; m++ ) + for ( m = 0; m < nblocks; m++ ) { q_direction->band_data[b].elevation[m] = 0.f; q_direction->band_data[b].elevation_index[m] = 0; @@ -2739,7 +3418,7 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( } } } - ELSE + else { bands_entropic[b] = 1; } @@ -2748,14 +3427,14 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( /*EC for the low diffuseness*/ /*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 ) + if ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) { 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 { 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 ); @@ -2763,53 +3442,53 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( } gr_param_elev = ivas_qmetadata_DecodeQuasiUniform( bitstream, index, 4 + 1 ); - IF( gr_param_elev == 4 ) /* all the elevation distances are zero */ + if ( gr_param_elev == 4 ) /* all the elevation distances are zero */ { - FOR( b = start_band; b < nbands; b++ ) + for ( b = start_band; b < nbands; b++ ) { - IF( bands_entropic[b] ) + if ( bands_entropic[b] ) { - Word16 tmp_index; - IF( hrmasa_flag ) + int16_t tmp_index; + if ( hrmasa_flag ) { diff_idx = 0; } - ELSE + else { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } - IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + 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 + else { avg_elevation_index_projected = ivas_dirac_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); /*reorder elevation indexing*/ tmp_index = avg_elevation_index_projected - ( elev_alph[b] >> 1 ); - IF( tmp_index < 0 ) + if ( tmp_index < 0 ) { tmp_index = tmp_index * -2; } - ELSE IF( tmp_index > 0 ) + else if ( tmp_index > 0 ) { tmp_index = tmp_index * 2 - 1; } avg_elevation_index_projected = tmp_index; } - FOR( m = 0; m < nblocks; m++ ) + 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 ) + 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 + else { azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][( q_direction->band_data[b].elevation_index[m] + 1 ) >> 1]; } @@ -2820,33 +3499,33 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( } } } - ELSE + else { - FOR( b = start_band; b < nbands; b++ ) + for ( b = start_band; b < nbands; b++ ) { - IF( bands_entropic[b] ) + if ( bands_entropic[b] ) { - IF( hrmasa_flag ) + if ( hrmasa_flag ) { diff_idx = 0; } - ELSE + else { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } - FOR( m = 0; m < nblocks; m++ ) + for ( m = 0; m < nblocks; m++ ) { - Word16 tmp_index; - IF( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) + int16_t 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 ) + if ( tmp_index % 2 ) { tmp_index = avg_elevation_index_projected + ( ( tmp_index + 1 ) >> 1 ); } - ELSE + else { tmp_index = avg_elevation_index_projected - ( tmp_index >> 1 ); } @@ -2855,7 +3534,7 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( /*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 + else { avg_elevation_index_projected = ivas_dirac_project_elevation_index( avg_elevation_idx, avg_elevation_alphabet, elev_alph[b] ); @@ -2864,11 +3543,11 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( /*reorder elevation indexing*/ tmp_index = tmp_index - ( elev_alph[b] >> 1 ); - IF( tmp_index < 0 ) + if ( tmp_index < 0 ) { tmp_index = tmp_index * -2; } - ELSE IF( tmp_index > 0 ) + else if ( tmp_index > 0 ) { tmp_index = tmp_index * 2 - 1; } @@ -2885,31 +3564,31 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( } } } - ELSE + else { - FOR( b = start_band; b < nbands; b++ ) + for ( b = start_band; b < nbands; b++ ) { - IF( bands_entropic[b] ) + if ( bands_entropic[b] ) { - IF( hrmasa_flag ) + if ( hrmasa_flag ) { diff_idx = 0; } - ELSE + else { diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; } - FOR( m = 0; m < nblocks; m++ ) + 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 ) + 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 + else { azith_alph[b][m] = no_phi_masa[bits_direction_masa[diff_idx] - 1][( q_direction->band_data[b].elevation_index[m] + 1 ) >> 1]; } @@ -2928,21 +3607,21 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( 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 */ + if ( gr_param_azith == 5 ) /* all the azimuth distances are zero */ { - FOR( b = start_band; b < nbands; b++ ) + for ( b = start_band; b < nbands; b++ ) { - IF( bands_entropic[b] ) + if ( bands_entropic[b] ) { - FOR( m = 0; m < nblocks; m++ ) + 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 ) + if ( azith_alph[b][m] == 1 ) { q_direction->band_data[b].azimuth[m] = 0.f; } - ELSE + 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 ); } @@ -2950,19 +3629,19 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( } } } - ELSE + else { set_zero( avg_direction_vector, 3 ); use_adapt_avg = 0; idx = 0; - FOR( b = start_band; b < nbands; b++ ) + for ( b = start_band; b < nbands; b++ ) { - IF( bands_entropic[b] ) + if ( bands_entropic[b] ) { - FOR( m = 0; m < nblocks; m++ ) + 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 ) ) + 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 )--; @@ -2971,26 +3650,26 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( 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 ) + if ( azith_alph[b][m] == 1 ) { q_direction->band_data[b].azimuth[m] = 0.f; } - ELSE + 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 ( ( q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ) && ( nblocks > 1 ) ) { - IF( idx < MASA_LIMIT_IDX_AVG_AZI ) + 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 + else { - IF( use_adapt_avg == 1 ) + if ( use_adapt_avg == 1 ) { - IF( m == 0 ) + if ( m == 0 ) { v_multc( avg_direction_vector, 0.5f, avg_direction_vector, 3 ); } @@ -3013,107 +3692,96 @@ static Word16 ivas_qmetadata_entropy_decode_dir_fx( #endif /*------------------------------------------------------------------------- - * ivas_qmetadata_raw_decode_dir() + * ivas_qmetadata_raw_decode_dir_512_fx() * * 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_raw_decode_dir_512_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, + UWord16 *bitstream, /* i : bitstream */ + Word16 *index, + const Word16 nbands, + const Word16 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; + Word16 b, m, i; + Word16 nblocks; + Word16 index_start; + UWord16 value; index_start = *index; nblocks = q_direction->cfg.nblocks; - for ( b = start_band; b < nbands; b++ ) + FOR( b = start_band; b < nbands; b++ ) { - for ( m = 0; m < nblocks; m++ ) + FOR( m = 0; m < nblocks; m++ ) { value = 0; - for ( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) + 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 ) + 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] ) ); + deindex_sph_idx_fx( value, sph_grid16, &( q_direction->band_data[b].elevation_fx[m] ), &( q_direction->band_data[b].azimuth_fx[m] ) ); } - 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 ); + 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 ); } } } 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( +#else +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 int16_t hrmasa_flag /* i : flag indicating high-rate MASA MD coding*/ + const SPHERICAL_GRID_DATA *sph_grid16 /* i : spherical grid for deindexing */ ) { - int16_t b, m, azith_alph; - int16_t diff_idx; + 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++ ) { - if ( q_direction->not_in_2D > 0 ) - { - decode_fixed_rate( q_direction, bitstream, index, b, nblocks ); - } - else + 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++ ) { - diff_idx = 0; + value = ( value << 1 ) + bitstream[( *index )--]; } - else + q_direction->band_data[b].spherical_index[m] = value; + + if ( q_direction->band_data[b].bits_sph_idx[m] == 16 ) { - diff_idx = q_direction->band_data[b].energy_ratio_index_mod[0]; + deindex_sph_idx( value, sph_grid16, &( q_direction->band_data[b].elevation[m] ), &( q_direction->band_data[b].azimuth[m] ) ); } - - for ( m = 0; m < nblocks; m++ ) + else { - 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 ); + 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 ); } +#endif + #ifdef IVAS_FLOAT_FIXED static Word16 ivas_qmetadata_raw_decode_dir_fx( @@ -3163,6 +3831,60 @@ static Word16 ivas_qmetadata_raw_decode_dir_fx( return ( index_start - *index ); } +#else +/*------------------------------------------------------------------------- + * 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; + + 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 ); +} #endif /*------------------------------------------------------------------------- @@ -3924,7 +4646,6 @@ static Word16 decode_azimuth_fx( 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); } } } @@ -4390,15 +5111,48 @@ static int16_t decode_elevation( q_direction->band_data[j].elevation_index[k] = 0; } } - } + } + + nbits = *pbit_pos - bit_pos; + *pbit_pos = bit_pos; + + return nbits; +} +#endif + + +#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 = 0; + FOR( i = 0; i < q_direction->band_data[b].bits_sph_idx[m]; i++ ) + { + value = ( value << 1 ) + bitstream[( *pbit_pos )--]; + } - nbits = *pbit_pos - bit_pos; - *pbit_pos = bit_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 ); + } return nbits; } -#endif +#else /*---------------------------------------------------------------- * decode_fixed_rate() * @@ -4435,37 +5189,6 @@ static int16_t decode_fixed_rate( 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 = 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 ); - } - - return nbits; -} #endif /*-------------------------------------------------------------------* * decode_azimuth2D() @@ -5148,7 +5871,7 @@ static void decode_spread_coherence_fx( 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 ); + minimum_s( (Word16 *) ( q_direction->band_data[i].energy_ratio_index ), q_direction->cfg.nblocks, &min_index ); min_index = min_index >> 1; } ELSE @@ -5778,25 +6501,25 @@ static Word16 read_coherence_data_hr_512_fx( 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 ) ); + hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (UWord8) L_add( Mpy_32_32( decoded_idx_fx, delta_fx ), L_shr( delta_fx, 23 ) ); } } - else + ELSE { /* read min_index */ min_index = 0; - for ( i = 0; i < nbits_coh; i++ ) + 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++ ) + 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 ) ); + hQMetaData->q_direction[idx_dir].coherence_band_data[j].spread_coherence[k] = (UWord8) L_add( Mpy_32_32( decoded_idx_fx, delta_fx ), L_shr( delta_fx, 23 ) ); } } } @@ -5916,7 +6639,7 @@ static Word16 read_coherence_data_fx( Word32 res; coding_subbands = hQMetaData->q_direction[idx_dir].cfg.nbands; - extra_cv = (int16_t) ( coding_subbands / MASA_FACTOR_CV_COH ); + extra_cv = (Word16) ( coding_subbands / MASA_FACTOR_CV_COH ); q_direction = &( hQMetaData->q_direction[idx_dir] ); bit_pos = *p_bit_pos; nbits = 0; @@ -5963,7 +6686,7 @@ static Word16 read_coherence_data_fx( 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] = (UWord8) (round_fx( res )); + q_direction->coherence_band_data[j].spread_coherence[0] = (UWord8) ( round_fx( res ) ); } ELSE { @@ -5973,7 +6696,7 @@ static Word16 read_coherence_data_fx( } ELSE { - uint16_t decoded_index[MASA_MAXIMUM_CODING_SUBBANDS]; + UWord16 decoded_index[MASA_MAXIMUM_CODING_SUBBANDS]; /* decode joint index */ 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++ ) @@ -5987,7 +6710,7 @@ static Word16 read_coherence_data_fx( 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] = (UWord8) (round_fx( res )); + q_direction->coherence_band_data[j].spread_coherence[0] = (UWord8) ( round_fx( res ) ); } ELSE { @@ -6071,7 +6794,7 @@ static Word16 read_coherence_data_fx( no_bits_vec = ceil_log_2( no_cb ); // (int16_t)ceilf(logf((float)no_cb) * INV_LOG_2); - /* read joint index for DCT0 */ + /* 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; @@ -6358,6 +7081,7 @@ static int16_t read_coherence_data( * *-------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static int16_t read_surround_coherence( uint16_t *bitstream, /* i : bitstream */ int16_t *p_bit_pos, /* i : position in the bitstream */ @@ -6519,6 +7243,172 @@ static int16_t read_surround_coherence( return bits_sur_coherence; } +#else +static Word16 read_surround_coherence( + UWord16 *bitstream, /* i : bitstream */ + Word16 *p_bit_pos, /* i : position in the bitstream */ + IVAS_QMETADATA *hQMetaData /* i/o: quantized metadata structure */ +) +{ + Word16 coding_subbands; + Word16 no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 bit_pos; + Word32 error_ratio_surr; + Word16 idx_ER[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 bits_sur_coherence, bits_GR; + Word16 j, d, k, idx; + UWord16 byteBuffer; + UWord16 idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS]; + IVAS_QDIRECTION *q_direction; + Word16 min_index; + + coding_subbands = hQMetaData->q_direction[0].cfg.nbands; + q_direction = hQMetaData->q_direction; + + bits_sur_coherence = 0; + bit_pos = *p_bit_pos; + + d = 0; + FOR( j = 0; j < coding_subbands; j++ ) + { + error_ratio_surr = ONE_IN_Q30; + + IF( EQ_16( hQMetaData->no_directions, 2 ) ) + { + d = add( d, hQMetaData->twoDirBands[j] ); + idx = s_max( sub( d, 1 ), 0 ); + IF( EQ_16( hQMetaData->twoDirBands[j], 1 ) ) + { + error_ratio_surr = L_sub( L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ), q_direction[1].band_data[idx].energy_ratio_fx[0] ); + } + ELSE + { + error_ratio_surr = L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ); + } + } + ELSE + { + error_ratio_surr = L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ); + } + + IF( LE_32( error_ratio_surr, 0 ) ) + { + error_ratio_surr = 0; + no_cv_vec[j] = 1; + idx_ER[j] = masa_sq_fx( 0, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); + } + ELSE + { + idx_ER[j] = masa_sq_fx( error_ratio_surr, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS ); + no_cv_vec[j] = idx_cb_sur_coh_masa[idx_ER[j]] + 2; + } + } + + IF( EQ_16( 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; + } + } + } + + return bits_sur_coherence; + } + + /* read how the surround coherence is encoded */ + byteBuffer = bitstream[bit_pos--]; + bits_sur_coherence = add( bits_sur_coherence, 1 ); + + IF( byteBuffer & 1 ) + { + /* GR decoding */ + /* read GR order */ + byteBuffer = bitstream[bit_pos--]; + bits_sur_coherence = add( bits_sur_coherence, 1 ); + + /* 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 = add( bits_sur_coherence, sub( bits_GR, bit_pos ) ); + + /* read GR data */ + FOR( j = 0; j < coding_subbands; j++ ) + { + bits_GR = bit_pos; + /* decoding for min removed */ + IF( GT_16( 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 = add( bits_sur_coherence, sub( bits_GR, bit_pos ) ); + } + ELSE + { + idx_sur_coh[j] = 0; + } + } + + FOR( j = 0; j < coding_subbands; j++ ) + { + IF( GT_16( no_cv_vec[j], 1 ) ) + { + hQMetaData->surcoh_band_data[j].sur_coherence_index = add( idx_sur_coh[j], min_index ); + } + ELSE + { + hQMetaData->surcoh_band_data[j].sur_coherence_index = idx_sur_coh[j]; + } + + hQMetaData->surcoh_band_data[j].surround_coherence[0] = sur_coherence_cb_masa[add( shl( idx_cb_sur_coh_masa[idx_ER[j]], 3 ), hQMetaData->surcoh_band_data[j].sur_coherence_index )]; + } + } + ELSE + { + /* fixed rate */ + 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_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++ ) + { + 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[add( shl( idx_cb_sur_coh_masa[idx_ER[j]], 3 ), 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 = sub( *p_bit_pos, bit_pos ); + *p_bit_pos = bit_pos; + + return bits_sur_coherence; +} +#endif // !IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* @@ -6526,7 +7416,7 @@ static int16_t read_surround_coherence( * * *-------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED static int16_t read_surround_coherence_hr( uint16_t *bitstream, /* i : bitstream */ int16_t *p_bit_pos, /* i : position in the bitstream */ @@ -6682,13 +7572,12 @@ static int16_t read_surround_coherence_hr( return bits_sur_coherence; } - -#ifdef IVAS_FLOAT_FIXED1 +#else 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 ) + Word64 energy_ratio[][MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES] ) { Word16 coding_subbands; Word16 no_cv_vec[MASA_MAXIMUM_CODING_SUBBANDS]; @@ -6708,10 +7597,11 @@ static Word16 read_surround_coherence_hr_fx( bits_sur_coherence = 0; bit_pos = *p_bit_pos; - for ( sf = 0; sf < hQMetaData->q_direction[0].cfg.nblocks; sf++ ) + FOR( sf = 0; sf < hQMetaData->q_direction[0].cfg.nblocks; sf++ ) { d = 0; - for ( j = 0; j < coding_subbands; j++ ) +#ifdef IVAS_FLOAT_FIXED_TBD + FOR( j = 0; j < coding_subbands; j++ ) { error_ratio_surr_fx = 1 << *q; if ( hQMetaData->no_directions == 2 ) @@ -6722,7 +7612,7 @@ static Word16 read_surround_coherence_hr_fx( 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 + ELSE { error_ratio_surr_fx = L_sub( 1 << *q, q_direction[0].band_data[j].energy_ratio_fx[sf] ); } @@ -6733,34 +7623,74 @@ static Word16 read_surround_coherence_hr_fx( no_cv_vec[j] = 1; idx_ER[j] = 0; } - else + 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; } } +#else + /* NOTE: This block gives incorrect output with fixed point resulting in failures in pytest */ + /* TODO: Remove the intermediate conversion from fixed to float below */ + float tmp; + float energy_ratio_j_sf; + float energy_ratio_idx_sf; + FOR( j = 0; j < coding_subbands; j++ ) + { + energy_ratio_j_sf = (float) energy_ratio[0][j][sf] / ( ONE_IN_Q62 ); - if ( sum_s( no_cv_vec, coding_subbands ) == coding_subbands ) + tmp = 1.0f; + IF( hQMetaData->no_directions == 2 ) + { + d += hQMetaData->twoDirBands[j]; + idx = max( d - 1, 0 ); + + energy_ratio_idx_sf = (float) energy_ratio[1][idx][sf] / ( ONE_IN_Q62 ); + + tmp = 1.0f - energy_ratio_j_sf - energy_ratio_idx_sf * hQMetaData->twoDirBands[j]; + } + ELSE + { + tmp = 1.0f - energy_ratio_j_sf; + } + + error_ratio_surr_fx = (Word32) ( tmp * ONE_IN_Q30 ); + + IF( error_ratio_surr_fx <= 0 ) + { + error_ratio_surr_fx = 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; + } + } +#endif // !IVAS_FLOAT_FIXED_TBD + + IF( sum_s( no_cv_vec, coding_subbands ) == coding_subbands ) { /* surround coherence is zero */ - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { - for ( k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) + FOR( k = 0; k < MAX_PARAM_SPATIAL_SUBFRAMES; k++ ) { - if ( hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->surcoh_band_data != NULL ) { hQMetaData->surcoh_band_data[j].surround_coherence[k] = 0; } } } } - else + ELSE { /* read how the surround coherence is encoded */ byteBuffer = bitstream[bit_pos--]; bits_sur_coherence += 1; - if ( byteBuffer & 1 ) + IF( byteBuffer & 1 ) { /* GR decoding */ /* read GR order */ @@ -6773,36 +7703,36 @@ static Word16 read_surround_coherence_hr_fx( bits_sur_coherence += bits_GR - bit_pos; /* read GR data */ - for ( j = 0; j < coding_subbands; j++ ) + FOR( j = 0; j < coding_subbands; j++ ) { bits_GR = bit_pos; /* decoding for min removed */ - if ( no_cv_vec[j] > 1 ) + 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 + ELSE { idx_sur_coh[j] = 0; } } - 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 ) { 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 + ELSE { hQMetaData->surcoh_band_data[j].sur_coherence_index = idx_sur_coh[j]; hQMetaData->surcoh_band_data[j].surround_coherence[sf] = 0; } } } - else + ELSE { /* fixed rate */ UWord16 sur_coh_temp_index[MASA_MAXIMUM_CODING_SUBBANDS]; @@ -6810,19 +7740,19 @@ static Word16 read_surround_coherence_hr_fx( 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++ ) + 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++ ) + FOR( j = 0; j < coding_subbands; j++ ) { - if ( no_cv_vec[j] > 1 ) + 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 + ELSE { hQMetaData->surcoh_band_data[j].surround_coherence[sf] = 0; } @@ -6837,6 +7767,7 @@ static Word16 read_surround_coherence_hr_fx( return bits_sur_coherence; } + #endif /*-------------------------------------------------------------------* diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index 57748c35a..abcfedf8a 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -368,8 +368,46 @@ ivas_error ivas_spar_dec( /* read DirAC bitstream */ if ( st_ivas->hQMetaData != NULL ) - { + { +#ifdef IVAS_FLOAT_FIXED + // To do remove this code once ivas_spar_dec_MD is done + for ( int d = 0; d < st_ivas->hQMetaData->no_directions; d++ ) + { + IVAS_QDIRECTION *q_direction; + q_direction = &st_ivas->hQMetaData->q_direction[d]; + int nbands = q_direction->cfg.nbands; + 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] = (Word32) ( q_direction->band_data[j].elevation[k] * ( 1 << 22 ) ); + q_direction->band_data[j].azimuth_fx[k] = (Word32) ( q_direction->band_data[j].azimuth[k] * ( 1 << 22 ) ); + q_direction->band_data[j].energy_ratio_fx[k] = (Word32) ( q_direction->band_data[j].energy_ratio[k] * ( 1 << 30 ) ); + } + } + } +#endif ivas_dirac_dec_read_BS( hDecoderConfig->ivas_total_brate, st0, st_ivas->hDirAC, st_ivas->hSpatParamRendCom, st_ivas->hQMetaData, nb_bits_read, last_bit_pos, ivas_get_hodirac_flag( hDecoderConfig->ivas_total_brate, st_ivas->sba_analysis_order ), st_ivas->hSpar->dirac_to_spar_md_bands ); + +#ifdef IVAS_FLOAT_FIXED + // To do remove this code once ivas_spar_dec_MD is done + for ( int d = 0; d < st_ivas->hQMetaData->no_directions; d++ ) + { + IVAS_QDIRECTION *q_direction; + q_direction = &st_ivas->hQMetaData->q_direction[d]; + int nbands = q_direction->cfg.nbands; + 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] / ( 1 << 22 ) ); + q_direction->band_data[j].azimuth[k] = ( (float) q_direction->band_data[j].azimuth_fx[k] / ( 1 << 22 ) ); + q_direction->band_data[j].energy_ratio[k] = ( (float) q_direction->band_data[j].energy_ratio_fx[k] / ( 1 << 30 ) ); + } + } + } +#endif } if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) -- GitLab From 220fe6283599037ce04ac62614ae759f04a49e23 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Mon, 22 Jan 2024 11:26:09 +0530 Subject: [PATCH 2/2] remove reference of prot_fx.h --- lib_com/tools_fx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index e3d99e01d..d900420a4 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -45,7 +45,6 @@ #include "stl.h" #include #include "cnst.h" -#include "prot_fx.h" #include "prot_fx1.h" #include "prot_fx2.h" #include "basop_util.h" -- GitLab