LCOV - code coverage report
Current view: top level - lib_enc - ivas_qmetadata_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 2785 2995 93.0 %
Date: 2025-05-03 01:55:50 Functions: 53 53 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <assert.h>
      34             : #include <stdint.h>
      35             : #include "options.h"
      36             : #include <math.h>
      37             : #include "ivas_cnst.h"
      38             : #include "prot_fx.h"
      39             : #include "ivas_prot_fx.h"
      40             : #include "ivas_rom_com.h"
      41             : #include "ivas_stat_enc.h"
      42             : #include "wmc_auto.h"
      43             : 
      44             : #include "basop_util.h"
      45             : #include "ivas_rom_com_fx.h"
      46             : 
      47             : /*-----------------------------------------------------------------------*
      48             :  * Local function prototypes
      49             :  *-----------------------------------------------------------------------*/
      50             : 
      51             : static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_fx( IVAS_QMETADATA_HANDLE hQMetaData, Word16 *needed_bits, Word16 *nbits_diff, Word16 *dfRatioBits, const Word16 hodirac_flag );
      52             : 
      53             : static Word16 ivas_qmetadata_entropy_encode_diffuseness_fx(
      54             :     BSTR_ENC_HANDLE hMetaData,
      55             :     IVAS_QDIRECTION *q_direction,
      56             :     UWord16 *diffuseness_index_max_ec_frame );
      57             : 
      58             : static void ivas_qmetadata_reorder_2dir_bands_fx( IVAS_QMETADATA_HANDLE hQMetaData );
      59             : 
      60             : static Word16 ivas_qmetadata_entropy_encode_df_ratio_fx(
      61             :     BSTR_ENC_HANDLE hMetaData,
      62             :     IVAS_QDIRECTION *q_direction,
      63             :     Word16 *df_ratio_bits );
      64             : 
      65             : static Word16 ivas_qmetadata_entropy_encode_dir_fx(
      66             :     BSTR_ENC_HANDLE hMetaData,
      67             :     IVAS_QDIRECTION *q_direction,
      68             :     const UWord16 diffuseness_index_max_ec_frame,
      69             :     const Word16 nbands,
      70             :     const Word16 start_band,
      71             :     const Word16 direction_bits_raw,
      72             :     Word16 max_bits,
      73             :     const Word16 hrmasa_flag );
      74             : 
      75             : static Word16 ivas_qmetadata_raw_encode_dir_fx(
      76             :     BSTR_ENC_HANDLE hMetaData,
      77             :     IVAS_QDIRECTION *q_direction,
      78             :     const Word16 nbands,
      79             :     const Word16 start_band );
      80             : 
      81             : 
      82             : static Word16 ivas_qmetadata_get_optimal_gr_param_fx(
      83             :     UWord16 *unsigned_data,
      84             :     const Word16 count,
      85             :     const Word16 gr_param_count,
      86             :     Word16 *opt_gr_size );
      87             : 
      88             : Word16 ivas_qmetadata_encode_extended_gr_length_fx( const UWord16 value, const UWord16 alphabet_size, const Word16 gr_param );
      89             : 
      90             : static Word16 ivas_qmetadata_encode_quasi_uniform_length_fx( const UWord16 value, const UWord16 alphabet_size );
      91             : 
      92             : static void ivas_qmetadata_encode_quasi_uniform_fx( BSTR_ENC_HANDLE hMetaData, const UWord16 value, const UWord16 alphabet_size );
      93             : 
      94             : static Word16 ivas_qmetadata_reorder_elevation_index_fx(
      95             :     const Word16 elevation_index,
      96             :     const Word16 avg_elevation_index,
      97             :     const Word16 elevation_alphabet );
      98             : 
      99             : static Word16 ivas_qmetadata_reorder_azimuth_index_fx(
     100             :     const Word16 azimuth_index,
     101             :     const Word16 avg_azimuth_index,
     102             :     const Word16 azimuth_alphabet );
     103             : static ivas_error requantize_direction_EC_3_fx( Word16 *extra_bits, IVAS_QDIRECTION *q_direction, const Word16 coding_subbands, BSTR_ENC_HANDLE hMetaData, Word32 elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], Word32 azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], Word16 *ind_order );
     104             : 
     105             : 
     106             : static void calculate_two_distances_fx(
     107             :     Word32 *el_fx,           /* i  : elevation values                  */
     108             :     Word16 *bits,            /* i  : number of bits for each tile      */
     109             :     const Word16 total_bits, /* i  : total number of bits for subband  */
     110             :     const Word16 len,        /* i  : number of tiles                   */
     111             :     Word32 *p_d1,            /* o  : first distortion                  */
     112             :     Word32 *p_d2,            /* o  : second distortion                 */
     113             :     Word16 *Q_out );
     114             : 
     115             : static void joint_encoding_fx( IVAS_QDIRECTION *q_direction, const Word16 j, const Word16 next_j, const Word16 coding_subbands, Word16 *bits_dir0, const Word16 allowed_bits, BSTR_ENC_HANDLE hMetaData, Word16 *diff );
     116             : static ivas_error write_ec_direction_fx( Word16 *num_bits_written, BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, const Word16 j_idx, const Word16 len, const Word16 GR_ord_elevation, const Word16 GR_ord_azimuth, const Word16 use_context, const Word16 same );
     117             : static Word16 write_fixed_rate_direction_fx( BSTR_ENC_HANDLE hMetaData, IVAS_QDIRECTION *q_direction, const Word16 j_idx, const Word16 len );
     118             : 
     119             : 
     120             : static Word16 ivas_qmetadata_quantize_coherence_fx(
     121             :     IVAS_QMETADATA *hQMetaData,      /* i/o: quantized metadata                        */
     122             :     const Word16 idx_d,              /* i  : current direction index                   */
     123             :     const Word16 all_coherence_zero, /* i  : all coherence is zero - flag              */
     124             :     BSTR_ENC_HANDLE hMetaData,       /* i  : metadata handle                           */
     125             :     const Word16 write_flag,         /* i  : flag to actually write the data or not    */
     126             :     Word16 *indice_coherence,
     127             :     const Word16 hrmasa_flag /* i  : flag indicating high-rate MASA MD coding  */
     128             : );
     129             : 
     130             : static void dct4_transform_fx(
     131             :     UWord8 *v,    /* i  : input 4D vector */
     132             :     Word32 *dct_v /* o  : output transformed vector Q31 */
     133             : );
     134             : 
     135             : static Word32 quantize_DCT_0_coh_fx( // o:Q21
     136             :     const Word16 x,                  /* i  : input value                                              Q14  */
     137             :     const Word16 j,                  /* i  : subband index                                              */
     138             :     const Word16 *coherence_cb,      /* i  : coherence codebook                                       Q14  */
     139             :     const Word16 delta_var,          /* i  : azimuth variance threshold                               Q6  */
     140             :     const Word16 no_cb,              /* i  : maximum number of codewords                                */
     141             :     IVAS_QDIRECTION *q_direction,    /* i  : quantized metadata                                         */
     142             :     UWord16 *idx_x,                  /* o  : codewords index                                            */
     143             :     Word16 *p_no_cb,                 /* o  : actual number of codewords dependent on energy ratio value */
     144             :     const Word16 hrmasa_flag         /* i  : flag indicating high-rate MASA MD coding                   */
     145             : );
     146             : 
     147             : static Word16 encode_coherence_indexesDCT0_fx(
     148             :     UWord16 *idx_dct,  /* i  : indexes to be encoded                 */
     149             :     const Word16 len,  /* i  : number of indexes                     */
     150             :     Word16 *no_cb_vec, /* i  : number of codewords for each position */
     151             :     BSTR_ENC_HANDLE hMetaData,
     152             :     const Word16 indice_coherence,
     153             :     const Word16 nbits,
     154             :     const Word16 nbits1 );
     155             : 
     156             : static Word16 encode_coherence_indexesDCT1_fx(
     157             :     UWord16 *idx_dct,         /* i  : data to be encoded   */
     158             :     const Word16 len,         /* i  : number of data       */
     159             :     BSTR_ENC_HANDLE hMetaData /* i  : metadata handle      */
     160             : );
     161             : 
     162             : static UWord64 create_combined_index_fx( UWord16 *idx_dct, const Word16 len, const Word16 *no_cb_vec );
     163             : 
     164             : static Word16 encode_surround_coherence_fx(
     165             :     IVAS_QMETADATA *hQMetaData, /* i  : quantized metadata            */
     166             :     BSTR_ENC_HANDLE hMetaData   /* i/o: metadata bitstream handle     */
     167             : );
     168             : static Word16 common_direction_fx(
     169             :     IVAS_QDIRECTION *q_direction,
     170             :     const Word16 band_idx,
     171             :     const Word16 len,
     172             :     const Word16 bits_allowed,
     173             :     BSTR_ENC_HANDLE hMetaData,
     174             :     Word32 *elevation_orig_fx,
     175             :     Word32 *azimuth_orig_fx );
     176             : static Word16 ivas_diffuseness_huff_ec_encode_fx(
     177             :     BSTR_ENC_HANDLE hMetaData,
     178             :     const UWord16 idx );
     179             : 
     180             : static void ivas_diffuseness_huff_ec_prepare_fx(
     181             :     IVAS_QDIRECTION *q_direction,
     182             :     Word16 *best_av,
     183             :     UWord16 *avr_idx,
     184             :     Word16 *diffuseness_bits_huff );
     185             : 
     186             : static Word16 coherence_coding_length( const UWord16 *idx_sur_coh_shift, const UWord8 idx_shift_len, const Word16 coding_subbands, const Word16 *no_cv, UWord16 *mr_idx, Word16 *no_cv_shift, Word16 *p_min_idx, Word16 *GR_ord, Word16 *nbits_fr, Word16 *nbits_fr1 );
     187             : 
     188             : static Word16 write_2dir_info( BSTR_ENC_HANDLE hMetaData, UWord8 *twoDirBands, const Word16 n, const Word16 k );
     189             : 
     190             : static void transform_azimuth_dir2_fx(
     191             :     IVAS_QMETADATA_HANDLE hQMetaData,
     192             :     Word16 *dir2_bands );
     193             : 
     194             : static Word16 ivas_qmetadata_quantize_coherence_hr_512_fx( IVAS_QMETADATA *hQMetaData, const Word16 idx_d, const Word16 all_coherence_zero, BSTR_ENC_HANDLE hMetaData, const Word16 bits_coh );
     195             : 
     196             : static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512_fx( IVAS_QMETADATA_HANDLE hQMetaData, Word16 *needed_bits, const Word16 bits_dir_hr, BSTR_ENC_HANDLE hMetaData );
     197             : 
     198             : static Word16 calc_var_azi_fx( const IVAS_QDIRECTION *q_direction, const Word16 diffuseness_index_max_ec_frame, const Word32 avg_azimuth, Word32 *avg_azimuth_out );
     199             : 
     200             : static Word16 encode_surround_coherence_hr_fx( IVAS_QMETADATA *hQMetaData, BSTR_ENC_HANDLE hMetaData );
     201             : 
     202             : static Word16 write_stream_dct_coeffs_omasa_fx( Word16 *q_idx, const Word16 len_stream, BSTR_ENC_HANDLE hMetaData, const Word16 first_line, const Word16 low_bitrate_mode );
     203             : 
     204             : static Word16 find_optimal_GR_order_fx( const Word16 *q_idx, const Word16 len, Word16 *GR );
     205             : 
     206             : static Word16 find_optimal_GR_orders_fx( const Word16 *q_idx, const Word16 len, const Word16 len_max_GR1, Word16 *GR1, Word16 *GR2, Word16 *i_min );
     207             : 
     208             : 
     209             : /*-----------------------------------------------------------------------*
     210             :  * ivas_qmetadata_enc_encode()
     211             :  *
     212             :  * Main function for quantizing and coding Spatial Metadata
     213             :  *-----------------------------------------------------------------------*/
     214             : 
     215      202957 : ivas_error ivas_qmetadata_enc_encode_fx(
     216             :     BSTR_ENC_HANDLE hMetaData,  /* i/o: metadata bitstream handle       */
     217             :     IVAS_QMETADATA *hQMetaData, /* i/o: metadata handle                 */
     218             :     const Word16 hodirac_flag   /* i  : flag to indicate HO-DirAC mode  */
     219             : )
     220             : {
     221             :     Word16 i, bit_pos_start, bit_pos_start_coh;
     222             :     Word16 next_ind_start;
     223             :     UWord16 diffuseness_index_max_ec_frame;
     224             :     UWord16 diffuseness_index_max_ec_frame_pre[QMETADATA_MAX_NO_DIRECTIONS];
     225             :     Word16 bits_dir_raw_pre[QMETADATA_MAX_NO_DIRECTIONS];
     226             :     Word16 bits_diff_sum;
     227             :     Word16 bits_diff[QMETADATA_MAX_NO_DIRECTIONS], bits_coherence[QMETADATA_MAX_NO_DIRECTIONS];
     228             :     Word16 bits_dir[QMETADATA_MAX_NO_DIRECTIONS], bits_dir_raw;
     229             :     Word16 extra_bits;
     230             :     IVAS_QDIRECTION *q_direction;
     231             :     Word16 nbands, nblocks, start_band;
     232             :     Word16 ndirections, d;
     233             :     Word32 azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES];
     234             :     Word16 all_coherence_zero;
     235             :     Word16 bit_pos_0, total_bits_1dir, bits_no_dirs_coh;
     236             :     Word16 bits_signaling[QMETADATA_MAX_NO_DIRECTIONS];
     237             :     Word16 indice_coherence;
     238             :     Word16 bits_dir_bands[MASA_MAXIMUM_CODING_SUBBANDS], raw_flag[MASA_MAXIMUM_CODING_SUBBANDS];
     239             :     Word16 diff_bits, bits_ec, next_ind_raw_flag;
     240             :     Word16 dfRatio_bits[MASA_MAXIMUM_CODING_SUBBANDS];
     241             :     Word16 bits_surround_coh, no_TF;
     242             :     Word16 dir2_bands[MASA_MAXIMUM_TWO_DIR_BANDS];
     243             :     Word16 ind_order[MASA_MAXIMUM_CODING_SUBBANDS];
     244             :     Word16 reduce_bits;
     245             :     ivas_error error;
     246             : 
     247      202957 :     error = IVAS_ERR_OK;
     248      202957 :     move32();
     249             : 
     250             :     /* Save initial position in bitstream */
     251      202957 :     bit_pos_0 = hMetaData->nb_bits_tot;
     252      202957 :     move16();
     253      202957 :     bit_pos_start = bit_pos_0;
     254      202957 :     move16();
     255             : 
     256      202957 :     ndirections = hQMetaData->no_directions;
     257      202957 :     move16();
     258      202957 :     extra_bits = 0;
     259      202957 :     move16();
     260             : 
     261             :     /* Check if coherence should be encoded */
     262      202957 :     all_coherence_zero = 1;
     263      202957 :     move16();
     264      202957 :     bits_no_dirs_coh = 0;
     265      202957 :     move16();
     266             : 
     267      202957 :     IF( hQMetaData->coherence_flag )
     268             :     {
     269       27866 :         all_coherence_zero = hQMetaData->all_coherence_zero;
     270       27866 :         move16();
     271             : 
     272       27866 :         push_next_indice( hMetaData, all_coherence_zero, 1 ); /* signal coherence */
     273       27866 :         bits_no_dirs_coh = add( bits_no_dirs_coh, 1 );
     274             :     }
     275             : 
     276      202957 :     IF( GT_16( ndirections, 1 ) )
     277             :     {
     278             :         /* Reorder 2dir bands for more efficient encoding. */
     279       20820 :         IF( !hodirac_flag )
     280             :         {
     281        4580 :             ivas_qmetadata_reorder_2dir_bands_fx( hQMetaData );
     282             :         }
     283       20820 :         d = 0;
     284       20820 :         move16();
     285      255252 :         FOR( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ )
     286             :         {
     287      234432 :             IF( EQ_16( hQMetaData->twoDirBands[i], 1 ) )
     288             :             {
     289      208080 :                 Copy32( hQMetaData->q_direction[1].band_data[i].azimuth_fx, hQMetaData->q_direction[1].band_data[d].azimuth_fx, hQMetaData->q_direction[1].cfg.nblocks );           // Q22
     290      208080 :                 Copy32( hQMetaData->q_direction[1].band_data[i].elevation_fx, hQMetaData->q_direction[1].band_data[d].elevation_fx, hQMetaData->q_direction[1].cfg.nblocks );       // Q22
     291      208080 :                 Copy32( hQMetaData->q_direction[1].band_data[i].energy_ratio_fx, hQMetaData->q_direction[1].band_data[d].energy_ratio_fx, hQMetaData->q_direction[1].cfg.nblocks ); // Q30
     292             : 
     293      208080 :                 dir2_bands[d] = i;
     294      208080 :                 move16();
     295             : 
     296      208080 :                 IF( hQMetaData->coherence_flag )
     297             :                 {
     298       13200 :                     mvc2c( hQMetaData->q_direction[1].coherence_band_data[i].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].cfg.nblocks );
     299             :                 }
     300      208080 :                 d = add( d, 1 );
     301             :             }
     302             :         }
     303             : 
     304       20820 :         bits_no_dirs_coh = add( bits_no_dirs_coh, write_2dir_info( hMetaData, hQMetaData->twoDirBands, hQMetaData->q_direction[0].cfg.nbands, hQMetaData->numTwoDirBands ) );
     305             : 
     306       47172 :         FOR( i = d; i < hQMetaData->q_direction[0].cfg.nbands; i++ )
     307             :         {
     308       26352 :             set32_fx( hQMetaData->q_direction[1].band_data[i].energy_ratio_fx, 0, hQMetaData->q_direction[1].cfg.nblocks );
     309             :         }
     310             : 
     311       20820 :         hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands;
     312       20820 :         move16();
     313             :     }
     314             : 
     315             :     /*Quantization of the Diffuseness */
     316      202957 :     ivas_qmetadata_quantize_diffuseness_nrg_ratios_fx( hQMetaData, bits_dir_raw_pre, bits_diff, dfRatio_bits, hodirac_flag );
     317             : 
     318      202957 :     bits_diff_sum = 0;
     319      202957 :     move16();
     320             : 
     321      202957 :     bits_diff[0] = ivas_qmetadata_entropy_encode_diffuseness_fx( hMetaData, &( hQMetaData->q_direction[0] ), &diffuseness_index_max_ec_frame_pre[0] );
     322      202957 :     move16();
     323      202957 :     bits_diff_sum = add( bits_diff_sum, bits_diff[0] );
     324             : 
     325      202957 :     IF( EQ_16( ndirections, 2 ) )
     326             :     {
     327       20820 :         bits_diff[1] = ivas_qmetadata_entropy_encode_df_ratio_fx( hMetaData, &( hQMetaData->q_direction[1] ), dfRatio_bits );
     328       20820 :         move16();
     329       20820 :         bits_diff_sum = add( bits_diff_sum, bits_diff[1] );
     330             :     }
     331             : 
     332             :     /* 2dir energy ratio encoding reuses index memory. Now that diffRatio and dFRatio have been encoded,
     333             :      * we retrieve index_dirRatio1Inv and index_dirRatio1Inv for further parameter encoding. This is
     334             :      * necessary only for bands that have two concurrent directions. */
     335      202957 :     IF( EQ_16( hQMetaData->no_directions, 2 ) )
     336             :     {
     337             :         Word16 j, k, dir2band, index_dirRatio1Inv, index_dirRatio2Inv;
     338             : 
     339       20820 :         dir2band = 0;
     340       20820 :         move16();
     341      255252 :         FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j )
     342             :         {
     343      234432 :             IF( EQ_16( hQMetaData->twoDirBands[j], 1 ) )
     344             :             {
     345      208080 :                 index_dirRatio1Inv = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
     346      208080 :                 index_dirRatio2Inv = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
     347             : 
     348     1031268 :                 FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ )
     349             :                 {
     350      823188 :                     hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index_dirRatio1Inv;
     351      823188 :                     move16();
     352             :                 }
     353             : 
     354     1031268 :                 FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ )
     355             :                 {
     356      823188 :                     hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[k] = index_dirRatio2Inv;
     357      823188 :                     move16();
     358             :                 }
     359             : 
     360      208080 :                 dir2band = add( dir2band, 1 );
     361             :             }
     362             :         }
     363             :     }
     364             : 
     365             :     /* Encode surround coherence */
     366      202957 :     IF( EQ_16( ndirections, 2 ) )
     367             :     {
     368       20820 :         no_TF = add( imult1616( hQMetaData->q_direction[0].cfg.nbands, hQMetaData->q_direction[0].cfg.nblocks ), imult1616( hQMetaData->q_direction[1].cfg.nbands, hQMetaData->q_direction[1].cfg.nblocks ) );
     369       20820 :         test();
     370       20820 :         IF( EQ_16( all_coherence_zero, 0 ) && GE_16( sub( sub( sub( hQMetaData->metadata_max_bits, bits_no_dirs_coh ), idiv1616( imult1616( 43, no_TF ), 10 ) ), sum16_fx( bits_diff, ndirections ) ), MASA_MIN_BITS_SURR_COH ) )
     371             :         {
     372        4580 :             bits_surround_coh = encode_surround_coherence_fx( hQMetaData, hMetaData );
     373             :         }
     374             :         ELSE
     375             :         {
     376       16240 :             bits_surround_coh = 0;
     377       16240 :             move16();
     378      211120 :             FOR( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ )
     379             :             {
     380      194880 :                 IF( hQMetaData->surcoh_band_data != NULL )
     381             :                 {
     382           0 :                     set8_fx( (Word8 *) hQMetaData->surcoh_band_data[i].surround_coherence, 0, hQMetaData->q_direction[0].cfg.nblocks );
     383             :                 }
     384             :             }
     385             :         }
     386       20820 :         bits_no_dirs_coh = add( bits_no_dirs_coh, bits_surround_coh );
     387             :         // 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;
     388             :         Word32 tmp_quo, tmp_mod;
     389       20820 :         iDiv_and_mod_32( imult3216( L_mult0( sub( hQMetaData->metadata_max_bits, bits_no_dirs_coh ), hQMetaData->q_direction[0].cfg.nbands ), hQMetaData->q_direction[0].cfg.nblocks ), no_TF, &tmp_quo, &tmp_mod, 0 );
     390       20820 :         total_bits_1dir = extract_l( tmp_quo );
     391             :     }
     392             :     ELSE
     393             :     {
     394      182137 :         no_TF = imult1616( hQMetaData->q_direction[0].cfg.nbands, hQMetaData->q_direction[0].cfg.nblocks );
     395      182137 :         test();
     396      182137 :         IF( EQ_16( all_coherence_zero, 0 ) && GE_16( sub( sub( sub( hQMetaData->metadata_max_bits, bits_no_dirs_coh ), idiv1616( imult1616( 43, no_TF ), 10 ) ), bits_diff[0] ), MASA_MIN_BITS_SURR_COH ) )
     397             :         {
     398       21939 :             bits_surround_coh = encode_surround_coherence_fx( hQMetaData, hMetaData );
     399             :         }
     400             :         ELSE
     401             :         {
     402      160198 :             bits_surround_coh = 0;
     403      160198 :             move16();
     404      673421 :             FOR( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ )
     405             :             {
     406      513223 :                 IF( hQMetaData->surcoh_band_data != NULL )
     407             :                 {
     408       14934 :                     set8_fx( (Word8 *) hQMetaData->surcoh_band_data[i].surround_coherence, 0, hQMetaData->q_direction[0].cfg.nblocks );
     409             :                 }
     410             :             }
     411             :         }
     412      182137 :         total_bits_1dir = sub( sub( hQMetaData->metadata_max_bits, bits_no_dirs_coh ), bits_surround_coh );
     413             :     }
     414             : 
     415             :     /* Loop over number of directions*/
     416      426734 :     FOR( d = 0; d < ndirections; d++ )
     417             :     {
     418      223777 :         q_direction = &( hQMetaData->q_direction[d] );
     419             : 
     420      223777 :         IF( EQ_16( d, 1 ) )
     421             :         {
     422       20820 :             transform_azimuth_dir2_fx( hQMetaData, dir2_bands );
     423             :         }
     424             : 
     425      223777 :         nbands = q_direction->cfg.nbands;
     426      223777 :         move16();
     427      223777 :         nblocks = q_direction->cfg.nblocks;
     428      223777 :         move16();
     429      223777 :         start_band = q_direction->cfg.start_band;
     430      223777 :         move16();
     431      223777 :         diffuseness_index_max_ec_frame = diffuseness_index_max_ec_frame_pre[0];
     432      223777 :         move16();
     433      223777 :         bits_dir_raw = bits_dir_raw_pre[d];
     434      223777 :         move16();
     435             : 
     436             :         /* This sets bit budget correctly for the second direction */
     437      223777 :         IF( d == 0 )
     438             :         {
     439      202957 :             bits_diff[d] = bits_diff_sum;
     440      202957 :             move16();
     441             :         }
     442             :         ELSE
     443             :         {
     444       20820 :             bits_diff[d] = 0;
     445       20820 :             move16();
     446             :         }
     447             : 
     448      223777 :         bits_signaling[d] = 0;
     449      223777 :         move16();
     450             : 
     451             :         /*Coherence */
     452      223777 :         bits_coherence[d] = 0;
     453      223777 :         move16();
     454      223777 :         bit_pos_start_coh = hMetaData->nb_bits_tot;
     455      223777 :         move16();
     456             : 
     457      223777 :         IF( all_coherence_zero == 0 )
     458             :         {
     459       31263 :             bits_coherence[d] = ivas_qmetadata_quantize_coherence_fx( hQMetaData, d, all_coherence_zero, hMetaData, 0, &indice_coherence, 0 );
     460       31263 :             move16();
     461             :         }
     462             : 
     463      223777 :         test();
     464      223777 :         IF( EQ_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_5_1 ) || EQ_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_7_1 ) )
     465             :         {
     466        9940 :             q_direction->not_in_2D = 0;
     467        9940 :             move16();
     468             :             /* Quantize directions*/
     469        9940 :             quantize_direction_frame2D_fx( q_direction, azimuth_orig, elevation_orig );
     470             :         }
     471             :         ELSE
     472             :         {
     473             :             /* Quantize directions*/
     474      213837 :             quantize_direction_frame_fx( q_direction, azimuth_orig, elevation_orig, 0 );
     475             :         }
     476             : 
     477             :         /* Signalling 2D*/
     478      223777 :         push_next_indice( hMetaData, ( q_direction->not_in_2D > 0 ), 1 ); /*2D flag*/
     479      223777 :         bits_signaling[d] = 1;
     480      223777 :         move16();
     481             : 
     482             :         /* Save state of metadata bitstream buffer after writing energy ratios, number of dirs and save space for coherence*/
     483      223777 :         bit_pos_start = hMetaData->nb_bits_tot;
     484      223777 :         move16();
     485      223777 :         next_ind_start = hMetaData->nb_ind_tot;
     486      223777 :         move16();
     487             : 
     488             :         /* Encode quantized directions with EC frame-wise*/
     489      223777 :         IF( LE_16( add( total_bits_1dir, bits_surround_coh ), hQMetaData->qmetadata_max_bit_req ) )
     490             :         {
     491      156446 :             push_next_indice( hMetaData, 0, 1 ); /*Write 1 bit to signal EC frame-wise (EC1)*/
     492      156446 :             bits_signaling[d] = add( bits_signaling[d], 1 );
     493      156446 :             move16();
     494             :         }
     495             : 
     496      223777 :         next_ind_raw_flag = hMetaData->nb_ind_tot;
     497      223777 :         move16();
     498      223777 :         push_next_indice( hMetaData, 0, 1 ); /* Raw coding flag*/
     499             : 
     500      223777 :         bits_dir_bands[0] = ivas_qmetadata_raw_encode_dir_fx( NULL, q_direction, q_direction->cfg.nbands, q_direction->cfg.start_band );
     501      223777 :         move16();
     502             : 
     503             :         // reduce_bits = hQMetaData->is_masa_ivas_format ? ( total_bits_1dir - ( bits_diff[d] + bits_coherence[d] + bits_signaling[d] ) - 1 ) : MASA_MAX_BITS;
     504      223777 :         IF( hQMetaData->is_masa_ivas_format )
     505             :         {
     506       53400 :             reduce_bits = sub( sub( total_bits_1dir, add( add( bits_diff[d], bits_coherence[d] ), bits_signaling[d] ) ), 1 );
     507             :         }
     508             :         ELSE
     509             :         {
     510      170377 :             reduce_bits = MASA_MAX_BITS;
     511      170377 :             move16();
     512             :         }
     513      223777 :         bits_ec = ivas_qmetadata_entropy_encode_dir_fx( hMetaData, q_direction, diffuseness_index_max_ec_frame, q_direction->cfg.nbands, q_direction->cfg.start_band, bits_dir_bands[0], reduce_bits, 0 );
     514             : 
     515      223777 :         IF( bits_ec < 0 )
     516             :         {
     517      106484 :             hMetaData->ind_list[next_ind_raw_flag].value = 1; /*rewrite flag*/
     518      106484 :             move16();
     519      106484 :             bits_ec = ivas_qmetadata_raw_encode_dir_fx( hMetaData, q_direction, q_direction->cfg.nbands, q_direction->cfg.start_band );
     520             :         }
     521      223777 :         bits_dir[d] = add( bits_ec, 1 );
     522      223777 :         move16();
     523      223777 :         extra_bits = sub( hQMetaData->metadata_max_bits, sub( hMetaData->nb_bits_tot, bit_pos_0 ) );
     524             : 
     525             :         /* Encode quantized directions with EC band-wise */
     526      223777 :         test();
     527      223777 :         test();
     528      223777 :         IF( LE_16( add( total_bits_1dir, bits_surround_coh ), hQMetaData->qmetadata_max_bit_req ) && GT_16( add( add( add( bits_dir[d], bits_diff[d] ), bits_coherence[d] ), bits_signaling[d] ), total_bits_1dir ) && GT_16( q_direction->cfg.nblocks, 1 ) )
     529             :         {
     530        8024 :             restore_metadata_buffer_fx( hMetaData, next_ind_start, bit_pos_start );
     531             : 
     532             :             /* Write signaling */
     533        8024 :             push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal no EC frame-wise (EC1)*/
     534        8024 :             push_next_indice( hMetaData, 0, 1 ); /*Write 1 bit to signal EC band-wise (EC2)*/
     535        8024 :             bits_signaling[d] = 3;
     536        8024 :             move16();
     537             : 
     538             :             /* Write raw flags */
     539        8024 :             next_ind_raw_flag = hMetaData->nb_ind_tot;
     540        8024 :             move16();
     541       41307 :             FOR( i = start_band; i < nbands; i++ )
     542             :             {
     543       33283 :                 push_next_indice( hMetaData, 0, 1 ); /* Raw coding flag*/
     544             :             }
     545             : 
     546        8024 :             bits_dir[d] = 0;
     547        8024 :             move16();
     548        8024 :             diff_bits = sub( add( add( bits_diff[d], bits_coherence[d] ), bits_signaling[d] ), total_bits_1dir );
     549       41307 :             FOR( i = start_band; i < nbands; i++ )
     550             :             {
     551       33283 :                 bits_dir_bands[i] = ivas_qmetadata_raw_encode_dir_fx( NULL, q_direction, add( i, 1 ), i );
     552       33283 :                 move16();
     553             : 
     554             :                 /* Write ec bits */
     555       33283 :                 bits_ec = ivas_qmetadata_entropy_encode_dir_fx( hMetaData, q_direction, diffuseness_index_max_ec_frame, add( i, 1 ), i, bits_dir_bands[i], MASA_MAX_BITS, 0 );
     556             : 
     557       33283 :                 IF( bits_ec >= 0 )
     558             :                 {
     559       17766 :                     bits_dir_bands[i] = bits_ec;
     560       17766 :                     move16();
     561       17766 :                     raw_flag[i] = 0;
     562       17766 :                     move16();
     563             :                 }
     564             :                 ELSE
     565             :                 {
     566       15517 :                     raw_flag[i] = 1;
     567       15517 :                     move16();
     568             :                 }
     569       33283 :                 diff_bits = add( diff_bits, add( bits_dir_bands[i], 1 ) );
     570             :             }
     571             : 
     572        8024 :             small_requantize_direction_frame_fx( q_direction, azimuth_orig, elevation_orig, raw_flag, bits_dir_bands, &diff_bits );
     573             : 
     574       41307 :             FOR( i = start_band; i < nbands; i++ )
     575             :             {
     576       33283 :                 IF( raw_flag[i] )
     577             :                 {
     578             :                     /* Rewrite raw flag value */
     579       15517 :                     hMetaData->ind_list[next_ind_raw_flag + i - start_band].value = 1;
     580       15517 :                     move16();
     581             : 
     582             :                     /* Write ec bits */
     583       15517 :                     bits_ec = ivas_qmetadata_raw_encode_dir_fx( hMetaData, q_direction, add( i, 1 ), i );
     584             :                 }
     585       33283 :                 bits_dir[d] = add( bits_dir[d], add( bits_dir_bands[i], 1 ) );
     586       33283 :                 move16();
     587             :             }
     588             : 
     589        8024 :             extra_bits = sub( hQMetaData->metadata_max_bits, sub( hMetaData->nb_bits_tot, bit_pos_0 ) );
     590             :         }
     591             : 
     592             :         /* Requantized directions */
     593      223777 :         test();
     594      223777 :         IF( LE_16( add( total_bits_1dir, bits_surround_coh ), hQMetaData->qmetadata_max_bit_req ) && GT_16( add( add( add( bits_dir[d], bits_diff[d] ), bits_coherence[d] ), bits_signaling[d] ), total_bits_1dir ) )
     595             :         {
     596             : 
     597             :             /*Bit budget exceeded, bit reduction strategy?*/
     598        9338 :             extra_bits = 0;
     599        9338 :             move16();
     600             : 
     601        9338 :             restore_metadata_buffer_fx( hMetaData, next_ind_start, bit_pos_start );
     602             : 
     603        9338 :             push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal no EC frame-wise (EC1)*/
     604        9338 :             IF( GT_16( nblocks, 1 ) )
     605             :             {
     606        5619 :                 push_next_indice( hMetaData, 1, 1 ); /*Write 1 bit to signal requantization stage (EC3)*/
     607        5619 :                 bits_signaling[d] = 3;
     608        5619 :                 move16();
     609             :             }
     610             :             ELSE
     611             :             {
     612        3719 :                 bits_signaling[d] = 2;
     613        3719 :                 move16();
     614             :             }
     615             : 
     616        9338 :             IF( hQMetaData->is_masa_ivas_format == 0 )
     617             :             {
     618        3136 :                 reduce_bits = sub( bits_dir_raw, sub( sub( sub( total_bits_1dir, bits_diff[d] ), bits_coherence[d] ), bits_signaling[d] ) );
     619        3136 :                 ind_order[0] = -1;
     620        3136 :                 move16();
     621             :             }
     622             :             ELSE
     623             :             {
     624        6202 :                 ind_order[0] = 0;
     625        6202 :                 move16();
     626        6202 :                 reduce_bits = s_min( add( imult1616( nbands, nblocks ), MASA_BIT_REDUCT_PARAM ), sub( bits_dir_raw, sub( sub( sub( total_bits_1dir, bits_diff[d] ), bits_coherence[d] ), bits_signaling[d] ) ) );
     627             : 
     628        6202 :                 IF( GT_16( reduce_bits, sub( bits_dir_raw, imult1616( nbands, nblocks ) ) ) )
     629             :                 {
     630         150 :                     reduce_bits = sub( bits_dir_raw, imult1616( nbands, nblocks ) );
     631             :                 }
     632             :             }
     633             : 
     634        9338 :             only_reduce_bits_direction_fx( &extra_bits, q_direction, reduce_bits, nbands, nblocks, ind_order );
     635        9338 :             bits_dir[d] = hMetaData->nb_bits_tot;
     636        9338 :             move16();
     637             : 
     638        9338 :             requantize_direction_EC_3_fx( &extra_bits, q_direction, nbands, hMetaData, elevation_orig, azimuth_orig, ind_order );
     639        9338 :             bits_dir[d] = sub( hMetaData->nb_bits_tot, bits_dir[d] );
     640        9338 :             move16();
     641             :         }
     642             : 
     643             :         /* finalize writing coherence */
     644      223777 :         test();
     645      223777 :         test();
     646      223777 :         IF( ( bits_coherence[d] > 0 ) && ( all_coherence_zero == 0 ) && GT_16( nblocks, 1 ) )
     647             :         {
     648       23095 :             bit_pos_start = hMetaData->nb_bits_tot;
     649       23095 :             hMetaData->nb_bits_tot = bit_pos_start_coh;
     650       23095 :             ivas_qmetadata_quantize_coherence_fx( hQMetaData, d, all_coherence_zero, hMetaData, 1, &indice_coherence, 0 );
     651       23095 :             hMetaData->nb_bits_tot = bit_pos_start;
     652       23095 :             move16();
     653       23095 :             move16();
     654       23095 :             move16();
     655             :         }
     656             : 
     657      223777 :         IF( d == 0 )
     658             :         {
     659      202957 :             total_bits_1dir = sub( hQMetaData->metadata_max_bits, sub( hMetaData->nb_bits_tot, bit_pos_0 ) );
     660             :         }
     661             : 
     662             :         /* Save quantized DOAs */
     663     1335070 :         FOR( i = start_band; i < nbands; i++ )
     664             :         {
     665     1111293 :             Copy32( q_direction->band_data[i].azimuth_fx, q_direction->band_data[i].q_azimuth_fx, nblocks );
     666     1111293 :             Copy32( q_direction->band_data[i].elevation_fx, q_direction->band_data[i].q_elevation_fx, nblocks );
     667             :         }
     668             : 
     669             :         /* Copy original DOAs back to q_direction*/
     670     1335070 :         FOR( i = start_band; i < nbands; i++ )
     671             :         {
     672     1111293 :             Copy32( azimuth_orig[i], q_direction->band_data[i].azimuth_fx, nblocks );
     673     1111293 :             Copy32( elevation_orig[i], q_direction->band_data[i].elevation_fx, nblocks );
     674             :         }
     675             :     }
     676             : 
     677      202957 :     return error;
     678             : }
     679             : 
     680             : 
     681             : /*-----------------------------------------------------------------------*
     682             :  * ivas_qmetadata_enc_encode_hr_384_512()
     683             :  *
     684             :  * Main function for quantizing and coding Spatial Metadata at HRs
     685             :  *-----------------------------------------------------------------------*/
     686        2276 : ivas_error ivas_qmetadata_enc_encode_hr_384_512_fx(
     687             :     BSTR_ENC_HANDLE hMetaData,  /* i/o: metadata bitstream handle */
     688             :     IVAS_QMETADATA *hQMetaData, /* i/o: metadata handle           */
     689             :     const Word16 bits_sph_idx,
     690             :     const Word16 bits_sp_coh )
     691             : {
     692             :     Word16 i, j;
     693             :     Word16 bits_diff[QMETADATA_MAX_NO_DIRECTIONS];
     694             :     IVAS_QDIRECTION *q_direction;
     695             :     Word16 nbands, nblocks, start_band;
     696             :     Word16 ndirections, d;
     697             :     Word16 all_coherence_zero;
     698             :     Word16 bits_ec;
     699             :     Word32 azimuth_orig_fx[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], elevation_orig_fx[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; // Q22
     700             :     ivas_error error;
     701             : 
     702        2276 :     error = IVAS_ERR_OK;
     703        2276 :     move32();
     704             : 
     705             : 
     706        2276 :     ndirections = hQMetaData->no_directions;
     707        2276 :     move16();
     708             : 
     709             :     /* Check if coherence should be encoded */
     710        2276 :     all_coherence_zero = 1;
     711        2276 :     move16();
     712        2276 :     IF( hQMetaData->q_direction->cfg.inactiveBands > 0 )
     713             :     {
     714         300 :         push_next_indice( hMetaData, 1, 1 );
     715             :         /* write the number of inactive higher bands */
     716         300 :         ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( hQMetaData->q_direction->cfg.inactiveBands, 1 ), MASA_MAXIMUM_CODING_SUBBANDS, 1 );
     717             :     }
     718             :     ELSE
     719             :     {
     720             :         /* no change */
     721        1976 :         push_next_indice( hMetaData, 0, 1 );
     722             :     }
     723        2276 :     IF( hQMetaData->coherence_flag )
     724             :     {
     725        2276 :         all_coherence_zero = hQMetaData->all_coherence_zero;
     726        2276 :         move16();
     727        2276 :         push_next_indice( hMetaData, all_coherence_zero, 1 ); /* signal coherence */
     728             :     }
     729             : 
     730             :     /* encode 2 direction subbands position */
     731        2276 :     test();
     732        2276 :     IF( EQ_16( ndirections, 2 ) && EQ_16( bits_sph_idx, 11 ) )
     733             :     {
     734         876 :         write_2dir_info( hMetaData, hQMetaData->twoDirBands, hQMetaData->q_direction[0].cfg.nbands, hQMetaData->numTwoDirBands );
     735         876 :         d = 0;
     736         876 :         move16();
     737       21600 :         FOR( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ )
     738             :         {
     739       20724 :             IF( EQ_16( hQMetaData->twoDirBands[i], 1 ) )
     740             :             {
     741        8334 :                 Copy32( hQMetaData->q_direction[1].band_data[i].azimuth_fx, hQMetaData->q_direction[1].band_data[d].azimuth_fx, hQMetaData->q_direction[1].cfg.nblocks );           // Q22
     742        8334 :                 Copy32( hQMetaData->q_direction[1].band_data[i].elevation_fx, hQMetaData->q_direction[1].band_data[d].elevation_fx, hQMetaData->q_direction[1].cfg.nblocks );       // Q22
     743        8334 :                 Copy32( hQMetaData->q_direction[1].band_data[i].energy_ratio_fx, hQMetaData->q_direction[1].band_data[d].energy_ratio_fx, hQMetaData->q_direction[1].cfg.nblocks ); // Q30
     744             : 
     745        8334 :                 IF( hQMetaData->coherence_flag )
     746             :                 {
     747        8334 :                     mvc2c( hQMetaData->q_direction[1].coherence_band_data[i].spread_coherence, hQMetaData->q_direction[1].coherence_band_data[d].spread_coherence, hQMetaData->q_direction[1].cfg.nblocks );
     748             :                 }
     749        8334 :                 d = add( d, 1 );
     750             :             }
     751             :         }
     752       13266 :         FOR( i = hQMetaData->numTwoDirBands; i < hQMetaData->q_direction[0].cfg.nbands; i++ )
     753             :         {
     754       12390 :             set32_fx( hQMetaData->q_direction[1].band_data[i].energy_ratio_fx, 0, hQMetaData->q_direction[1].cfg.nblocks );
     755             :         }
     756             : 
     757         876 :         hQMetaData->q_direction[1].cfg.nbands = hQMetaData->numTwoDirBands;
     758         876 :         move16();
     759             :     }
     760             : 
     761             :     /*Quantization and encoding of the Diffuseness */
     762        2276 :     ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512_fx( hQMetaData, bits_diff, bits_sph_idx, hMetaData );
     763             : 
     764             : 
     765             :     /* Encode surround coherence */
     766        2276 :     IF( all_coherence_zero == 0 )
     767             :     {
     768        2276 :         encode_surround_coherence_hr_fx( hQMetaData, hMetaData );
     769             :     }
     770             :     ELSE
     771             :     {
     772           0 :         FOR( i = 0; i < hQMetaData->q_direction[0].cfg.nbands; i++ )
     773             :         {
     774           0 :             IF( hQMetaData->surcoh_band_data != NULL )
     775             :             {
     776           0 :                 set8_fx( (Word8 *) hQMetaData->surcoh_band_data[i].surround_coherence, 0, hQMetaData->q_direction[0].cfg.nblocks );
     777             :             }
     778             :         }
     779             :     }
     780             : 
     781             :     /* Loop over number of directions*/
     782        5808 :     FOR( d = 0; d < ndirections; d++ )
     783             :     {
     784        3532 :         q_direction = &( hQMetaData->q_direction[d] );
     785             : 
     786        3532 :         nbands = q_direction->cfg.nbands;
     787        3532 :         nblocks = q_direction->cfg.nblocks;
     788        3532 :         start_band = q_direction->cfg.start_band;
     789        3532 :         move16();
     790        3532 :         move16();
     791        3532 :         move16();
     792             : 
     793        3532 :         q_direction->not_in_2D = 0;
     794        3532 :         move16();
     795             : 
     796             :         /*Coherence */
     797        3532 :         IF( all_coherence_zero == 0 )
     798             :         {
     799        3532 :             ivas_qmetadata_quantize_coherence_hr_512_fx( hQMetaData, d, all_coherence_zero, hMetaData, bits_sp_coh );
     800             :         }
     801             : 
     802             :         /* write the  spherical indexes */
     803        3532 :         bits_ec = hMetaData->nb_bits_tot;
     804        3532 :         move16();
     805             : 
     806        3532 :         IF( EQ_16( bits_sph_idx, 11 ) )
     807             :         {
     808             :             /* do the quantization */
     809        2352 :             quantize_direction_frame_fx( q_direction, azimuth_orig_fx, elevation_orig_fx, 1 );
     810             :         }
     811             : 
     812       75310 :         FOR( i = start_band; i < nbands; i++ )
     813             :         {
     814      343140 :             FOR( j = 0; j < nblocks; j++ )
     815             :             {
     816      271362 :                 push_next_indice( hMetaData, q_direction->band_data[i].spherical_index[j], bits_sph_idx );
     817             :             }
     818             :         }
     819        3532 :         bits_ec = sub( hMetaData->nb_bits_tot, bits_ec );
     820             : 
     821             : 
     822             :         /* Save quantized DOAs */
     823        3532 :         IF( EQ_16( bits_sph_idx, 11 ) )
     824             :         {
     825       45810 :             FOR( i = start_band; i < nbands; i++ )
     826             :             {
     827       43458 :                 Copy32( azimuth_orig_fx[i], q_direction->band_data[i].azimuth_fx, nblocks );     // Q22
     828       43458 :                 Copy32( elevation_orig_fx[i], q_direction->band_data[i].elevation_fx, nblocks ); // Q22
     829             :             }
     830             :         }
     831             :         ELSE
     832             :         {
     833       29500 :             FOR( i = start_band; i < nbands; i++ )
     834             :             {
     835       28320 :                 Copy32( q_direction->band_data[i].azimuth_fx, q_direction->band_data[i].q_azimuth_fx, nblocks );     // Q22
     836       28320 :                 Copy32( q_direction->band_data[i].elevation_fx, q_direction->band_data[i].q_elevation_fx, nblocks ); // Q22
     837             :             }
     838             :         }
     839             :     }
     840             : 
     841        2276 :     IF( hQMetaData->q_direction->cfg.inactiveBands > 0 )
     842             :     {
     843         300 :         hQMetaData->q_direction[0].cfg.nbands = add( hQMetaData->q_direction[0].cfg.nbands, hQMetaData->q_direction->cfg.inactiveBands );
     844         300 :         move16();
     845         300 :         IF( GT_16( ndirections, 1 ) )
     846             :         {
     847         300 :             hQMetaData->q_direction[1].cfg.nbands = add( hQMetaData->q_direction[1].cfg.nbands, hQMetaData->q_direction->cfg.inactiveBands );
     848         300 :             move16();
     849             :         }
     850             :     }
     851             : 
     852        2276 :     return error;
     853             : }
     854             : 
     855             : 
     856             : /*-----------------------------------------------------------------------*
     857             :  * ivas_qmetadata_enc_sid_encode()
     858             :  *
     859             :  * Main function for coding SID for Spatial Metadata
     860             :  *-----------------------------------------------------------------------*/
     861             : 
     862             : /*! r: number of bits written */
     863       10391 : void ivas_qmetadata_enc_sid_encode_fx(
     864             :     BSTR_ENC_HANDLE hMetaData,        /* i/o: metadata bitstream handle                 */
     865             :     IVAS_QMETADATA *q_metadata,       /* i/o: metadata handle                           */
     866             :     const Word16 masa_sid_descriptor, /* i  : description of MASA SID coding structure  */
     867             :     const Word16 ivas_format          /* i  : IVAS format                               */
     868             : )
     869             : {
     870             :     Word16 b, m;
     871             :     Word16 bit_pos_start;
     872             :     IVAS_QDIRECTION *q_direction;
     873             :     Word16 nbands, nblocks, start_band;
     874             :     Word32 avg_direction_vector_fx[3];
     875             :     Word32 avg_elevation_fx[MASA_MAXIMUM_CODING_SUBBANDS];
     876             :     Word32 direction_vector_fx[3];
     877             :     Word32 avg_azimuth_fx[MASA_MAXIMUM_CODING_SUBBANDS];
     878             :     Word16 bits_dir, bits_diff, bits_delta;
     879             :     Word16 metadata_sid_bits; /* bits allocated to SID for metadata */
     880             : 
     881       10391 :     IF( EQ_16( ivas_format, SBA_FORMAT ) )
     882             :     {
     883        3363 :         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*/
     884        3363 :         move16();
     885             :     }
     886             :     ELSE
     887             :     {
     888        7028 :         metadata_sid_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS;
     889        7028 :         move16();
     890             :     }
     891             : 
     892             : 
     893             :     /* Save initial position in bitstream */
     894       10391 :     bit_pos_start = hMetaData->nb_bits_tot;
     895       10391 :     move16();
     896             : 
     897             :     /* write for MASA the number of transport channels used at coding and the CPE mode DFT/MDCT */
     898       10391 :     IF( GT_16( masa_sid_descriptor, negate( 1 ) ) )
     899             :     {
     900        4016 :         push_next_indice( hMetaData, masa_sid_descriptor, 1 );
     901             :     }
     902             : 
     903             :     /* Code for one direction: diffuseness and average DOA(s)*/
     904       10391 :     q_direction = &( q_metadata->q_direction[0] );
     905       10391 :     nbands = q_direction->cfg.nbands;
     906       10391 :     nblocks = q_direction->cfg.nblocks;
     907       10391 :     move16();
     908       10391 :     move16();
     909       10391 :     start_band = 0; /*Start always with band 0 for SID*/
     910       10391 :     move16();
     911             : 
     912             :     /* sanity checks*/
     913       10391 :     assert( q_metadata->no_directions == 1 && "Qmetadata SID: only one direction supported!" );
     914       10391 :     IF( EQ_16( ivas_format, SBA_FORMAT ) )
     915             :     {
     916        3363 :         assert( ( q_direction->cfg.nbands == DIRAC_DTX_BANDS ) && "Qmetadata SID: only 2 bands supported!" );
     917             :     }
     918             :     ELSE
     919             :     {
     920        7028 :         assert( ( q_direction->cfg.nbands == 5 ) && "Qmetadata SID: only 5 bands supported!" );
     921             :     }
     922             : 
     923       10391 :     IF( NE_16( ivas_format, SBA_FORMAT ) )
     924             :     {
     925             :         /* Signalling 2D*/
     926        7028 :         push_next_indice( hMetaData, ( q_direction->not_in_2D > 0 ), 1 ); /*2D flag*/
     927             :     }
     928             :     ELSE
     929             :     {
     930        3363 :         q_direction->not_in_2D = 1; /* force for merged modes */
     931        3363 :         move16();
     932             :     }
     933             : 
     934             :     /*Encode the quantized diffuseness in raw coding*/
     935       10391 :     bits_dir = 0;
     936       10391 :     bits_diff = 0;
     937       10391 :     move16();
     938       10391 :     move16();
     939       10391 :     IF( NE_16( ivas_format, SBA_FORMAT ) )
     940             :     {
     941       42168 :         FOR( b = start_band; b < nbands; b++ )
     942             :         {
     943       35140 :             q_direction->band_data[b].energy_ratio_index[0] = s_max( q_direction->band_data[b].energy_ratio_index[0], 4 );
     944       35140 :             move16();
     945       35140 :             bits_diff = add( bits_diff, ivas_qmetadata_encode_quasi_uniform_length_fx( sub( q_direction->band_data[b].energy_ratio_index[0], 4 ), DIRAC_DIFFUSE_LEVELS - 4 ) );
     946       35140 :             q_direction->band_data[b].bits_sph_idx[0] = bits_direction_masa[q_direction->band_data[b].energy_ratio_index[0]];
     947       35140 :             move16();
     948             : 
     949       35140 :             IF( q_direction->not_in_2D == 0 )
     950             :             {
     951         625 :                 q_direction->band_data[b].azimuth_m_alphabet[0] = 1 << ( s_min( 8, q_direction->band_data[b].bits_sph_idx[0] ) );
     952         625 :                 move16();
     953         625 :                 bits_dir = add( bits_dir, ivas_qmetadata_encode_quasi_uniform_length_fx( sub( q_direction->band_data[b].azimuth_m_alphabet[0], 1 ), q_direction->band_data[b].azimuth_m_alphabet[0] ) );
     954             :             }
     955             :             ELSE
     956             :             {
     957       34515 :                 bits_dir = add( bits_dir, q_direction->band_data[b].bits_sph_idx[0] );
     958             :             }
     959             :         }
     960             : 
     961             :         /* Reduce bit demand by increasing diffuseness*/
     962        7028 :         bits_delta = sub( sub( sub( metadata_sid_bits, sub( hMetaData->nb_bits_tot, bit_pos_start ) ), bits_diff ), bits_dir );
     963        7028 :         IF( bits_delta > 0 )
     964             :         {
     965       32504 :             WHILE( bits_delta > 0 )
     966             :             {
     967       25476 :                 test();
     968      139244 :                 FOR( b = start_band; b < nbands && ( bits_delta > 0 ); b++ )
     969             :                 {
     970      113768 :                     test();
     971      113768 :                     IF( LT_16( q_direction->band_data[b].bits_sph_idx[0], 11 ) )
     972             :                     {
     973      113766 :                         bits_delta = sub( bits_delta, 1 );
     974      113766 :                         q_direction->band_data[b].bits_sph_idx[0] = add( q_direction->band_data[b].bits_sph_idx[0], 1 );
     975      113766 :                         move16();
     976             :                     }
     977             :                 }
     978             :             }
     979             : 
     980        7028 :             IF( q_direction->not_in_2D == 0 )
     981             :             {
     982         750 :                 FOR( b = start_band; b < nbands; b++ )
     983             :                 {
     984         625 :                     q_direction->band_data[b].azimuth_m_alphabet[0] = shl( 1, ( s_min( 8, q_direction->band_data[b].bits_sph_idx[0] ) ) );
     985         625 :                     move16();
     986             :                 }
     987             :             }
     988             :         }
     989             :         ELSE
     990             :         {
     991           0 :             WHILE( bits_delta < 0 )
     992             :             {
     993           0 :                 test();
     994           0 :                 FOR( b = nbands - 1; b >= start_band && ( bits_delta < 0 ); b-- )
     995             :                 {
     996           0 :                     test();
     997           0 :                     IF( GE_16( q_direction->band_data[b].bits_sph_idx[0], 4 ) )
     998             :                     {
     999           0 :                         bits_delta = add( bits_delta, 1 );
    1000           0 :                         q_direction->band_data[b].bits_sph_idx[0] = sub( q_direction->band_data[b].bits_sph_idx[0], 1 );
    1001           0 :                         IF( q_direction->not_in_2D == 0 )
    1002             :                         {
    1003           0 :                             q_direction->band_data[b].azimuth_m_alphabet[0] = shl( 1, ( s_min( 8, q_direction->band_data[b].bits_sph_idx[0] ) ) );
    1004           0 :                             move16();
    1005             :                         }
    1006             :                     }
    1007             :                 }
    1008             :             }
    1009             :         }
    1010             :     }
    1011             :     ELSE
    1012             :     {
    1013       10089 :         FOR( b = start_band; b < nbands; b++ )
    1014             :         {
    1015        6726 :             q_direction->band_data[b].energy_ratio_index[0] = s_max( q_direction->band_data[b].energy_ratio_index[0], 4 );
    1016        6726 :             bits_diff = add( bits_diff, ivas_qmetadata_encode_quasi_uniform_length_fx( sub( q_direction->band_data[b].energy_ratio_index[0], 4 ), DIRAC_DIFFUSE_LEVELS - 4 ) );
    1017        6726 :             q_direction->band_data[b].bits_sph_idx[0] = bits_direction_masa[q_direction->band_data[b].energy_ratio_index[0]];
    1018        6726 :             move16();
    1019        6726 :             move16();
    1020             : 
    1021        6726 :             IF( q_direction->not_in_2D == 0 )
    1022             :             {
    1023           0 :                 q_direction->band_data[b].azimuth_m_alphabet[0] = shl( 1, ( s_min( 5, q_direction->band_data[b].bits_sph_idx[0] ) ) );
    1024           0 :                 move16();
    1025           0 :                 bits_dir = add( bits_dir, ivas_qmetadata_encode_quasi_uniform_length_fx( sub( q_direction->band_data[b].azimuth_m_alphabet[0], 1 ), q_direction->band_data[b].azimuth_m_alphabet[0] ) );
    1026             :             }
    1027             :             ELSE
    1028             :             {
    1029        6726 :                 bits_dir = add( bits_dir, q_direction->band_data[b].bits_sph_idx[0] );
    1030             :             }
    1031             :         }
    1032             : 
    1033             :         /* Reduce bit demand by increasing diffuseness*/
    1034        3363 :         bits_delta = sub( sub( sub( metadata_sid_bits, sub( hMetaData->nb_bits_tot, bit_pos_start ) ), bits_diff ), bits_dir );
    1035             : 
    1036        3363 :         test();
    1037        3367 :         WHILE( bits_delta < 0 && ( q_direction->not_in_2D > 0 ) )
    1038             :         {
    1039           4 :             test();
    1040           4 :             test();
    1041          10 :             FOR( b = nbands - 1; b >= start_band && ( bits_delta < 0 ); b-- )
    1042             :             {
    1043           6 :                 test();
    1044           6 :                 IF( LT_16( q_direction->band_data[b].energy_ratio_index[0], ( DIRAC_DIFFUSE_LEVELS - 1 ) ) )
    1045             :                 {
    1046           6 :                     bits_delta = add( bits_delta, q_direction->band_data[b].bits_sph_idx[0] );
    1047           6 :                     q_direction->band_data[b].energy_ratio_index[0] = add( q_direction->band_data[b].energy_ratio_index[0], 1 );
    1048           6 :                     move16();
    1049           6 :                     q_direction->band_data[b].bits_sph_idx[0] = bits_direction_masa[q_direction->band_data[b].energy_ratio_index[0]];
    1050           6 :                     move16();
    1051           6 :                     bits_delta = sub( bits_delta, q_direction->band_data[b].bits_sph_idx[0] );
    1052             :                 }
    1053             :             }
    1054             :         }
    1055             :     }
    1056       10391 :     assert( ( bits_delta >= 0 ) && "Bit budget in Qmetadata SID is violated!!!" );
    1057             : 
    1058             :     /*Code diffuseness*/
    1059       52257 :     FOR( b = start_band; b < nbands; b++ )
    1060             :     {
    1061       41866 :         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, sub( q_direction->band_data[b].energy_ratio_index[0], 4 ), DIRAC_DIFFUSE_LEVELS - 4 );
    1062             :     }
    1063             : 
    1064             :     /* Compute and Quantize an average direction per band*/
    1065       52257 :     FOR( b = start_band; b < nbands; b++ )
    1066             :     {
    1067       41866 :         set32_fx( avg_direction_vector_fx, 0, 3 );
    1068      133541 :         FOR( m = 0; m < nblocks; m++ )
    1069             :         {
    1070             :             /*compute the average direction */
    1071       91675 :             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 );
    1072       91675 :             scale_sig32( direction_vector_fx, 3, Q22 - Q30 ); // Q30 -> Q22
    1073             : #ifdef VEC_ARITH_OPT_v1
    1074       91675 :             v_add_fixed_no_hdrm( avg_direction_vector_fx, direction_vector_fx, avg_direction_vector_fx, 3 ); // Q22
    1075             : #else                                                                                                        /* VEC_ARITH_OPT_v1 */
    1076             :             v_add_fixed( avg_direction_vector_fx, direction_vector_fx, avg_direction_vector_fx, 3, 0 ); // Q22
    1077             : #endif                                                                                                       /* VEC_ARITH_OPT_v1 */
    1078             :         }
    1079             : 
    1080       41866 :         ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector_fx, Q22, &avg_azimuth_fx[b], &avg_elevation_fx[b] );
    1081             : 
    1082             :         /* Quantize the average direction */
    1083       41866 :         IF( q_direction->not_in_2D == 0 )
    1084             :         {
    1085        1250 :             q_direction->band_data[b].spherical_index[0] = quantize_direction2D_fx( avg_azimuth_fx[b], q_direction->band_data[b].azimuth_m_alphabet[0], &avg_azimuth_fx[b],
    1086         625 :                                                                                     &q_direction->band_data[b].azimuth_index[0], q_direction->cfg.mc_ls_setup );
    1087         625 :             move16();
    1088             :         }
    1089             :         ELSE
    1090             :         {
    1091       82482 :             q_direction->band_data[b].spherical_index[0] = quantize_direction_fx( avg_elevation_fx[b], avg_azimuth_fx[b], q_direction->band_data[b].bits_sph_idx[0], &avg_elevation_fx[b], &avg_azimuth_fx[b],
    1092       41241 :                                                                                   &q_direction->band_data[b].elevation_index[0], &q_direction->band_data[b].azimuth_index[0], q_direction->cfg.mc_ls_setup );
    1093       41241 :             move16();
    1094             :         }
    1095             : 
    1096             :         /* Save quantized DOAs */
    1097       41866 :         q_direction->band_data[b].q_azimuth_fx[0] = avg_azimuth_fx[b];
    1098       41866 :         q_direction->band_data[b].q_elevation_fx[0] = avg_elevation_fx[b];
    1099       41866 :         move32();
    1100       41866 :         move32();
    1101             : 
    1102       41866 :         IF( EQ_16( q_direction->band_data[b].azimuth_index[0], MASA_NO_INDEX ) )
    1103             :         {
    1104         125 :             q_direction->band_data[b].azimuth_index[0] = 0;
    1105         125 :             move16();
    1106             :         }
    1107             :     }
    1108             : 
    1109             :     /* quantize average elevation and azimuth angles */
    1110       10391 :     IF( q_direction->not_in_2D > 0 )
    1111             :     {
    1112       51507 :         FOR( b = start_band; b < nbands; b++ )
    1113             :         {
    1114       41241 :             push_next_indice( hMetaData, q_direction->band_data[b].spherical_index[0], q_direction->band_data[b].bits_sph_idx[0] );
    1115             :         }
    1116             :     }
    1117             :     ELSE
    1118             :     {
    1119         750 :         FOR( b = start_band; b < nbands; b++ )
    1120             :         {
    1121         625 :             ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, q_direction->band_data[b].azimuth_index[0], q_direction->band_data[b].azimuth_m_alphabet[0] );
    1122             :         }
    1123             :     }
    1124             : 
    1125             : 
    1126             :     /* fill bits*/
    1127       10391 :     assert( ( hMetaData->nb_bits_tot - bit_pos_start ) <= metadata_sid_bits && "Too many written bits!" );
    1128       26849 :     WHILE( ( ( ( hMetaData->nb_bits_tot - bit_pos_start ) ) < metadata_sid_bits ) )
    1129             :     {
    1130       16458 :         push_next_indice( hMetaData, 0, 1 ); /*fill bit*/
    1131             :     }
    1132             : 
    1133       10391 :     return;
    1134             : }
    1135             : 
    1136             : 
    1137             : /*-------------------------------------------------------------------------
    1138             :  * reset_metadata_spatial()
    1139             :  *
    1140             :  * Reset metadata in spatial formats
    1141             :  *------------------------------------------------------------------------*/
    1142       81539 : void reset_metadata_spatial_fx(
    1143             :     const IVAS_FORMAT ivas_format, /* i  : IVAS format                  */
    1144             :     BSTR_ENC_HANDLE hMetaData,     /* i/o: metadata bitstream handle    */
    1145             :     const Word32 element_brate,    /* i  : element bitrate              */
    1146             :     Word32 *total_brate,           /* o  : total bitrate                */
    1147             :     const Word32 core_brate,       /* i  : core bitrate                 */
    1148             :     const Word16 nb_bits_metadata  /* i  : number of meatdata bits      */
    1149             : )
    1150             : {
    1151             :     Word16 i, next_ind_sid, last_ind_sid;
    1152             :     Word16 j;
    1153             :     Word16 metadata_sid_bits;
    1154             : 
    1155       81539 :     test();
    1156       81539 :     IF( EQ_32( core_brate, SID_2k40 ) || core_brate == FRAME_NO_DATA )
    1157             :     {
    1158        3932 :         test();
    1159        3932 :         test();
    1160        3932 :         IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, MASA_FORMAT ) ) && core_brate != FRAME_NO_DATA )
    1161             :         {
    1162         541 :             IF( EQ_32( ivas_format, SBA_FORMAT ) )
    1163             :             {
    1164         350 :                 hMetaData->ind_list[0].value = 1;
    1165         350 :                 move16();
    1166         350 :                 metadata_sid_bits = (Word16) ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS;
    1167         350 :                 move16();
    1168             : 
    1169         700 :                 WHILE( ( hMetaData->nb_bits_tot < metadata_sid_bits ) )
    1170             :                 {
    1171         350 :                     push_next_indice( hMetaData, 0, 1 ); /*fill bit*/
    1172             :                 }
    1173             :             }
    1174             :             ELSE
    1175             :             {
    1176             :                 /* Reset metadata and keep only SID metadata*/
    1177         191 :                 last_ind_sid = hMetaData->nb_ind_tot;
    1178         191 :                 next_ind_sid = hMetaData->nb_ind_tot;
    1179         191 :                 move16();
    1180         191 :                 move16();
    1181        2366 :                 WHILE( ( hMetaData->nb_bits_tot > nb_bits_metadata ) )
    1182             :                 {
    1183        2175 :                     next_ind_sid = sub( next_ind_sid, 1 );
    1184        2175 :                     hMetaData->nb_bits_tot = sub( hMetaData->nb_bits_tot, hMetaData->ind_list[next_ind_sid].nb_bits );
    1185        2175 :                     move16();
    1186             :                 }
    1187             : 
    1188         191 :                 hMetaData->nb_bits_tot = 0;
    1189         191 :                 move16();
    1190             : 
    1191        3964 :                 FOR( i = 0; i < next_ind_sid; i++ )
    1192             :                 {
    1193        3773 :                     hMetaData->ind_list[i].nb_bits = -1;
    1194        3773 :                     move16();
    1195             :                 }
    1196             : 
    1197        2366 :                 FOR( ( j = 0, i = next_ind_sid ); i < last_ind_sid; ( i++, j++ ) )
    1198             :                 {
    1199        2175 :                     hMetaData->ind_list[j].value = hMetaData->ind_list[i].value;
    1200        2175 :                     hMetaData->ind_list[j].nb_bits = hMetaData->ind_list[i].nb_bits;
    1201        2175 :                     hMetaData->nb_bits_tot = add( hMetaData->nb_bits_tot, hMetaData->ind_list[j].nb_bits );
    1202        2175 :                     hMetaData->ind_list[i].nb_bits = -1;
    1203        2175 :                     move16();
    1204        2175 :                     move16();
    1205        2175 :                     move16();
    1206        2175 :                     move16();
    1207             :                 }
    1208             : 
    1209         191 :                 hMetaData->nb_ind_tot = j;
    1210         191 :                 move16();
    1211             :             }
    1212             :         }
    1213             :         ELSE
    1214             :         {
    1215             :             /*Reset metadata*/
    1216        3391 :             reset_indices_enc_fx( hMetaData, hMetaData->nb_ind_tot );
    1217             :         }
    1218             : 
    1219        3932 :         *total_brate = element_brate;
    1220        3932 :         move32();
    1221             :     }
    1222       77607 :     ELSE IF( NE_32( ivas_format, SBA_FORMAT ) )
    1223             :     {
    1224             :         /* Reset SID metadata bits*/
    1225      101935 :         WHILE( ( hMetaData->nb_bits_tot > nb_bits_metadata ) )
    1226             :         {
    1227       65708 :             hMetaData->nb_ind_tot = sub( hMetaData->nb_ind_tot, 1 );
    1228       65708 :             hMetaData->nb_bits_tot = sub( hMetaData->nb_bits_tot, hMetaData->ind_list[hMetaData->nb_ind_tot].nb_bits );
    1229       65708 :             hMetaData->ind_list[hMetaData->nb_ind_tot].nb_bits = -1;
    1230       65708 :             move16();
    1231       65708 :             move16();
    1232       65708 :             move16();
    1233             :         }
    1234             :     }
    1235             : 
    1236       81539 :     return;
    1237             : }
    1238             : 
    1239             : 
    1240             : /*-------------------------------------------------------------------------
    1241             :  * quantize_direction2D()
    1242             :  *
    1243             :  *
    1244             :  *------------------------------------------------------------------------*/
    1245             : /*! r: quantized spherical index */
    1246       85849 : Word16 quantize_direction2D_fx(
    1247             :     Word32 phi,                 /* i  : input azimuth value            Q22 */
    1248             :     const Word16 no_cw,         /* i  : number of bits                  */
    1249             :     Word32 *phi_q,              /* o  : quantized azimuth value        Q22 */
    1250             :     UWord16 *index_phi,         /* o  : quantized azimuth index         */
    1251             :     const MC_LS_SETUP mc_format /* i  : channel format if in MC-mode    */
    1252             : )
    1253             : {
    1254             :     Word16 idx_sph;
    1255             :     UWord16 id_phi;
    1256       85849 :     IF( LT_16( no_cw, 2 ) )
    1257             :     {
    1258           0 :         *phi_q = 0;
    1259           0 :         move32();
    1260             : 
    1261           0 :         return 0;
    1262             :     }
    1263             : 
    1264       85849 :     IF( NE_32( mc_format, MC_LS_SETUP_INVALID ) )
    1265             :     {
    1266       83843 :         id_phi = quantize_phi_chan_compand_fx( L_add( phi, DEGREE_180_Q_22 ), phi_q, no_cw, 0, mc_format );
    1267             :     }
    1268             :     ELSE
    1269             :     {
    1270        2006 :         id_phi = quantize_phi_enc_fx( L_add( phi, DEGREE_180_Q_22 ), 0, phi_q, no_cw );
    1271             :     }
    1272       85849 :     *phi_q = L_sub( *phi_q, DEGREE_180_Q_22 );
    1273       85849 :     move32();
    1274             : 
    1275       85849 :     *index_phi = ivas_qmetadata_reorder_generic_fx( sub( id_phi, shr( no_cw, 1 ) ) );
    1276       85849 :     move16();
    1277             : 
    1278       85849 :     idx_sph = id_phi;
    1279       85849 :     move16();
    1280             : 
    1281       85849 :     return idx_sph;
    1282             : }
    1283             : 
    1284        2276 : static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_hr_512_fx(
    1285             :     IVAS_QMETADATA_HANDLE hQMetaData,
    1286             :     Word16 *needed_bits,
    1287             :     const Word16 bits_dir_hr,
    1288             :     BSTR_ENC_HANDLE hMetaData )
    1289             : {
    1290             :     Word16 j, k;
    1291             :     Word16 index;
    1292             : 
    1293        2276 :     needed_bits[0] = 0;
    1294        2276 :     needed_bits[1] = 0;
    1295        2276 :     move16();
    1296        2276 :     move16();
    1297             : 
    1298       56600 :     FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j )
    1299             :     {
    1300      261270 :         FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ )
    1301             :         {
    1302      206946 :             index = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] ), diffuseness_thresholds_hr_fx, HR_MASA_ER_LEVELS );
    1303             : 
    1304      206946 :             push_next_indice( hMetaData, index, MASA_BITS_ER_HR );
    1305      206946 :             hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index;
    1306      206946 :             hQMetaData->q_direction[0].band_data[j].energy_ratio_index_mod[k] = index;
    1307      206946 :             hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = W_extract_h( W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[index] ) ); // Q30
    1308      206946 :             needed_bits[0] = add( needed_bits[0], MASA_BITS_ER_HR );
    1309      206946 :             hQMetaData->q_direction[0].band_data[j].bits_sph_idx[k] = bits_dir_hr;
    1310      206946 :             move16();
    1311      206946 :             move16();
    1312      206946 :             move32();
    1313      206946 :             move16();
    1314      206946 :             move16();
    1315             :         }
    1316             :     }
    1317             : 
    1318        2276 :     IF( EQ_16( hQMetaData->no_directions, 2 ) )
    1319             :     {
    1320             :         Word32 ratioSum;
    1321             :         Word16 div_e;
    1322        1256 :         IF( EQ_16( bits_dir_hr, 16 ) )
    1323             :         {
    1324        9500 :             FOR( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; j++ )
    1325             :             {
    1326       45600 :                 FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ )
    1327             :                 {
    1328       36480 :                     index = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ), diffuseness_thresholds_hr_fx, HR_MASA_ER_LEVELS );
    1329             : 
    1330       36480 :                     push_next_indice( hMetaData, index, MASA_BITS_ER_HR );
    1331       36480 :                     hQMetaData->q_direction[1].band_data[j].energy_ratio_index[k] = index;
    1332       36480 :                     move16();
    1333       36480 :                     hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = W_extract_h( W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[index] ) );
    1334       36480 :                     move32();
    1335             : 
    1336       36480 :                     ratioSum = L_add( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] );
    1337       36480 :                     IF( GT_32( ratioSum, ONE_IN_Q30 /*1.0f*/ ) )
    1338             :                     {
    1339        1294 :                         hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_newton( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], ratioSum, &div_e );
    1340        1294 :                         hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k], sub( div_e, 1 ) );
    1341        1294 :                         move32();
    1342        1294 :                         move32();
    1343             : 
    1344        1294 :                         hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_newton( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], ratioSum, &div_e );
    1345        1294 :                         hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], sub( div_e, 1 ) );
    1346        1294 :                         move32();
    1347        1294 :                         move32();
    1348             :                     }
    1349             : 
    1350       36480 :                     needed_bits[1] = add( needed_bits[1], MASA_BITS_ER_HR );
    1351       36480 :                     move16();
    1352       36480 :                     hQMetaData->q_direction[1].band_data[j].bits_sph_idx[k] = bits_dir_hr;
    1353       36480 :                     move16();
    1354             :                 }
    1355             :             }
    1356             :         }
    1357             :         ELSE
    1358             :         {
    1359             :             Word16 pos_2dir_band[MASA_MAXIMUM_CODING_SUBBANDS];
    1360         876 :             k = 0;
    1361         876 :             move16();
    1362       21600 :             FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; j++ )
    1363             :             {
    1364       20724 :                 IF( EQ_16( hQMetaData->twoDirBands[j], 1 ) )
    1365             :                 {
    1366        8334 :                     pos_2dir_band[k] = j;
    1367        8334 :                     move16();
    1368        8334 :                     k = add( k, 1 );
    1369             :                 }
    1370             :                 ELSE
    1371             :                 {
    1372       12390 :                     pos_2dir_band[k] = 0;
    1373       12390 :                     move16();
    1374             :                 }
    1375             :             }
    1376        9210 :             FOR( j = hQMetaData->q_direction[1].cfg.start_band; j < hQMetaData->q_direction[1].cfg.nbands; j++ )
    1377             :             {
    1378       36270 :                 FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ )
    1379             :                 {
    1380       27936 :                     index = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ), diffuseness_thresholds_hr_fx, HR_MASA_ER_LEVELS );
    1381             : 
    1382       27936 :                     push_next_indice( hMetaData, index, MASA_BITS_ER_HR );
    1383       27936 :                     hQMetaData->q_direction[1].band_data[j].energy_ratio_index[k] = index;
    1384       27936 :                     move16();
    1385       27936 :                     hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = W_extract_h( W_sub( ONE_IN_Q62, diffuseness_reconstructions_hr_fx[index] ) ); // Q30
    1386       27936 :                     move32();
    1387             : 
    1388       27936 :                     ratioSum = L_add( hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k], hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] ); // Q30
    1389             : 
    1390       27936 :                     IF( GT_32( ratioSum, ONE_IN_Q30 /*1.0f*/ ) )
    1391             :                     {
    1392         326 :                         hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_newton( hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k], ratioSum, &div_e );
    1393         326 :                         hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[0].band_data[pos_2dir_band[j]].energy_ratio_fx[k], sub( div_e, 1 ) );
    1394         326 :                         move32();
    1395         326 :                         move32();
    1396             : 
    1397         326 :                         hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = BASOP_Util_Divide3232_Scale_newton( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], ratioSum, &div_e );
    1398         326 :                         hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k] = L_shl( hQMetaData->q_direction[1].band_data[j].energy_ratio_fx[k], sub( div_e, 1 ) );
    1399         326 :                         move32();
    1400         326 :                         move32();
    1401             :                     }
    1402             : 
    1403       27936 :                     needed_bits[1] = add( needed_bits[1], MASA_BITS_ER_HR );
    1404       27936 :                     move16();
    1405       27936 :                     hQMetaData->q_direction[1].band_data[j].bits_sph_idx[k] = bits_dir_hr;
    1406       27936 :                     move16();
    1407             :                 }
    1408             :             }
    1409             :         }
    1410             :     }
    1411             : 
    1412        2276 :     return;
    1413             : }
    1414             : 
    1415             : 
    1416             : /*-------------------------------------------------------------------------
    1417             :  * ivas_qmetadata_quantize_diffuseness_nrg_ratios()
    1418             :  *
    1419             :  * Quantize diffuseness
    1420             :  *------------------------------------------------------------------------*/
    1421             : 
    1422      202957 : static void ivas_qmetadata_quantize_diffuseness_nrg_ratios_fx(
    1423             :     IVAS_QMETADATA_HANDLE hQMetaData,
    1424             :     Word16 *needed_bits,
    1425             :     Word16 *nbits_diff,
    1426             :     Word16 *dfRatioBits,
    1427             :     const Word16 hodirac_flag )
    1428             : {
    1429             :     Word16 j, k, dir2band;
    1430             :     Word16 index_dirRatio1Inv, index_dirRatio2Inv, index_dirRatio1Inv_mod, index_dirRatio2Inv_mod;
    1431             :     Word16 index_diff;
    1432             : 
    1433      202957 :     nbits_diff[0] = 0;
    1434      202957 :     nbits_diff[1] = 0;
    1435      202957 :     needed_bits[0] = 0;
    1436      202957 :     needed_bits[1] = 0;
    1437      202957 :     dir2band = 0;
    1438      202957 :     move16();
    1439      202957 :     move16();
    1440      202957 :     move16();
    1441      202957 :     move16();
    1442      202957 :     move16();
    1443             : 
    1444     1106170 :     FOR( j = hQMetaData->q_direction[0].cfg.start_band; j < hQMetaData->q_direction[0].cfg.nbands; ++j )
    1445             :     {
    1446      903213 :         test();
    1447      903213 :         IF( EQ_32( hQMetaData->no_directions, 2 ) && EQ_16( hQMetaData->twoDirBands[j], 1 ) )
    1448      208080 :         {
    1449             :             Word32 diffRatio, dfRatio, dfRatioQ, diffRatioQ, dirRatio1Q, dirRatio2Q; /* Q30 */
    1450             :             Word32 dirRatio1, dirRatio2, sumRatio;                                   /* Q30 */
    1451             :             Word16 dfRatio_index, dfRatio_qsteps, dfRatio_bits;
    1452             : 
    1453             :             /* With 2dir metadata, we quantize and transmit diffuse-to-total ratio (diffRatio) and
    1454             :              * distribution factor of direct-to-total ratios (dFRatio). This is more efficient and
    1455             :              * accurate than simple separate quantization of each direct-to-total ratio or their
    1456             :              * separate inverses. */
    1457      208080 :             IF( hodirac_flag )
    1458             :             {
    1459             :                 /* already encoded as total and ratios in HO-DirAC */
    1460      194880 :                 diffRatio = L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ); // Q30
    1461      194880 :                 dfRatio = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0];                 // Q30
    1462      194880 :                 move32();
    1463             :             }
    1464             :             ELSE
    1465             :             {
    1466       13200 :                 dirRatio1 = hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0]; // Q30
    1467       13200 :                 move32();
    1468       13200 :                 dirRatio2 = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[0]; // Q30
    1469       13200 :                 move32();
    1470       13200 :                 sumRatio = L_add( dirRatio1, dirRatio2 );  // Q30
    1471       13200 :                 diffRatio = L_sub( ONE_IN_Q30, sumRatio ); // Q30
    1472       13200 :                 IF( LT_32( sumRatio, EPSILON_FIX ) )
    1473             :                 {
    1474           0 :                     dfRatio = ONE_IN_Q29 /* 0.5f in Q30*/; // Q30
    1475           0 :                     move32();
    1476             :                 }
    1477             :                 ELSE
    1478             :                 {
    1479             :                     Word16 exp_diff;
    1480       13200 :                     dfRatio = L_deposit_h( BASOP_Util_Divide3232_Scale( dirRatio1, sumRatio, &exp_diff ) );
    1481       13200 :                     dfRatio = L_shl( dfRatio, sub( exp_diff, Q1 ) ); // Q30
    1482             :                 }
    1483             :             }
    1484             : 
    1485             : 
    1486      208080 :             index_diff = masa_sq_fx( diffRatio, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
    1487      208080 :             diffRatioQ = diffuseness_reconstructions_fx[index_diff]; // Q30
    1488      208080 :             move32();
    1489             : 
    1490      208080 :             IF( hodirac_flag )
    1491             :             {
    1492      194880 :                 dfRatio_bits = ivas_get_df_ratio_bits_hodirac_fx( index_diff );
    1493             :             }
    1494             :             ELSE
    1495             :             {
    1496       13200 :                 dfRatio_bits = ivas_get_df_ratio_bits_fx( index_diff );
    1497             :             }
    1498             : 
    1499      208080 :             dfRatioBits[dir2band] = dfRatio_bits;
    1500      208080 :             move16();
    1501             : 
    1502      208080 :             dfRatio_qsteps = shl( 1, dfRatio_bits );
    1503      208080 :             IF( hodirac_flag )
    1504             :             {
    1505             :                 Word16 dfRatioQ16; /* Q14 */
    1506      194880 :                 dfRatio_index = usquant_fx( extract_h( dfRatio ), &dfRatioQ16 /* Q14 */, 0, shr( div_s( 1, sub( dfRatio_qsteps, 1 ) ), 2 ), dfRatio_qsteps );
    1507      194880 :                 dfRatioQ = L_deposit_h( dfRatioQ16 );         // Q30
    1508      194880 :                 dirRatio1Q = L_sub( ONE_IN_Q30, diffRatioQ ); // Q30
    1509      194880 :                 dirRatio2Q = dfRatioQ;                        // Q30
    1510      194880 :                 move32();
    1511             :             }
    1512             :             ELSE
    1513             :             {
    1514             :                 Word16 dfRatioQ16; /* Q14 */
    1515       13200 :                 dfRatio_index = usquant_fx( extract_h( dfRatio ), &dfRatioQ16 /* Q14 */, ONE_IN_Q13 /* 0.5f in Q14 */, shr( div_s( 1, sub( dfRatio_qsteps, 1 ) ), 3 ), dfRatio_qsteps );
    1516             : 
    1517             :                 /* Direction quantization requires also separately quantized direct-to-total ratios. Thus, we calculate them. */
    1518       13200 :                 dirRatio1Q = L_shl( Mpy_32_16_1( L_sub( ONE_IN_Q30, diffRatioQ ), dfRatioQ16 ), 1 ); // Q30
    1519       13200 :                 dirRatio2Q = L_sub( L_sub( ONE_IN_Q30, diffRatioQ ), dirRatio1Q );                   // Q30
    1520             :             }
    1521             : 
    1522      208080 :             index_dirRatio1Inv = masa_sq_fx( L_sub( ONE_IN_Q30, dirRatio1Q ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
    1523             : 
    1524             :             /* Note: To save memory, we store temporarily index_diff and dfRatio_index into first and second direction
    1525             :              * energy ratio index variables until they have been encoded. index_dirRatio1Inv and index_dirRatio2Inv are
    1526             :              * then later retrieved for further use in encoding. */
    1527     1031268 :             FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ )
    1528             :             {
    1529      823188 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index_diff; // Q0
    1530      823188 :                 move16();
    1531      823188 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = dirRatio1Q; // Q30
    1532      823188 :                 move32();
    1533             :             }
    1534      208080 :             nbits_diff[0] = add( nbits_diff[0], MASA_BITS_ER );
    1535      208080 :             move16();
    1536             : 
    1537      208080 :             IF( hodirac_flag )
    1538             :             {
    1539             :                 Word16 tmp; /* Q14 */
    1540      194880 :                 index_dirRatio2Inv = usquant_fx( extract_h( dirRatio2Q ), &tmp /* Q14 */, 0, shr( div_s( 1, sub( DIRAC_DIFFUSE_LEVELS, 1 ) ), 2 ), DIRAC_DIFFUSE_LEVELS );
    1541             :             }
    1542             :             ELSE
    1543             :             {
    1544       13200 :                 index_dirRatio2Inv = masa_sq_fx( L_sub( ONE_IN_Q30, dirRatio2Q ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
    1545             :             }
    1546             : 
    1547     1031268 :             FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ )
    1548             :             {
    1549      823188 :                 hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[k] = dfRatio_index; // Q0
    1550      823188 :                 move16();
    1551      823188 :                 hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_fx[k] = dirRatio2Q; // Q30
    1552      823188 :                 move32();
    1553             :             }
    1554      208080 :             nbits_diff[1] = add( nbits_diff[1], dfRatio_bits );
    1555      208080 :             move16();
    1556             : 
    1557             :             /* Obtain compensated direct-to-total ratios for direction quantization. This compensates for the
    1558             :              * fact that with 2dir data, it is harder to achieve separate high direct-to-total ratio values
    1559             :              * which are assumed by the direction quantization system. In practice, this improves direction
    1560             :              * accuracy when it is perceptual meaningful. */
    1561      208080 :             masa_compensate_two_dir_energy_ratio_index_fx( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag );
    1562             : 
    1563     1031268 :             FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ )
    1564             :             {
    1565      823188 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_index_mod[k] = index_dirRatio1Inv_mod;
    1566      823188 :                 move16();
    1567      823188 :                 hQMetaData->q_direction[0].band_data[j].bits_sph_idx[k] = bits_direction_masa[index_dirRatio1Inv_mod];
    1568      823188 :                 move16();
    1569             :             }
    1570      208080 :             needed_bits[0] = add( needed_bits[0], imult1616( hQMetaData->q_direction[0].cfg.nblocks, bits_direction_masa[index_dirRatio1Inv_mod] ) );
    1571      208080 :             move16();
    1572             : 
    1573     1031268 :             FOR( k = 0; k < hQMetaData->q_direction[1].cfg.nblocks; k++ )
    1574             :             {
    1575      823188 :                 hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index_mod[k] = index_dirRatio2Inv_mod;
    1576      823188 :                 move16();
    1577      823188 :                 hQMetaData->q_direction[1].band_data[dir2band].bits_sph_idx[k] = bits_direction_masa[index_dirRatio2Inv_mod];
    1578      823188 :                 move16();
    1579             :             }
    1580      208080 :             needed_bits[1] = add( needed_bits[1], imult1616( hQMetaData->q_direction[1].cfg.nblocks, bits_direction_masa[index_dirRatio2Inv_mod] ) );
    1581      208080 :             move16();
    1582             : 
    1583      208080 :             dir2band = add( dir2band, 1 );
    1584             :         }
    1585             :         ELSE
    1586             :         {
    1587      695133 :             index_dirRatio1Inv = masa_sq_fx( L_sub( ONE_IN_Q30, hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[0] ), diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
    1588             : 
    1589     2915733 :             FOR( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ )
    1590             :             {
    1591     2220600 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_index[k] = index_dirRatio1Inv;
    1592     2220600 :                 move16();
    1593     2220600 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_index_mod[k] = index_dirRatio1Inv;
    1594     2220600 :                 move16();
    1595     2220600 :                 hQMetaData->q_direction[0].band_data[j].energy_ratio_fx[k] = L_sub( ONE_IN_Q30, diffuseness_reconstructions_fx[index_dirRatio1Inv] ); // Q30
    1596     2220600 :                 move32();
    1597     2220600 :                 hQMetaData->q_direction[0].band_data[j].bits_sph_idx[k] = bits_direction_masa[index_dirRatio1Inv];
    1598     2220600 :                 move16();
    1599             :             }
    1600             : 
    1601      695133 :             nbits_diff[0] = add( nbits_diff[0], MASA_BITS_ER );
    1602      695133 :             move16();
    1603             : 
    1604      695133 :             needed_bits[0] = add( needed_bits[0], imult1616( hQMetaData->q_direction[0].cfg.nblocks, bits_direction_masa[index_dirRatio1Inv] ) );
    1605      695133 :             move16();
    1606             :         }
    1607             :     }
    1608             : 
    1609      202957 :     return;
    1610             : }
    1611             : 
    1612             : 
    1613             : /*-------------------------------------------------------------------------
    1614             :  * ivas_diffuseness_huff_ec_encode()
    1615             :  *
    1616             :  *
    1617             :  *------------------------------------------------------------------------*/
    1618      144052 : static Word16 ivas_diffuseness_huff_ec_encode_fx(
    1619             :     BSTR_ENC_HANDLE hMetaData,
    1620             :     const UWord16 idx )
    1621             : {
    1622             :     Word16 nbits;
    1623      144052 :     nbits = 0;
    1624      144052 :     move16();
    1625      144052 :     IF( LE_16( idx, DIFF_EC_HUFF_GR0_LIMIT ) )
    1626             :     {
    1627      140957 :         IF( idx > 0 )
    1628             :         {
    1629       79097 :             push_next_indice( hMetaData, (UWord16) L_sub( L_shl( 1, idx ), 1 ), idx );
    1630       79097 :             nbits = add( nbits, idx );
    1631             :         }
    1632      140957 :         push_next_indice( hMetaData, 0, 1 );
    1633      140957 :         nbits = add( nbits, 1 );
    1634             :     }
    1635             :     ELSE
    1636             :     {
    1637        3095 :         push_next_indice( hMetaData, 511, DIFF_EC_HUFF_GR0_LIMIT + 1 );
    1638        3095 :         push_next_indice( hMetaData, (UWord16) L_sub( idx, DIFF_EC_HUFF_GR0_LIMIT + 1 ), 2 );
    1639        3095 :         nbits = add( nbits, DIFF_EC_HUFF_GR0_LIMIT + 3 );
    1640             :     }
    1641      144052 :     return nbits;
    1642             : }
    1643             : 
    1644             : /*-------------------------------------------------------------------------
    1645             :  * ivas_diffuseness_huff_ec_prepare()
    1646             :  *
    1647             :  *
    1648             :  *------------------------------------------------------------------------*/
    1649       25294 : static void ivas_diffuseness_huff_ec_prepare_fx(
    1650             :     IVAS_QDIRECTION *q_direction,
    1651             :     Word16 *best_av,
    1652             :     UWord16 *avr_idx,
    1653             :     Word16 *diffuseness_bits_huff )
    1654             : {
    1655             :     Word16 bits;
    1656             :     Word16 av_crt;
    1657             :     Word16 av;
    1658             :     Word16 av_e;
    1659             :     Word16 sh_idx;
    1660             :     UWord16 ui_sh_idx[MASA_MAXIMUM_CODING_SUBBANDS];
    1661             :     Word16 b, start_band, nbands;
    1662             : 
    1663       25294 :     start_band = q_direction->cfg.start_band;
    1664       25294 :     move16();
    1665       25294 :     nbands = q_direction->cfg.nbands;
    1666       25294 :     move16();
    1667             : 
    1668       25294 :     *diffuseness_bits_huff = 0;
    1669       25294 :     move16();
    1670       25294 :     av = 0;
    1671       25294 :     move16();
    1672      344582 :     FOR( b = start_band; b < nbands; b++ )
    1673             :     {
    1674      319288 :         av = add( av, q_direction->band_data[b].energy_ratio_index[0] );
    1675             :     }
    1676             :     // av = (Word16) ( 0.5f + av / (float) nbands );
    1677       25294 :     av = BASOP_Util_Divide1616_Scale( av, nbands, &av_e );
    1678       25294 :     av = shr_r( av, sub( 15, av_e ) ); // Q0
    1679       25294 :     *best_av = av;
    1680       25294 :     move16();
    1681             : 
    1682       25294 :     *diffuseness_bits_huff = MAX16B;
    1683       25294 :     move16();
    1684      101176 :     FOR( av_crt = av - 1; av_crt <= av + 1; av_crt++ )
    1685             :     {
    1686       75882 :         bits = 0;
    1687       75882 :         move16();
    1688     1033746 :         FOR( b = start_band; b < nbands; b++ )
    1689             :         {
    1690      957864 :             sh_idx = sub( q_direction->band_data[b].energy_ratio_index[0], av_crt );
    1691             :             // ui_sh_idx[b] = ( sh_idx <= 0 ) ? ( -2 * sh_idx ) : sh_idx * 2 - 1;
    1692      957864 :             IF( sh_idx <= 0 )
    1693             :             {
    1694      568203 :                 ui_sh_idx[b] = negate( shl( sh_idx, 1 ) );
    1695             :             }
    1696             :             ELSE
    1697             :             {
    1698      389661 :                 ui_sh_idx[b] = sub( shl( sh_idx, 1 ), 1 );
    1699             :             }
    1700      957864 :             move16();
    1701      957864 :             if ( GE_32( ui_sh_idx[b], 2 * DIRAC_DIFFUSE_LEVELS - 3 ) )
    1702             :             {
    1703        3840 :                 bits = 100; /* to avoid difference larger than 6 in absolute value */
    1704        3840 :                 move16();
    1705             :             }
    1706             : 
    1707             :             // bits += ( ui_sh_idx[b] <= DIFF_EC_HUFF_GR0_LIMIT ) ? ( ui_sh_idx[b] + 1 ) : 11;
    1708      957864 :             IF( LE_32( ui_sh_idx[b], DIFF_EC_HUFF_GR0_LIMIT ) )
    1709             :             {
    1710      923595 :                 bits = add( bits, add( ui_sh_idx[b], 1 ) );
    1711             :             }
    1712             :             ELSE
    1713             :             {
    1714       34269 :                 bits = add( bits, 11 );
    1715             :             }
    1716             :         }
    1717             : 
    1718       75882 :         IF( LT_16( bits, *diffuseness_bits_huff ) )
    1719             :         {
    1720       47109 :             *diffuseness_bits_huff = bits;
    1721       47109 :             move16();
    1722       47109 :             Copy( (Word16 *) ui_sh_idx, (Word16 *) avr_idx, nbands );
    1723       47109 :             *best_av = av_crt;
    1724       47109 :             move16();
    1725             :         }
    1726             :     }
    1727             : 
    1728       25294 :     *diffuseness_bits_huff = add( *diffuseness_bits_huff, MASA_BITS_ER ); /* for the average */
    1729       25294 :     move16();
    1730             : 
    1731       25294 :     return;
    1732             : }
    1733             : 
    1734             : /*-------------------------------------------------------------------------
    1735             :  * ivas_qmetadata_entropy_encode_diffuseness()
    1736             :  *
    1737             :  * encode diffuseness
    1738             :  *------------------------------------------------------------------------*/
    1739      202957 : static Word16 ivas_qmetadata_entropy_encode_diffuseness_fx(
    1740             :     BSTR_ENC_HANDLE hMetaData,
    1741             :     IVAS_QDIRECTION *q_direction,
    1742             :     UWord16 *diffuseness_index_max_ec_frame )
    1743             : {
    1744             :     Word16 start_bit_pos;
    1745             :     Word16 diffuseness_bits_raw;
    1746             :     Word16 b;
    1747             :     Word16 min_diffuseness_m_index, max_diffuseness_m_index;
    1748             :     Word16 nbands;
    1749             :     Word16 start_band;
    1750             : 
    1751      202957 :     nbands = q_direction->cfg.nbands;
    1752      202957 :     move16();
    1753      202957 :     start_band = q_direction->cfg.start_band;
    1754      202957 :     move16();
    1755             : 
    1756      202957 :     start_bit_pos = hMetaData->nb_bits_tot;
    1757      202957 :     move16();
    1758             : 
    1759      202957 :     IF( EQ_16( nbands, 1 ) )
    1760             :     {
    1761             :         /* If there is only one band, diffuseness should be coded directly as raw with no signaling. */
    1762        3973 :         push_next_indice( hMetaData, q_direction->band_data[0].energy_ratio_index[0], MASA_BITS_ER );
    1763        3973 :         *diffuseness_index_max_ec_frame = 5;
    1764        3973 :         move16();
    1765        3973 :         return sub( hMetaData->nb_bits_tot, start_bit_pos );
    1766             :     }
    1767             : 
    1768             :     /* compute the number of raw coding bits */
    1769      198984 :     diffuseness_bits_raw = 0;
    1770      198984 :     move16();
    1771     1098224 :     FOR( b = start_band; b < nbands; b++ )
    1772             :     {
    1773      899240 :         diffuseness_bits_raw = add( diffuseness_bits_raw, ivas_qmetadata_encode_quasi_uniform_length_fx( q_direction->band_data[b].energy_ratio_index[0], DIRAC_DIFFUSE_LEVELS ) );
    1774             :     }
    1775             : 
    1776      198984 :     min_diffuseness_m_index = q_direction->band_data[start_band].energy_ratio_index[0];
    1777      198984 :     move16();
    1778      198984 :     max_diffuseness_m_index = q_direction->band_data[start_band].energy_ratio_index[0];
    1779      198984 :     move16();
    1780             : 
    1781     1098224 :     FOR( b = start_band; b < nbands; b++ )
    1782             :     {
    1783      899240 :         if ( LT_16( q_direction->band_data[b].energy_ratio_index[0], min_diffuseness_m_index ) )
    1784             :         {
    1785      118363 :             min_diffuseness_m_index = q_direction->band_data[b].energy_ratio_index[0];
    1786      118363 :             move16();
    1787             :         }
    1788             : 
    1789      899240 :         if ( GT_16( q_direction->band_data[b].energy_ratio_index[0], max_diffuseness_m_index ) )
    1790             :         {
    1791      129862 :             max_diffuseness_m_index = q_direction->band_data[b].energy_ratio_index[0];
    1792      129862 :             move16();
    1793             :         }
    1794             :     }
    1795             : 
    1796      198984 :     IF( LT_16( nbands, DIFF_EC_HUFF_BAND_LIMIT ) )
    1797             :     {
    1798             :         /* Use similarity coding approach or raw coding when there is a low number of bands. */
    1799             :         /* one bit is used to indicate whether diffuseness values are entropy coded or coded raw */
    1800      173690 :         IF( EQ_16( min_diffuseness_m_index, max_diffuseness_m_index ) ) /* all values are equal */
    1801             :         {
    1802       52525 :             push_next_indice( hMetaData, 0, 1 );                                                                /* dif_use_raw_coding */
    1803       52525 :             push_next_indice( hMetaData, 1, 1 );                                                                /* dif_have_unique_value */
    1804       52525 :             ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, min_diffuseness_m_index, DIRAC_DIFFUSE_LEVELS ); /* dif_unique_value */
    1805             :         }
    1806      121165 :         ELSE IF( EQ_16( add( min_diffuseness_m_index, 1 ), max_diffuseness_m_index ) ) /* only two consecutive values are present */
    1807             :         {
    1808       38348 :             push_next_indice( hMetaData, 0, 1 );                                                                    /* dif_use_raw_coding */
    1809       38348 :             push_next_indice( hMetaData, 0, 1 );                                                                    /* dif_have_unique_value */
    1810       38348 :             ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, min_diffuseness_m_index, DIRAC_DIFFUSE_LEVELS - 1 ); /* dif_min_value */
    1811             : 
    1812      167986 :             FOR( b = start_band; b < nbands; b++ )
    1813             :             {
    1814      129638 :                 push_next_indice( hMetaData, sub( q_direction->band_data[b].energy_ratio_index[0], min_diffuseness_m_index ), 1 ); /* dif_bit_offset_values */
    1815             :             }
    1816             :         }
    1817             :         ELSE /* raw coding */
    1818             :         {
    1819       82817 :             push_next_indice( hMetaData, 1, 1 ); /* dif_use_raw_coding */
    1820             : 
    1821      379174 :             FOR( b = start_band; b < nbands; b++ )
    1822             :             {
    1823      296357 :                 ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, q_direction->band_data[b].energy_ratio_index[0], DIRAC_DIFFUSE_LEVELS ); /* dif_values */
    1824             :             }
    1825             :         }
    1826             :     }
    1827             :     ELSE
    1828             :     {
    1829             :         /* Use Huffman-coding approach or raw coding when there is a high number of bands. */
    1830             :         Word16 diffuseness_bits_huff;
    1831             :         Word16 best_av;
    1832             :         UWord16 avr_idx[MASA_MAXIMUM_CODING_SUBBANDS];
    1833             : 
    1834             :         /* First, obtain average indices and bit usage for Huffman-coding. */
    1835       25294 :         ivas_diffuseness_huff_ec_prepare_fx( q_direction, &best_av, avr_idx, &diffuseness_bits_huff );
    1836             : 
    1837             :         /* If there is benefit, use Huffman-coding. Otherwise, use raw coding. */
    1838       25294 :         IF( LT_16( diffuseness_bits_huff, diffuseness_bits_raw ) )
    1839             :         {
    1840             :             /* Signal Huffman EC */
    1841       11241 :             push_next_indice( hMetaData, 0, 1 );
    1842       11241 :             push_next_indice( hMetaData, best_av, MASA_BITS_ER );
    1843      155293 :             FOR( b = start_band; b < nbands; b++ )
    1844             :             {
    1845      144052 :                 ivas_diffuseness_huff_ec_encode_fx( hMetaData, avr_idx[b] );
    1846             :             }
    1847             :         }
    1848             :         ELSE
    1849             :         {
    1850             :             /* Signal raw */
    1851       14053 :             push_next_indice( hMetaData, 1, 1 );
    1852      189289 :             FOR( b = start_band; b < nbands; b++ )
    1853             :             {
    1854      175236 :                 ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, q_direction->band_data[b].energy_ratio_index[0], DIRAC_DIFFUSE_LEVELS ); /* dif_values */
    1855             :             }
    1856             :         }
    1857             :     }
    1858             : 
    1859      198984 :     *diffuseness_index_max_ec_frame = 5;
    1860      198984 :     move16();
    1861             :     /* adaptively select the diffuseness_index_max_ec threshold */
    1862      198984 :     IF( GT_16( min_diffuseness_m_index, 5 ) )
    1863             :     {
    1864       71096 :         *diffuseness_index_max_ec_frame = DIRAC_DIFFUSE_LEVELS - 1;
    1865       71096 :         move16();
    1866             :     }
    1867             : 
    1868             : 
    1869      198984 :     return sub( hMetaData->nb_bits_tot, start_bit_pos );
    1870             : }
    1871             : 
    1872             : /*-------------------------------------------------------------------------
    1873             :  * ivas_qmetadata_entropy_encode_df_ratio()
    1874             :  *
    1875             :  * encode dfRatio
    1876             :  *------------------------------------------------------------------------*/
    1877       20820 : static Word16 ivas_qmetadata_entropy_encode_df_ratio_fx(
    1878             :     BSTR_ENC_HANDLE hMetaData,
    1879             :     IVAS_QDIRECTION *q_direction,
    1880             :     Word16 *df_ratio_bits )
    1881             : {
    1882             :     Word16 start_bit_pos;
    1883             :     Word16 bits_raw;
    1884             :     Word16 b;
    1885             :     Word16 min_index, max_index;
    1886             :     Word16 nbands, start_band;
    1887             :     Word16 max_df_ratio_bits;
    1888       20820 :     Word16 ec_mode = 0;
    1889       20820 :     move16();
    1890             :     Word16 max_alphabet_size;
    1891             : 
    1892       20820 :     nbands = q_direction->cfg.nbands;
    1893       20820 :     move16();
    1894       20820 :     start_band = q_direction->cfg.start_band;
    1895       20820 :     move16();
    1896             : 
    1897       20820 :     start_bit_pos = hMetaData->nb_bits_tot;
    1898       20820 :     move16();
    1899             : 
    1900       20820 :     IF( EQ_16( nbands, 1 ) )
    1901             :     {
    1902             :         /* If there is only one band, ratio should be coded directly as raw with no signaling. */
    1903        1732 :         push_next_indice( hMetaData, q_direction->band_data[0].energy_ratio_index[0], df_ratio_bits[0] );
    1904             : 
    1905        1732 :         return sub( hMetaData->nb_bits_tot, start_bit_pos );
    1906             :     }
    1907             : 
    1908             :     /* compute the number of raw coding bits */
    1909       19088 :     bits_raw = 0;
    1910       19088 :     move16();
    1911       19088 :     max_df_ratio_bits = 0;
    1912       19088 :     move16();
    1913      225436 :     FOR( b = start_band; b < nbands; b++ )
    1914             :     {
    1915      206348 :         bits_raw = add( bits_raw, df_ratio_bits[b] );
    1916      206348 :         max_df_ratio_bits = s_max( df_ratio_bits[b], max_df_ratio_bits );
    1917             :     }
    1918             : 
    1919       19088 :     min_index = q_direction->band_data[start_band].energy_ratio_index[0];
    1920       19088 :     move16();
    1921       19088 :     max_index = q_direction->band_data[start_band].energy_ratio_index[0];
    1922       19088 :     move16();
    1923      225436 :     FOR( b = start_band; b < nbands; b++ )
    1924             :     {
    1925      206348 :         if ( LT_16( q_direction->band_data[b].energy_ratio_index[0], min_index ) )
    1926             :         {
    1927       16386 :             min_index = q_direction->band_data[b].energy_ratio_index[0];
    1928       16386 :             move16();
    1929             :         }
    1930             : 
    1931      206348 :         if ( GT_16( q_direction->band_data[b].energy_ratio_index[0], max_index ) )
    1932             :         {
    1933       23295 :             max_index = q_direction->band_data[b].energy_ratio_index[0];
    1934       23295 :             move16();
    1935             :         }
    1936             :     }
    1937             : 
    1938             :     /* Decide what modes are possible */
    1939       19088 :     IF( GE_16( bits_raw, add( add( max_df_ratio_bits, 2 ), nbands ) ) )
    1940             :     {
    1941       14574 :         ec_mode = 2;
    1942             :     }
    1943        4514 :     ELSE IF( GE_16( bits_raw, add( max_df_ratio_bits, 1 ) ) )
    1944             :     {
    1945        4514 :         ec_mode = 1;
    1946             :     }
    1947             :     ELSE
    1948             :     {
    1949           0 :         ec_mode = 0;
    1950             :     }
    1951       19088 :     move16();
    1952       19088 :     max_alphabet_size = shl( 1, max_df_ratio_bits );
    1953             : 
    1954       19088 :     test();
    1955       19088 :     test();
    1956       19088 :     IF( EQ_16( min_index, max_index ) && ec_mode > 0 ) /* all values are equal */
    1957             :     {
    1958         344 :         push_next_indice( hMetaData, 0, 1 ); /* Signal between EC and raw */
    1959         344 :         IF( GT_16( ec_mode, 1 ) )
    1960             :         {
    1961             :             /* Only use bit for signaling if necessary */
    1962         101 :             push_next_indice( hMetaData, 0, 1 ); /* Signal between one value or bandwise diff mode */
    1963             :         }
    1964             : 
    1965         344 :         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, min_index, max_alphabet_size );
    1966             :     }
    1967       18744 :     ELSE IF( EQ_16( add( min_index, 1 ), max_index ) && GT_16( ec_mode, 1 ) ) /* only two consecutive values are present */
    1968             :     {
    1969        1181 :         push_next_indice( hMetaData, 0, 1 );
    1970        1181 :         push_next_indice( hMetaData, 1, 1 );
    1971        1181 :         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, min_index, sub( max_alphabet_size, 1 ) );
    1972             : 
    1973       12132 :         FOR( b = start_band; b < nbands; b++ )
    1974             :         {
    1975       10951 :             push_next_indice( hMetaData, sub( q_direction->band_data[b].energy_ratio_index[0], min_index ), 1 ); /* Band-wise offset values */
    1976             :         }
    1977             :     }
    1978             :     ELSE /* raw coding */
    1979             :     {
    1980       17563 :         IF( ec_mode > 0 )
    1981             :         {
    1982       17563 :             push_next_indice( hMetaData, 1, 1 ); /* Only signal raw mode if not implicitly using it */
    1983             :         }
    1984             : 
    1985      211668 :         FOR( b = start_band; b < nbands; b++ )
    1986             :         {
    1987      194105 :             ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, q_direction->band_data[b].energy_ratio_index[0], shl( 1, df_ratio_bits[b] ) ); /* dif_values */
    1988             :         }
    1989             :     }
    1990             : 
    1991       19088 :     return sub( hMetaData->nb_bits_tot, start_bit_pos );
    1992             : }
    1993             : 
    1994             : /*-------------------------------------------------------------------------
    1995             :  * restore_metadata_buffer()
    1996             :  *
    1997             :  * Restore metadata buffer
    1998             :  *------------------------------------------------------------------------*/
    1999      248691 : void restore_metadata_buffer_fx(
    2000             :     BSTR_ENC_HANDLE hMetaData,
    2001             :     const Word16 next_ind_start,
    2002             :     const Word16 bit_pos_start )
    2003             : {
    2004             :     Word16 i;
    2005             : 
    2006    11198879 :     FOR( i = next_ind_start; i < hMetaData->nb_ind_tot; i++ )
    2007             :     {
    2008    10950188 :         hMetaData->ind_list[i].nb_bits = -1;
    2009    10950188 :         move16();
    2010             :     }
    2011      248691 :     hMetaData->nb_bits_tot = bit_pos_start;
    2012      248691 :     move16();
    2013      248691 :     hMetaData->nb_ind_tot = next_ind_start;
    2014      248691 :     move16();
    2015             : 
    2016      248691 :     return;
    2017             : }
    2018             : 
    2019             : /*-------------------------------------------------------------------------
    2020             :  * ivas_qmetadata_encode_quasi_uniform_fx()
    2021             :  *
    2022             :  * encode value using a quasi-uniform code of b or b + 1 bits, where b = floor(log2(alphabet_size))
    2023             :  *------------------------------------------------------------------------*/
    2024     1895061 : static void ivas_qmetadata_encode_quasi_uniform_fx(
    2025             :     BSTR_ENC_HANDLE hMetaData,
    2026             :     const UWord16 value,
    2027             :     const UWord16 alphabet_size )
    2028             : {
    2029             :     Word16 bits;
    2030             :     UWord16 tresh;
    2031             : 
    2032     1895061 :     bits = sub( 30, norm_l( alphabet_size ) ); /* bits = floor(log2(alphabet_size)) */
    2033     1895061 :     tresh = (UWord16) L_sub( L_shl( 1U, add( bits, 1 ) ), alphabet_size );
    2034             : 
    2035     1895061 :     IF( LT_32( value, tresh ) )
    2036             :     {
    2037     1581694 :         push_next_indice( hMetaData, value, bits );
    2038             :     }
    2039             :     ELSE /* value >= tresh */
    2040             :     {
    2041      313367 :         push_next_indice( hMetaData, (UWord16) L_add( value, tresh ), add( bits, 1 ) );
    2042             :     }
    2043             : 
    2044     1895061 :     return;
    2045             : }
    2046             : 
    2047             : 
    2048             : /*-----------------------------------------------------------------------*
    2049             :  * GR encoder function definitions
    2050             :  *-----------------------------------------------------------------------*/
    2051             : /*-------------------------------------------------------------------------
    2052             :  * GR_bits_new_fx()
    2053             :  *
    2054             :  *
    2055             :  *------------------------------------------------------------------------*/
    2056             : /*! r: number of bits using Golomb Rice code */
    2057      135554 : static Word16 GR_bits_new_fx(
    2058             :     UWord16 *data,                 /* i  : data to encode with GR              */
    2059             :     Word16 *no_symb,               /* i  : number of symbols for each component*/
    2060             :     const Word16 no_data,          /* i  : number of input data                */
    2061             :     const Word16 GR_order,         /* i  : GR order to be used                 */
    2062             :     const Word16 check_two_orders, /* i  : check also coding with GR_order-1   */
    2063             :     Word16 *real_GR_ord            /* o  : the GR order that has been used     */
    2064             : )
    2065             : {
    2066      135554 :     Word16 nbits = 0, i;
    2067      135554 :     Word16 nbits1 = 0;
    2068             :     Word16 nb;
    2069      135554 :     move16();
    2070      135554 :     move16();
    2071             : 
    2072     1183094 :     FOR( i = 0; i < no_data; i++ )
    2073             :     {
    2074     1047540 :         nb = ivas_qmetadata_encode_extended_gr_length_fx( data[i], no_symb[i], GR_order );
    2075     1047540 :         nbits = add( nbits, nb );
    2076             :     }
    2077             : 
    2078      135554 :     IF( EQ_16( check_two_orders, 1 ) )
    2079             :     {
    2080     1012277 :         FOR( i = 0; i < no_data; i++ )
    2081             :         {
    2082      899818 :             nb = ivas_qmetadata_encode_extended_gr_length_fx( data[i], no_symb[i], GR_order - 1 );
    2083      899818 :             nbits1 = add( nbits1, nb );
    2084             :         }
    2085             : 
    2086      112459 :         IF( nbits1 < nbits )
    2087             :         {
    2088       69777 :             nbits = add( nbits1, 1 );
    2089       69777 :             *real_GR_ord = sub( GR_order, 1 );
    2090       69777 :             move16();
    2091             :         }
    2092             :         ELSE
    2093             :         {
    2094       42682 :             nbits = add( nbits, 1 );
    2095       42682 :             *real_GR_ord = GR_order;
    2096       42682 :             move16();
    2097             :         }
    2098             :     }
    2099             :     ELSE
    2100             :     {
    2101       23095 :         *real_GR_ord = GR_order;
    2102       23095 :         move16();
    2103             :     }
    2104             : 
    2105      135554 :     return nbits;
    2106             : }
    2107             : 
    2108             : 
    2109             : /*-------------------------------------------------------------------------
    2110             :  * GR_bits_azimuth_context()
    2111             :  *
    2112             :  * Encoding azimuth indexes with GR code using context
    2113             :  *------------------------------------------------------------------------*/
    2114             : /*! r: numer of bits used for coding */
    2115       18841 : static Word16 GR_bits_azimuth_context_fx(
    2116             :     UWord16 *data_in,        /* i  : data to be encoded                                Qx*/
    2117             :     Word16 *no_symb,         /* i  : number of symbols for each component              */
    2118             :     const Word16 no_data_in, /* i  : number of input data                              */
    2119             :     const Word16 GR_order,   /* i  : GR order (GR_order or GR_order-1 are used )       */
    2120             :     const UWord16 *bits_dir, /* i  : bits for encoding the direction for each TF tile  */
    2121             :     Word16 *real_GR_ord,     /* o  : which GR order has been used                  Q0    */
    2122             :     Word16 *p_use_context    /* o  : flag telling if context has been used or not  Q0   */
    2123             : )
    2124             : {
    2125             :     Word16 i, nbits, nbits1, use_context;
    2126             :     UWord16 cdata[MAX_PARAM_SPATIAL_SUBFRAMES];
    2127             :     UWord16 data[MAX_PARAM_SPATIAL_SUBFRAMES];
    2128             :     Word16 min_val, max_val;
    2129             :     Word16 real_GR_ord1;
    2130             :     Word16 no_symb_local[MAX_PARAM_SPATIAL_SUBFRAMES];
    2131       18841 :     Word16 no_data = 0;
    2132       18841 :     move16();
    2133       75527 :     FOR( i = 0; i < no_data_in; i++ )
    2134             :     {
    2135       56686 :         IF( LT_32( data_in[i], MASA_NO_INDEX ) )
    2136             :         {
    2137       56673 :             no_symb_local[no_data] = no_symb[i];
    2138       56673 :             move16();
    2139       56673 :             data[no_data++] = data_in[i]; // Qx
    2140       56673 :             move16();
    2141             :         }
    2142             :     }
    2143             : 
    2144       18841 :     IF( no_data == 0 )
    2145             :     {
    2146           6 :         *p_use_context = -3; /* corresponding to nothing to be written */
    2147           6 :         move16();
    2148           6 :         return 0;
    2149             :     }
    2150             : 
    2151       18835 :     nbits = 0;
    2152       18835 :     move16();
    2153       18835 :     use_context = 0;
    2154       18835 :     move16();
    2155       75508 :     FOR( i = 0; i < no_data; i++ )
    2156             :     {
    2157       56673 :         IF( LE_16( bits_dir[i], 1 ) )
    2158             :         {
    2159           0 :             nbits = add( nbits, bits_dir[i] );
    2160           0 :             use_context = 1;
    2161           0 :             move16();
    2162             :         }
    2163             :         ELSE
    2164             :         {
    2165       56673 :             *real_GR_ord = sub( GR_order, (Word16) EQ_16( bits_dir[i], 2 ) );
    2166       56673 :             move16();
    2167       56673 :             nbits = add( nbits, ivas_qmetadata_encode_extended_gr_length_fx( data[i], no_symb_local[i], *real_GR_ord ) );
    2168             :         }
    2169             :     }
    2170             : 
    2171       18835 :     real_GR_ord1 = 0;
    2172       18835 :     move16();
    2173       18835 :     IF( use_context == 0 )
    2174             :     {
    2175       18835 :         nbits = GR_bits_new_fx( data, no_symb_local, no_data, GR_order, 1, real_GR_ord );
    2176       18835 :         nbits1 = nbits;
    2177       18835 :         move16();
    2178       18835 :         min_val = data[0]; // Qx
    2179       18835 :         move16();
    2180       56673 :         FOR( i = 1; i < no_data; i++ )
    2181             :         {
    2182       37838 :             if ( LT_32( data[i], min_val ) )
    2183             :             {
    2184        5320 :                 min_val = data[i]; // Qx
    2185        5320 :                 move16();
    2186             :             }
    2187             :         }
    2188       75508 :         FOR( i = 0; i < no_data; i++ )
    2189             :         {
    2190       56673 :             cdata[i] = (UWord16) L_sub( data[i], min_val ); // Qx
    2191       56673 :             move16();
    2192             :         }
    2193             : 
    2194       18835 :         maximum_s( no_symb_local, no_data, &max_val );
    2195       18835 :         nbits1 = add( GR_bits_new_fx( cdata, no_symb_local, no_data, sub( GR_order, 1 ), 1, &real_GR_ord1 ), ivas_qmetadata_encode_extended_gr_length_fx( min_val, max_val, MASA_GR_ORD_AZ ) );
    2196             : 
    2197       18835 :         IF( LT_16( nbits1, nbits ) )
    2198             :         {
    2199        6533 :             nbits = add( nbits1, 1 );
    2200        6533 :             use_context = -2;
    2201        6533 :             move16();
    2202        6533 :             *real_GR_ord = real_GR_ord1;
    2203        6533 :             move16();
    2204             :         }
    2205             :         ELSE
    2206             :         {
    2207       12302 :             nbits = add( nbits, 1 );
    2208       12302 :             use_context = -1;
    2209       12302 :             move16();
    2210             :         }
    2211             :     }
    2212             : 
    2213       18835 :     *p_use_context = use_context;
    2214       18835 :     move16();
    2215       18835 :     return nbits;
    2216             : }
    2217             : 
    2218             : /*-------------------------------------------------------------------------
    2219             :  * mean_removed_GR_new()
    2220             :  *
    2221             :  * Golomb Rice encoding with mean removing
    2222             :  *------------------------------------------------------------------------*/
    2223             : /*! r: number of bits used */
    2224       36323 : static Word16 mean_removed_GR_new_fx(
    2225             :     const UWord16 *idx, /* i  : data to encode */
    2226             :     const Word16 max_no_symb,
    2227             :     const Word16 len,      /* i  : number of data                                      */
    2228             :     const Word16 adapt_GR, /* i  : flag for telling to use or nor two GR order values  */
    2229             :     Word16 *GR_ord,        /* i/o: GR order                                            */
    2230             :     UWord16 *p_av,         /* o  : average index                                       */
    2231             :     UWord16 *mr_idx        /* o  : mean removed indexes                                */
    2232             : )
    2233             : {
    2234             :     Word16 av, i, nbits;
    2235             :     Word16 sh_idx[MASA_MAXIMUM_CODING_SUBBANDS];
    2236             :     Word16 max_ns[MASA_MAXIMUM_CODING_SUBBANDS];
    2237             : 
    2238             :     /* av = (Word16) ( 0.5f + sum_s( (const Word16 *) idx, len ) / (float) len ); */
    2239       36323 :     av = shr( add( 1, idiv1616U( shl( sum16_fx( (const Word16 *) idx, len ), 1 ), len ) ), 1 ); // Q0
    2240             : 
    2241       36323 :     *p_av = av;
    2242       36323 :     move16();
    2243      455407 :     FOR( i = 0; i < len; i++ )
    2244             :     {
    2245      419084 :         max_ns[i] = shl( max_no_symb, 1 );
    2246      419084 :         sh_idx[i] = sub( idx[i], av );
    2247      419084 :         move16();
    2248      419084 :         move16();
    2249             :     }
    2250             : 
    2251      455407 :     FOR( i = 0; i < len; i++ )
    2252             :     {
    2253      419084 :         IF( sh_idx[i] < 0 )
    2254             :         {
    2255       51221 :             sh_idx[i] = imult1616( -2, sh_idx[i] );
    2256             :         }
    2257      367863 :         ELSE IF( sh_idx[i] > 0 )
    2258             :         {
    2259       49652 :             sh_idx[i] = sub( shl( sh_idx[i], 1 ), 1 );
    2260       49652 :             move16();
    2261             :         }
    2262             :         ELSE
    2263             :         {
    2264      318211 :             sh_idx[i] = 0;
    2265      318211 :             move16();
    2266             :         }
    2267      419084 :         mr_idx[i] = (UWord16) sh_idx[i];
    2268      419084 :         move16();
    2269             :     }
    2270             : 
    2271       36323 :     nbits = GR_bits_new_fx( mr_idx, max_ns, len, *GR_ord, adapt_GR, GR_ord );
    2272             : 
    2273       36323 :     return nbits;
    2274             : }
    2275             : 
    2276             : /*-------------------------------------------------------------------------
    2277             :  * ivas_qmetadata_encode_quasi_uniform_length_fx()
    2278             :  *
    2279             :  *------------------------------------------------------------------------*/
    2280     8689190 : static Word16 ivas_qmetadata_encode_quasi_uniform_length_fx(
    2281             :     const UWord16 value,
    2282             :     const UWord16 alphabet_size )
    2283             : {
    2284             :     Word16 bits;
    2285             :     UWord16 tresh;
    2286             : 
    2287     8689190 :     bits = sub( 30, norm_l( alphabet_size ) ); /* bits = floor(log2(alphabet_size)) */
    2288     8689190 :     tresh = (UWord16) L_sub( L_shl( 1U, add( bits, 1 ) ), alphabet_size );
    2289             : 
    2290     8689190 :     IF( GE_32( value, tresh ) )
    2291             :     {
    2292     2280955 :         bits = add( bits, 1 );
    2293             :     }
    2294             : 
    2295     8689190 :     return bits;
    2296             : }
    2297             : 
    2298             : /*-------------------------------------------------------------------------
    2299             :  * ivas_qmetadata_entropy_encode_dir()
    2300             :  *
    2301             :  * Main function for entropy coding of the directions
    2302             :  *------------------------------------------------------------------------*/
    2303             : 
    2304      257060 : static Word16 ivas_qmetadata_entropy_encode_dir_fx(
    2305             :     BSTR_ENC_HANDLE hMetaData,
    2306             :     IVAS_QDIRECTION *q_direction,
    2307             :     const UWord16 diffuseness_index_max_ec_frame,
    2308             :     const Word16 nbands,
    2309             :     const Word16 start_band,
    2310             :     const Word16 direction_bits_raw,
    2311             :     Word16 max_bits,
    2312             :     const Word16 hrmasa_flag )
    2313             : {
    2314             :     UWord16 diff_idx_min;
    2315             :     Word16 i, j;
    2316             :     Word16 nblocks;
    2317             : 
    2318             :     Word32 avg_direction_vector[3], direction_vector[3], avg_azimuth, avg_elevation;
    2319             :     Word16 avg_azimuth_alphabet, avg_elevation_alphabet;
    2320             :     UWord16 avg_azimuth_index, avg_elevation_index;
    2321             :     Word16 avg_elevation_index_projected;
    2322             :     Word16 avg_azimuth_index_projected;
    2323             :     UWord16 avg_elevation_index_initial, avg_elevation_offset;
    2324             :     UWord16 avg_azimuth_index_initial, avg_azimuth_offset;
    2325             :     Word16 elevation_bits_ec_best, azimuth_bits_ec_best;
    2326             : 
    2327      257060 :     Word16 gr_param_elevation_best = 0, avg_elevation_index_best = 0;
    2328      257060 :     move16();
    2329      257060 :     move16();
    2330             :     UWord16 dist_elevation_indexes_best[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    2331             :     Word16 gr_param_azimuth_best, avg_azimuth_index_best;
    2332             :     UWord16 dist_azimuth_indexes_best[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    2333             : 
    2334             :     UWord16 idx, dist_count;
    2335             :     Word16 direction_bits_ec;
    2336             : 
    2337             :     UWord16 dist_elevation_indexes[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    2338             :     UWord16 dist_elevation_alphabets[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    2339             :     UWord16 dist_azimuth_indexes[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    2340             :     UWord16 dist_azimuth_alphabets[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    2341      257060 :     Word16 all_zero_dist_elevation_indexes = 1, all_zero_dist_azimuth_indexes = 1;
    2342      257060 :     move16();
    2343      257060 :     move16();
    2344             :     Word16 gr_param_elevation, gr_size_elevation, egr_size_elevation, gr_param_azimuth, gr_size_azimuth;
    2345             :     Word16 egr_size_azimuth, elevation_bits_ec, azimuth_bits_ec;
    2346             : 
    2347             :     Word32 abs_theta;
    2348             :     Word16 theta_cb[MAX_NO_THETA]; // Q22-Q16 = Q6
    2349             :     Word16 sign_th, no_th;
    2350      257060 :     Word16 avg_azimuth_index_upd = 0, use_adapt_avg;
    2351      257060 :     move16();
    2352      257060 :     Word16 make_gain = 0;
    2353      257060 :     move16();
    2354      257060 :     Word16 bits_gained = 0;
    2355      257060 :     move16();
    2356      257060 :     nblocks = q_direction->cfg.nblocks;
    2357      257060 :     move16();
    2358             : 
    2359             :     /* estimate the number of bits for entropy coding of the direction values */
    2360      257060 :     direction_bits_ec = 0;
    2361      257060 :     move16();
    2362      257060 :     diff_idx_min = DIRAC_DIFFUSE_LEVELS;
    2363      257060 :     move16();
    2364      257060 :     idx = 0;
    2365      257060 :     move16();
    2366      257060 :     dist_count = 0;
    2367      257060 :     move16();
    2368      257060 :     set_zero_fx( avg_direction_vector, 3 );
    2369             : 
    2370     1401636 :     FOR( i = start_band; i < nbands; i++ )
    2371             :     {
    2372     1144576 :         IF( hrmasa_flag )
    2373             :         {
    2374           0 :             diff_idx_min = 0; // min( q_direction->band_data[i].energy_ratio_index_mod[0]>>1, diff_idx_min );
    2375           0 :             move16();
    2376             :         }
    2377             :         ELSE
    2378             :         {
    2379     1144576 :             diff_idx_min = s_min( q_direction->band_data[i].energy_ratio_index_mod[0], diff_idx_min );
    2380             :         }
    2381             : 
    2382     1144576 :         IF( GT_32( q_direction->band_data[i].energy_ratio_index_mod[0], diffuseness_index_max_ec_frame ) )
    2383             :         {
    2384             :             /* estimate the raw part  */
    2385      315998 :             IF( q_direction->not_in_2D > 0 )
    2386             :             {
    2387     1212111 :                 FOR( j = 0; j < nblocks; j++ )
    2388             :                 {
    2389      939696 :                     direction_bits_ec = add( direction_bits_ec, q_direction->band_data[i].bits_sph_idx[j] );
    2390             :                 }
    2391             :             }
    2392             :             ELSE
    2393             :             {
    2394      173029 :                 FOR( j = 0; j < nblocks; j++ )
    2395             :                 {
    2396      129446 :                     direction_bits_ec = add( direction_bits_ec, ivas_qmetadata_encode_quasi_uniform_length_fx( q_direction->band_data[i].azimuth_index[j], q_direction->band_data[i].azimuth_m_alphabet[j] ) );
    2397             :                 }
    2398             :             }
    2399             :         }
    2400             :         ELSE
    2401             :         {
    2402      828578 :             dist_count = add( dist_count, nblocks );
    2403             : 
    2404     3759544 :             FOR( j = 0; j < nblocks; j++ )
    2405             :             {
    2406             :                 /*compute the average direction */
    2407     2930966 :                 ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[i].azimuth_fx[j], q_direction->band_data[i].elevation_fx[j], direction_vector );
    2408     2930966 :                 scale_sig32( direction_vector, 3, -8 ); // Q30 -> Q22
    2409             : #ifdef VEC_ARITH_OPT_v1
    2410     2930966 :                 v_add_fixed_no_hdrm( avg_direction_vector, direction_vector, avg_direction_vector, 3 );
    2411             : #else  /* VEC_ARITH_OPT_v1 */
    2412             :                 v_add_fixed( avg_direction_vector, direction_vector, avg_direction_vector, 3, 0 );
    2413             : #endif /* VEC_ARITH_OPT_v1 */
    2414             :             }
    2415             :         }
    2416             :     }
    2417             : 
    2418             :     /* quantize average elevation and azimuth angles using the best angle spacing and equatorial precision */
    2419      257060 :     ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector, Q22, &avg_azimuth, &avg_elevation );
    2420             : 
    2421      257060 :     IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2422             :     {
    2423       15130 :         avg_elevation_alphabet = no_theta_masa[bits_direction_masa[diff_idx_min] - 3]; // Q0
    2424       15130 :         move16();
    2425       15130 :         avg_azimuth_alphabet = no_phi_masa[bits_direction_masa[diff_idx_min] - 1][0]; /* average azimuth is quantized on the equatorial plane Q0*/
    2426       15130 :         move16();
    2427             :     }
    2428             :     ELSE
    2429             :     {
    2430      241930 :         avg_elevation_alphabet = sub( shl( no_theta_masa[bits_direction_masa[diff_idx_min] - 3], 1 ), 1 ); // Q0
    2431      241930 :         avg_azimuth_alphabet = no_phi_masa[bits_direction_masa[diff_idx_min] - 1][0];                      /* average azimuth is quantized on the equatorial plane Q0*/
    2432      241930 :         move16();
    2433             :     }
    2434             : 
    2435      257060 :     no_th = no_theta_masa[bits_direction_masa[diff_idx_min] - 3]; // Q0
    2436      257060 :     move16();
    2437             : 
    2438     2551612 :     FOR( i = 0; i < no_th; i++ )
    2439             :     {
    2440     2294552 :         theta_cb[i] = imult1616( i, round_fx( delta_theta_masa_fx[bits_direction_masa[diff_idx_min] - 3] ) ); // Q6
    2441     2294552 :         move16();
    2442             :     }
    2443             : 
    2444      257060 :     if ( GT_32( theta_cb[i - 1], 90 << Q6 ) )
    2445             :     {
    2446      132088 :         theta_cb[i - 1] = 90 << Q6;
    2447      132088 :         move16();
    2448             :     }
    2449             : 
    2450      257060 :     IF( avg_elevation < 0 )
    2451             :     {
    2452      109204 :         abs_theta = L_negate( avg_elevation ); // Q22
    2453      109204 :         sign_th = -1;
    2454      109204 :         move16();
    2455             :     }
    2456             :     ELSE
    2457             :     {
    2458      147856 :         abs_theta = avg_elevation; // Q22
    2459      147856 :         move32();
    2460      147856 :         sign_th = 1;
    2461      147856 :         move16();
    2462             :     }
    2463             : 
    2464             :     Word16 tmp;
    2465      257060 :     avg_elevation_index = squant_fx( round_fx( abs_theta ), &tmp, theta_cb, no_th );
    2466      257060 :     avg_elevation = L_deposit_h( tmp ); // Q22
    2467             : 
    2468      257060 :     IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2469             :     {
    2470       15130 :         assert( avg_elevation >= 0 );
    2471             :     }
    2472             :     ELSE
    2473             :     {
    2474      241930 :         IF( sign_th < 0 )
    2475             :         {
    2476      109204 :             avg_elevation_index = sub( shr( avg_elevation_alphabet, 1 ), avg_elevation_index );
    2477             :         }
    2478             :         ELSE
    2479             :         {
    2480      132726 :             avg_elevation_index = add( avg_elevation_index, shr( avg_elevation_alphabet, 1 ) );
    2481             :         }
    2482             :         // avg_elevation *= sign_th;
    2483      241930 :         if ( sign_th < 0 )
    2484             :         {
    2485      109204 :             avg_elevation = L_negate( avg_elevation ); // Q22
    2486             :         }
    2487             :     }
    2488             : 
    2489      257060 :     avg_azimuth_index = (UWord16) ( quantize_phi_enc_fx( L_add( avg_azimuth, DEGREE_180_Q_22 ), 0, &avg_azimuth, avg_azimuth_alphabet ) );
    2490             : 
    2491             :     /* Elevation only if not 2D */
    2492      257060 :     IF( q_direction->not_in_2D > 0 )
    2493             :     {
    2494      220304 :         avg_elevation_index_initial = avg_elevation_index;
    2495      220304 :         move16();
    2496      220304 :         elevation_bits_ec_best = MAX16B;
    2497      220304 :         move16();
    2498      220304 :         avg_elevation_index_best = -1; /* out of range value */
    2499      220304 :         move16();
    2500      220304 :         gr_param_elevation_best = -1; /* out of range value */
    2501      220304 :         move16();
    2502             : 
    2503      881216 :         FOR( avg_elevation_offset = 0; avg_elevation_offset < q_direction->cfg.search_effort; avg_elevation_offset++ )
    2504             :         {
    2505      660912 :             IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2506             :             {
    2507       12990 :                 avg_elevation_index = u_extract_l( UL_addNsD( avg_elevation_index_initial, avg_elevation_offset ) );
    2508             :             }
    2509             :             ELSE
    2510             :             {
    2511      647922 :                 avg_elevation_index = (UWord16) L_add( avg_elevation_index_initial, ivas_qmetadata_dereorder_generic_fx( avg_elevation_offset ) );
    2512             :             }
    2513             :             // avg_elevation_index = (uint16_t) ( ( avg_elevation_index + avg_elevation_alphabet ) % avg_elevation_alphabet );
    2514      660912 :             avg_elevation_index = u_extract_l( UL_addNsD( avg_elevation_index, avg_elevation_alphabet ) % avg_elevation_alphabet );
    2515             : 
    2516      660912 :             all_zero_dist_elevation_indexes = 1;
    2517      660912 :             move16();
    2518      660912 :             IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2519             :             {
    2520       12990 :                 elevation_bits_ec = ivas_qmetadata_encode_quasi_uniform_length_fx( avg_elevation_index, avg_elevation_alphabet );
    2521             :             }
    2522             :             ELSE
    2523             :             {
    2524      647922 :                 elevation_bits_ec = ivas_qmetadata_encode_quasi_uniform_length_fx( ivas_qmetadata_reorder_generic_fx( sub( avg_elevation_index, shr( avg_elevation_alphabet, 1 ) ) ), avg_elevation_alphabet );
    2525             :             }
    2526      660912 :             idx = 0;
    2527      660912 :             move16();
    2528     3609462 :             FOR( i = start_band; i < nbands; i++ )
    2529             :             {
    2530     2948550 :                 IF( LE_16( q_direction->band_data[i].energy_ratio_index_mod[0], diffuseness_index_max_ec_frame ) )
    2531             :                 {
    2532     9837183 :                     FOR( j = 0; j < nblocks; j++ )
    2533             :                     {
    2534             :                         /* project the quantized average elevation to the same grid as the current sample */
    2535     7705878 :                         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2536             :                         {
    2537       77232 :                             avg_elevation_index_projected = ivas_chan_project_elevation_index_fx( avg_elevation_index, avg_elevation_alphabet, q_direction->band_data[i].elevation_m_alphabet[j] ); // Q0
    2538             :                         }
    2539             :                         ELSE
    2540             :                         {
    2541     7628646 :                             avg_elevation_index_projected = ivas_dirac_project_elevation_index_fx( avg_elevation_index, avg_elevation_alphabet, q_direction->band_data[i].elevation_m_alphabet[j] ); // Q0
    2542             :                         }
    2543             : 
    2544     7705878 :                         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2545             :                         {
    2546       77232 :                             IF( L_sub( q_direction->band_data[i].elevation_index[j], avg_elevation_index_projected ) > 0 )
    2547             :                             {
    2548             :                                 // dist_elevation_indexes[idx] = 2 * ( q_direction->band_data[i].elevation_index[j] - avg_elevation_index_projected ) - 1;
    2549        3868 :                                 dist_elevation_indexes[idx] = sub( shl( sub( q_direction->band_data[i].elevation_index[j], avg_elevation_index_projected ), 1 ), 1 );
    2550        3868 :                                 move16();
    2551             :                             }
    2552             :                             ELSE
    2553             :                             {
    2554             :                                 // dist_elevation_indexes[idx] = -2 * ( q_direction->band_data[i].elevation_index[j] - avg_elevation_index_projected );
    2555       73364 :                                 dist_elevation_indexes[idx] = imult1616( -2, sub( q_direction->band_data[i].elevation_index[j], avg_elevation_index_projected ) );
    2556       73364 :                                 move16();
    2557             :                             }
    2558             :                         }
    2559             :                         ELSE
    2560             :                         {
    2561     7628646 :                             dist_elevation_indexes[idx] = ivas_qmetadata_reorder_elevation_index_fx( q_direction->band_data[i].elevation_index[j], avg_elevation_index_projected, q_direction->band_data[i].elevation_m_alphabet[j] );
    2562     7628646 :                             move16();
    2563             :                         }
    2564     7705878 :                         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2565             :                         {
    2566       77232 :                             dist_elevation_alphabets[idx] = sub( shl( q_direction->band_data[i].elevation_m_alphabet[j], 1 ), 1 );
    2567       77232 :                             move16();
    2568             :                         }
    2569             :                         ELSE
    2570             :                         {
    2571     7628646 :                             dist_elevation_alphabets[idx] = q_direction->band_data[i].elevation_m_alphabet[j];
    2572     7628646 :                             move16();
    2573             :                         }
    2574             : 
    2575     7705878 :                         if ( dist_elevation_indexes[idx] != 0 )
    2576             :                         {
    2577     5224400 :                             all_zero_dist_elevation_indexes = 0;
    2578     5224400 :                             move16();
    2579             :                         }
    2580     7705878 :                         idx = add( idx, 1 );
    2581             :                     }
    2582             :                 }
    2583             :             }
    2584             : 
    2585      660912 :             IF( all_zero_dist_elevation_indexes )
    2586             :             {
    2587       57827 :                 egr_size_elevation = 0;
    2588       57827 :                 move16();
    2589       57827 :                 gr_param_elevation = 4;
    2590       57827 :                 move16();
    2591             :             }
    2592             :             ELSE
    2593             :             {
    2594      603085 :                 gr_param_elevation = ivas_qmetadata_get_optimal_gr_param_fx( dist_elevation_indexes, idx, 4, &gr_size_elevation ); // Q0
    2595      603085 :                 egr_size_elevation = 0;
    2596      603085 :                 move16();
    2597     8193868 :                 FOR( i = 0; i < idx; i++ )
    2598             :                 {
    2599     7590783 :                     egr_size_elevation = add( egr_size_elevation, ivas_qmetadata_encode_extended_gr_length_fx( dist_elevation_indexes[i], dist_elevation_alphabets[i], gr_param_elevation ) ); // Q0
    2600             :                 }
    2601             :             }
    2602      660912 :             elevation_bits_ec = add( elevation_bits_ec, add( ivas_qmetadata_encode_quasi_uniform_length_fx( gr_param_elevation, 4 + 1 ), egr_size_elevation ) ); // Q0
    2603             : 
    2604      660912 :             IF( LT_16( elevation_bits_ec, elevation_bits_ec_best ) )
    2605             :             {
    2606      300917 :                 elevation_bits_ec_best = elevation_bits_ec; // Q0
    2607      300917 :                 move16();
    2608      300917 :                 avg_elevation_index_best = avg_elevation_index; // Q0
    2609      300917 :                 move16();
    2610      300917 :                 gr_param_elevation_best = gr_param_elevation; // Q0
    2611      300917 :                 move16();
    2612     4171363 :                 FOR( idx = 0; idx < dist_count; idx++ )
    2613             :                 {
    2614     3870446 :                     dist_elevation_indexes_best[idx] = dist_elevation_indexes[idx];
    2615     3870446 :                     move16();
    2616             :                 }
    2617             :             }
    2618             :         }
    2619             : 
    2620      220304 :         direction_bits_ec = add( direction_bits_ec, elevation_bits_ec_best );
    2621             :     }
    2622             : 
    2623             :     /*Azimuth*/
    2624      257060 :     use_adapt_avg = 0;
    2625      257060 :     move16();
    2626      257060 :     test();
    2627      257060 :     test();
    2628      257060 :     IF( GE_16( sub( nbands, start_band ), 5 ) && NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) && GT_16( nblocks, 1 ) )
    2629             :     {
    2630        3415 :         use_adapt_avg = calc_var_azi_fx( q_direction, diffuseness_index_max_ec_frame, L_sub( avg_azimuth, DEGREE_180_Q_22 ), &avg_azimuth ); // 180.Q22
    2631             : 
    2632        3415 :         avg_azimuth_index = (UWord16) ( quantize_phi_enc_fx( L_add( avg_azimuth, DEGREE_180_Q_22 ), 0, &avg_azimuth, avg_azimuth_alphabet ) );
    2633             :     }
    2634      257060 :     avg_azimuth_index_initial = avg_azimuth_index; /* avg_azimuth_index;*/
    2635      257060 :     move16();
    2636      257060 :     azimuth_bits_ec_best = MAX16B;
    2637      257060 :     move16();
    2638      257060 :     avg_azimuth_index_best = -1; /* out of range value */
    2639      257060 :     move16();
    2640      257060 :     gr_param_azimuth_best = -1; /* out of range value */
    2641      257060 :     move16();
    2642             : 
    2643     1028240 :     FOR( avg_azimuth_offset = 0; avg_azimuth_offset < q_direction->cfg.search_effort; avg_azimuth_offset++ )
    2644             :     {
    2645      771180 :         set_zero_fx( avg_direction_vector, 3 );
    2646      771180 :         avg_azimuth_index = (UWord16) L_add( avg_azimuth_index_initial, ivas_qmetadata_dereorder_generic_fx( avg_azimuth_offset ) );
    2647      771180 :         avg_azimuth_index = (UWord16) ( L_add( avg_azimuth_index, avg_azimuth_alphabet ) % avg_azimuth_alphabet );
    2648      771180 :         all_zero_dist_azimuth_indexes = 1;
    2649      771180 :         move16();
    2650      771180 :         azimuth_bits_ec = ivas_qmetadata_encode_quasi_uniform_length_fx( ivas_qmetadata_reorder_generic_fx( sub( avg_azimuth_index, shr( avg_azimuth_alphabet, 1 ) ) ), avg_azimuth_alphabet );
    2651             : 
    2652      771180 :         idx = 0;
    2653      771180 :         move16();
    2654     4204908 :         FOR( i = start_band; i < nbands; i++ )
    2655             :         {
    2656     3433728 :             IF( LE_16( q_direction->band_data[i].energy_ratio_index_mod[0], diffuseness_index_max_ec_frame ) )
    2657             :             {
    2658    11278632 :                 FOR( j = 0; j < nblocks; j++ )
    2659             :                 {
    2660     8792898 :                     test();
    2661     8792898 :                     test();
    2662     8792898 :                     IF( GT_16( idx, MASA_LIMIT_IDX_AVG_AZI ) && NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) && EQ_16( use_adapt_avg, 1 ) )
    2663             :                     {
    2664       52437 :                         avg_azimuth_index_projected = ivas_dirac_project_azimuth_index_fx( avg_azimuth_index_upd, avg_azimuth_alphabet, q_direction->band_data[i].azimuth_m_alphabet[j] );
    2665             :                     }
    2666             :                     ELSE
    2667             :                     {
    2668     8740461 :                         test();
    2669     8740461 :                         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) && ( use_adapt_avg == 1 ) )
    2670             :                         {
    2671       34935 :                             ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[i].azimuth_fx[j], q_direction->band_data[i].elevation_fx[j], direction_vector );
    2672       34935 :                             scale_sig32( direction_vector, 3, -8 ); // Q30 -> Q22
    2673             : 
    2674       34935 :                             IF( LT_16( idx, 4 ) )
    2675             :                             {
    2676             : #ifdef VEC_ARITH_OPT_v1
    2677       29220 :                                 v_add_fixed_no_hdrm( avg_direction_vector, direction_vector, avg_direction_vector, 3 );
    2678             : #else  /* VEC_ARITH_OPT_v1 */
    2679             :                                 v_add_fixed( avg_direction_vector, direction_vector, avg_direction_vector, 3, 0 );
    2680             : #endif /* VEC_ARITH_OPT_v1 */
    2681             :                             }
    2682             :                         }
    2683             :                         /* project the quantized average azimuth angle to the same grid as the current sample */
    2684     8740461 :                         avg_azimuth_index_projected = ivas_dirac_project_azimuth_index_fx( avg_azimuth_index, avg_azimuth_alphabet, q_direction->band_data[i].azimuth_m_alphabet[j] );
    2685             :                     }
    2686     8792898 :                     dist_azimuth_indexes[idx] = ivas_qmetadata_reorder_azimuth_index_fx( add( ivas_qmetadata_dereorder_generic_fx( q_direction->band_data[i].azimuth_index[j] ), shr( q_direction->band_data[i].azimuth_m_alphabet[j], 1 ) ), avg_azimuth_index_projected, q_direction->band_data[i].azimuth_m_alphabet[j] );
    2687     8792898 :                     move16();
    2688     8792898 :                     dist_azimuth_alphabets[idx] = q_direction->band_data[i].azimuth_m_alphabet[j];
    2689     8792898 :                     move16();
    2690             : 
    2691     8792898 :                     if ( dist_azimuth_indexes[idx] != 0 )
    2692             :                     {
    2693     6727084 :                         all_zero_dist_azimuth_indexes = 0;
    2694     6727084 :                         move16();
    2695             :                     }
    2696             : 
    2697     8792898 :                     test();
    2698     8792898 :                     test();
    2699     8792898 :                     IF( GE_16( idx, MASA_LIMIT_IDX_AVG_AZI ) && NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) && EQ_16( use_adapt_avg, 1 ) )
    2700             :                     {
    2701       58152 :                         IF( idx % nblocks == 0 )
    2702             :                         {
    2703             :                             // v_multc( avg_direction_vector, 0.5f, avg_direction_vector, 3 );
    2704       14538 :                             scale_sig32( avg_direction_vector, 3, -1 );
    2705             :                         }
    2706             : 
    2707             :                         /*compute the average direction per already coded subband */
    2708       58152 :                         ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[i].azimuth_fx[j], q_direction->band_data[i].elevation_fx[j], direction_vector );
    2709       58152 :                         scale_sig32( direction_vector, 3, -8 ); // Q30 -> Q22
    2710             : 
    2711             : #ifdef VEC_ARITH_OPT_v1
    2712       58152 :                         v_add_fixed_no_hdrm( avg_direction_vector, direction_vector, avg_direction_vector, 3 );
    2713             : #else  /* VEC_ARITH_OPT_v1 */
    2714             :                         v_add_fixed( avg_direction_vector, direction_vector, avg_direction_vector, 3, 0 );
    2715             : #endif /* VEC_ARITH_OPT_v1 */
    2716       58152 :                         ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector, Q22, &avg_azimuth, &avg_elevation );
    2717             : 
    2718       58152 :                         avg_azimuth_index_upd = quantize_phi_enc_fx( L_add( avg_azimuth, 180 << Q22 ), 0, &avg_azimuth, avg_azimuth_alphabet );
    2719             :                     }
    2720     8792898 :                     idx = add( idx, 1 );
    2721             :                 }
    2722             :             }
    2723             :         }
    2724             : 
    2725      771180 :         IF( all_zero_dist_azimuth_indexes )
    2726             :         {
    2727       67684 :             egr_size_azimuth = 0;
    2728       67684 :             move16();
    2729       67684 :             gr_param_azimuth = 5;
    2730       67684 :             move16();
    2731             :         }
    2732             :         ELSE
    2733             :         {
    2734             :             /* estimate the ExtendedGR part for azimuth */
    2735      703496 :             gr_param_azimuth = ivas_qmetadata_get_optimal_gr_param_fx( dist_azimuth_indexes, idx, 5, &gr_size_azimuth );
    2736      703496 :             egr_size_azimuth = 0;
    2737      703496 :             move16();
    2738     9377664 :             FOR( i = 0; i < idx; i++ )
    2739             :             {
    2740     8674168 :                 egr_size_azimuth = add( egr_size_azimuth, ivas_qmetadata_encode_extended_gr_length_fx( dist_azimuth_indexes[i], dist_azimuth_alphabets[i], gr_param_azimuth ) );
    2741             :             }
    2742             :         }
    2743             : 
    2744      771180 :         azimuth_bits_ec = add( azimuth_bits_ec, add( ivas_qmetadata_encode_quasi_uniform_length_fx( gr_param_azimuth, 5 + 1 ), egr_size_azimuth ) );
    2745             : 
    2746      771180 :         IF( LT_16( azimuth_bits_ec, azimuth_bits_ec_best ) )
    2747             :         {
    2748      369332 :             azimuth_bits_ec_best = azimuth_bits_ec;
    2749      369332 :             move16();
    2750      369332 :             avg_azimuth_index_best = avg_azimuth_index;
    2751      369332 :             move16();
    2752      369332 :             gr_param_azimuth_best = gr_param_azimuth;
    2753      369332 :             move16();
    2754             : 
    2755     4871216 :             FOR( idx = 0; idx < dist_count; idx++ )
    2756             :             {
    2757     4501884 :                 dist_azimuth_indexes_best[idx] = dist_azimuth_indexes[idx];
    2758     4501884 :                 move16();
    2759             :             }
    2760             :         }
    2761             :     }
    2762             : 
    2763      257060 :     test();
    2764      257060 :     test();
    2765      257060 :     test();
    2766      257060 :     IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) && GT_16( dist_count, 4 ) && NE_16( gr_param_azimuth_best, 5 ) && GT_16( nblocks, 1 ) )
    2767             :     {
    2768        2711 :         azimuth_bits_ec_best = add( azimuth_bits_ec_best, 1 );
    2769             :     }
    2770             : 
    2771      257060 :     direction_bits_ec = add( direction_bits_ec, azimuth_bits_ec_best );
    2772             : 
    2773             :     /*Decision raw or EC*/
    2774             :     /* one bit is used to indicate whether the direction values are entropy coded or coded raw */
    2775      257060 :     IF( LT_16( direction_bits_ec, direction_bits_raw ) ) /* entropy coding is better */
    2776             :     {
    2777             : 
    2778             :         /* encode the raw part first */
    2779      842280 :         FOR( i = start_band; i < nbands; i++ )
    2780             :         {
    2781      707221 :             IF( GT_16( q_direction->band_data[i].energy_ratio_index_mod[0], diffuseness_index_max_ec_frame ) )
    2782             :             {
    2783      190455 :                 IF( q_direction->not_in_2D > 0 )
    2784             :                 {
    2785      817213 :                     FOR( j = 0; j < nblocks; j++ )
    2786             :                     {
    2787      645599 :                         push_next_indice( hMetaData, q_direction->band_data[i].spherical_index[j], q_direction->band_data[i].bits_sph_idx[j] );
    2788             :                     }
    2789             :                 }
    2790             :                 ELSE
    2791             :                 {
    2792       87173 :                     FOR( j = 0; j < nblocks; j++ )
    2793             :                     {
    2794       68332 :                         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, q_direction->band_data[i].azimuth_index[j], q_direction->band_data[i].azimuth_m_alphabet[j] );
    2795             :                     }
    2796             :                 }
    2797             :             }
    2798             :         }
    2799             : 
    2800      135059 :         test();
    2801      135059 :         test();
    2802      135059 :         if ( GT_16( nbands, 1 ) && sub( direction_bits_ec, max_bits ) > 0 && LT_16( sub( direction_bits_ec, max_bits ), imult1616( nblocks, nbands ) ) )
    2803             :         {
    2804        2207 :             make_gain = 1;
    2805        2207 :             move16();
    2806             :         }
    2807             : 
    2808      135059 :         IF( q_direction->not_in_2D > 0 )
    2809             :         {
    2810             :             /* encode the ExtendedGR part for elevation */
    2811      116175 :             IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    2812             :             {
    2813        2553 :                 ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, avg_elevation_index_best, avg_elevation_alphabet );
    2814             :             }
    2815             :             ELSE
    2816             :             {
    2817      113622 :                 ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, ivas_qmetadata_reorder_generic_fx( sub( avg_elevation_index_best, shr( avg_elevation_alphabet, 1 ) ) ), avg_elevation_alphabet );
    2818             :             }
    2819             : 
    2820      116175 :             ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, gr_param_elevation_best, 4 + 1 );
    2821             : 
    2822      116175 :             IF( NE_16( gr_param_elevation_best, 4 ) ) /* not all zero */
    2823             :             {
    2824     1660758 :                 FOR( idx = 0; idx < dist_count; idx++ )
    2825             :                 {
    2826     1566553 :                     ivas_qmetadata_encode_extended_gr_fx( hMetaData, dist_elevation_indexes_best[idx], dist_elevation_alphabets[idx], gr_param_elevation_best );
    2827             :                 }
    2828             :             }
    2829             :         }
    2830             : 
    2831             :         /* encode the ExtendedGR part for azimuth */
    2832      135059 :         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, ivas_qmetadata_reorder_generic_fx( sub( avg_azimuth_index_best, shr( avg_azimuth_alphabet, 1 ) ) ), avg_azimuth_alphabet );
    2833             : 
    2834      135059 :         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, gr_param_azimuth_best, 5 + 1 );
    2835             : 
    2836      135059 :         IF( NE_16( gr_param_azimuth_best, 5 ) ) /* not all zero */
    2837             :         {
    2838      561000 :             FOR( idx = 0; idx < s_min( nblocks, dist_count ); idx++ )
    2839             :             {
    2840      444627 :                 test();
    2841      444627 :                 test();
    2842      444627 :                 IF( EQ_16( make_gain, 1 ) && LT_16( bits_gained, sub( direction_bits_ec, max_bits ) ) && GT_16( dist_azimuth_alphabets[idx], 40 ) )
    2843             :                 {
    2844        1569 :                     IF( GT_16( dist_azimuth_indexes_best[idx], 1 ) )
    2845             :                     {
    2846        1032 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( dist_azimuth_indexes_best[idx], 2 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2847        1032 :                         bits_gained = add( bits_gained, sub( ivas_qmetadata_encode_extended_gr_length_fx( dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best ),
    2848        1032 :                                                              ivas_qmetadata_encode_extended_gr_length_fx( sub( dist_azimuth_indexes_best[idx], 2 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best ) ) );
    2849             :                     }
    2850         537 :                     ELSE IF( EQ_16( dist_azimuth_indexes_best[idx], 1 ) )
    2851             :                     {
    2852         226 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( dist_azimuth_indexes_best[idx], 1 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2853         226 :                         bits_gained = add( bits_gained, sub( ivas_qmetadata_encode_extended_gr_length_fx( dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best ),
    2854         226 :                                                              ivas_qmetadata_encode_extended_gr_length_fx( sub( dist_azimuth_indexes_best[idx], 1 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best ) ) );
    2855             :                     }
    2856             :                     ELSE
    2857             :                     {
    2858         311 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2859             :                     }
    2860             :                 }
    2861             :                 ELSE
    2862             :                 {
    2863      443058 :                     ivas_qmetadata_encode_extended_gr_fx( hMetaData, dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2864             :                 }
    2865             :             }
    2866             : 
    2867      116373 :             IF( GT_16( dist_count, nblocks ) )
    2868             :             {
    2869       90748 :                 test();
    2870       90748 :                 IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) && GT_16( nblocks, 1 ) )
    2871             :                 {
    2872        2267 :                     push_next_indice( hMetaData, use_adapt_avg, 1 );
    2873             :                 }
    2874     1447749 :                 FOR( idx = nblocks; idx < dist_count; idx++ )
    2875             :                 {
    2876     1357001 :                     test();
    2877     1357001 :                     test();
    2878     1357001 :                     IF( EQ_16( make_gain, 1 ) && LT_16( bits_gained, sub( direction_bits_ec, max_bits ) ) && GT_16( dist_azimuth_alphabets[idx], 40 ) )
    2879             :                     {
    2880       10009 :                         IF( GT_16( dist_azimuth_indexes_best[idx], 1 ) )
    2881             :                         {
    2882        7116 :                             ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( dist_azimuth_indexes_best[idx], 2 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2883        7116 :                             bits_gained = add( bits_gained, sub( ivas_qmetadata_encode_extended_gr_length_fx( dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best ),
    2884        7116 :                                                                  ivas_qmetadata_encode_extended_gr_length_fx( sub( dist_azimuth_indexes_best[idx], 2 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best ) ) );
    2885             :                         }
    2886        2893 :                         ELSE IF( EQ_16( dist_azimuth_indexes_best[idx], 1 ) )
    2887             :                         {
    2888        1246 :                             ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( dist_azimuth_indexes_best[idx], 1 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2889        1246 :                             bits_gained = add( bits_gained, sub( ivas_qmetadata_encode_extended_gr_length_fx( dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best ),
    2890        1246 :                                                                  ivas_qmetadata_encode_extended_gr_length_fx( sub( dist_azimuth_indexes_best[idx], 1 ), dist_azimuth_alphabets[idx], gr_param_azimuth_best ) ) );
    2891             :                         }
    2892             :                         ELSE
    2893             :                         {
    2894        1647 :                             ivas_qmetadata_encode_extended_gr_fx( hMetaData, dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2895             :                         }
    2896             :                     }
    2897             :                     ELSE
    2898             :                     {
    2899     1346992 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, dist_azimuth_indexes_best[idx], dist_azimuth_alphabets[idx], gr_param_azimuth_best );
    2900             :                     }
    2901             :                 }
    2902             :             }
    2903             :         }
    2904             : 
    2905      135059 :         direction_bits_ec = sub( direction_bits_ec, bits_gained );
    2906             :     }
    2907             :     ELSE
    2908             :     {
    2909      122001 :         direction_bits_ec = -1;
    2910      122001 :         move16();
    2911             :     }
    2912             : 
    2913      257060 :     return direction_bits_ec;
    2914             : }
    2915             : 
    2916             : 
    2917             : /*-------------------------------------------------------------------------
    2918             :  * ivas_qmetadata_raw_encode_dir()
    2919             :  *
    2920             :  * Main function for raw coding of the directions (writing and bit estimation)
    2921             :  *------------------------------------------------------------------------*/
    2922      379061 : static Word16 ivas_qmetadata_raw_encode_dir_fx(
    2923             :     BSTR_ENC_HANDLE hMetaData,
    2924             :     IVAS_QDIRECTION *q_direction,
    2925             :     const Word16 nbands,
    2926             :     const Word16 start_band )
    2927             : {
    2928             :     Word16 i, j;
    2929             :     Word16 direction_bits_raw;
    2930      379061 :     Word16 start_bits = 0; /*To avoid compiler warning*/
    2931      379061 :     move16();
    2932             : 
    2933      379061 :     direction_bits_raw = 0;
    2934      379061 :     move16();
    2935      379061 :     if ( hMetaData != NULL )
    2936             :     {
    2937      122001 :         start_bits = hMetaData->nb_bits_tot;
    2938      122001 :         move16();
    2939             :     }
    2940             : 
    2941      379061 :     IF( q_direction->not_in_2D > 0 )
    2942             :     {
    2943     1671705 :         FOR( i = start_band; i < nbands; i++ )
    2944             :         {
    2945     1347272 :             IF( hMetaData != NULL )
    2946             :             {
    2947     1559103 :                 FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
    2948             :                 {
    2949     1194681 :                     push_next_indice( hMetaData, q_direction->band_data[i].spherical_index[j], q_direction->band_data[i].bits_sph_idx[j] );
    2950             :                 }
    2951             :             }
    2952             :             ELSE
    2953             :             {
    2954      982850 :                 direction_bits_raw = add( direction_bits_raw, imult1616( q_direction->cfg.nblocks, q_direction->band_data[i].bits_sph_idx[0] ) );
    2955             :             }
    2956             :         }
    2957             :     }
    2958             :     ELSE
    2959             :     {
    2960      289287 :         FOR( i = start_band; i < nbands; i++ )
    2961             :         {
    2962      918580 :             FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
    2963             :             {
    2964      683921 :                 IF( hMetaData != NULL )
    2965             :                 {
    2966      192135 :                     ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, q_direction->band_data[i].azimuth_index[j], q_direction->band_data[i].azimuth_m_alphabet[j] );
    2967             :                 }
    2968             :                 ELSE
    2969             :                 {
    2970      491786 :                     direction_bits_raw = add( direction_bits_raw,
    2971      491786 :                                               ivas_qmetadata_encode_quasi_uniform_length_fx( q_direction->band_data[i].azimuth_index[j], q_direction->band_data[i].azimuth_m_alphabet[j] ) );
    2972             :                 }
    2973             :             }
    2974             :         }
    2975             :     }
    2976             : 
    2977      379061 :     IF( hMetaData != NULL )
    2978             :     {
    2979      122001 :         direction_bits_raw = sub( hMetaData->nb_bits_tot, start_bits );
    2980             :     }
    2981             : 
    2982      379061 :     return direction_bits_raw;
    2983             : }
    2984             : 
    2985             : /*-------------------------------------------------------------------------
    2986             :  * ivas_qmetadata_get_optimal_gr_param()
    2987             :  *
    2988             :  *
    2989             :  *------------------------------------------------------------------------*/
    2990     1306581 : static Word16 ivas_qmetadata_get_optimal_gr_param_fx(
    2991             :     UWord16 *unsigned_data,
    2992             :     const Word16 count,
    2993             :     const Word16 gr_param_count,
    2994             :     Word16 *opt_gr_size )
    2995             : {
    2996             :     Word16 opt_bits, bits, idx;
    2997             :     Word16 opt_gr_param;
    2998             :     Word16 p;
    2999             : 
    3000     1306581 :     opt_bits = MAX16B;
    3001     1306581 :     move16();
    3002     1306581 :     opt_gr_param = -1;
    3003     1306581 :     move16();
    3004             : 
    3005     7236401 :     FOR( p = 0; p < gr_param_count; p++ )
    3006             :     {
    3007     5929820 :         bits = imult1616( count, add( 1, p ) ); /* terminating zero bit and the lsb bits */
    3008    79663792 :         FOR( idx = 0; idx < count; idx++ )
    3009             :         {
    3010    73733972 :             bits = add( bits, extract_l( L_shr( unsigned_data[idx], p ) ) ); /* leading one bits */
    3011             :         }
    3012             : 
    3013     5929820 :         IF( LT_16( bits, opt_bits ) )
    3014             :         {
    3015     2187612 :             opt_gr_param = p;
    3016     2187612 :             move16();
    3017     2187612 :             opt_bits = bits;
    3018     2187612 :             move16();
    3019             :         }
    3020             :     }
    3021             : 
    3022     1306581 :     *opt_gr_size = opt_bits;
    3023     1306581 :     move16();
    3024             : 
    3025     1306581 :     return opt_gr_param;
    3026             : }
    3027             : 
    3028             : /*-------------------------------------------------------------------------
    3029             :  * ivas_qmetadata_encode_extended_gr_length_fx()
    3030             :  *
    3031             :  *
    3032             :  *------------------------------------------------------------------------*/
    3033             : Word16
    3034    20226824 : ivas_qmetadata_encode_extended_gr_length_fx(
    3035             :     const UWord16 value,
    3036             :     const UWord16 alphabet_size,
    3037             :     const Word16 gr_param )
    3038             : {
    3039             :     UWord16 msb_alphabet_size;
    3040             :     Word16 bits;
    3041             :     UWord16 msb, lsb;
    3042             : 
    3043             : 
    3044    20226824 :     msb_alphabet_size = (UWord16) L_shr( L_add( alphabet_size, L_sub( L_shl( 1U, gr_param ), 1 ) ), gr_param );
    3045             : 
    3046    20226824 :     IF( LE_32( msb_alphabet_size, 3 ) )
    3047             :     {
    3048             :         /* EncodeQuasiUniform is always equal or better than Limited GR with up to 3 msb values */
    3049     4031549 :         bits = ivas_qmetadata_encode_quasi_uniform_length_fx( value, alphabet_size );
    3050             :     }
    3051             :     ELSE
    3052             :     {
    3053    16195275 :         msb = (UWord16) L_shr( value, gr_param );
    3054             : 
    3055    16195275 :         bits = msb; /* leading one bits */
    3056    16195275 :         move16();
    3057    16195275 :         IF( LT_32( msb, L_sub( msb_alphabet_size, 1 ) ) )
    3058             :         {
    3059    15964781 :             bits = add( bits, add( 1, gr_param ) ); /* terminating zero bit, if not the largest msb (Limited GR), and the lsb bits */
    3060             :         }
    3061             :         ELSE
    3062             :         {
    3063      230494 :             lsb = (UWord16) L_and( value, L_sub( L_shl( 1U, gr_param ), 1 ) );
    3064      230494 :             bits = add( bits, ivas_qmetadata_encode_quasi_uniform_length_fx( lsb, (UWord16) L_sub( alphabet_size, L_shl( L_sub( msb_alphabet_size, 1 ), gr_param ) ) ) );
    3065             :         }
    3066             :     }
    3067             : 
    3068    20226824 :     return bits;
    3069             : }
    3070             : 
    3071             : /*-------------------------------------------------------------------------
    3072             :  * ivas_qmetadata_reorder_elevation_index()
    3073             :  *
    3074             :  *
    3075             :  *------------------------------------------------------------------------*/
    3076    11276265 : static Word16 ivas_qmetadata_reorder_elevation_index_fx(
    3077             :     const Word16 elevation_index,
    3078             :     const Word16 avg_elevation_index,
    3079             :     const Word16 elevation_alphabet )
    3080             : {
    3081             :     Word16 elevation_alphabet_half;
    3082             :     Word16 elevation_index_reordered;
    3083             : 
    3084    11276265 :     elevation_alphabet_half = shr( elevation_alphabet, 1 );
    3085    11276265 :     elevation_index_reordered = sub( elevation_index, avg_elevation_index );
    3086             : 
    3087             :     /* reduce the distance for the index elevation to the range [-elevation_alphabet_half, elevation_alphabet_half] */
    3088    11276265 :     IF( LT_16( elevation_index_reordered, negate( elevation_alphabet_half ) ) )
    3089             :     {
    3090      230148 :         elevation_index_reordered = add( elevation_index_reordered, elevation_alphabet );
    3091             :     }
    3092    11046117 :     ELSE IF( GT_16( elevation_index_reordered, elevation_alphabet_half ) )
    3093             :     {
    3094      193084 :         elevation_index_reordered = sub( elevation_index_reordered, elevation_alphabet );
    3095             :     }
    3096             : 
    3097             :     /* fold reduced signed distance value for converting to unsigned */
    3098    11276265 :     elevation_index_reordered = ivas_qmetadata_reorder_generic_fx( elevation_index_reordered );
    3099             : 
    3100    11276265 :     return elevation_index_reordered;
    3101             : }
    3102             : 
    3103             : /*-------------------------------------------------------------------------
    3104             :  * ivas_qmetadata_reorder_azimuth_index()
    3105             :  *
    3106             :  *
    3107             :  *------------------------------------------------------------------------*/
    3108     8792898 : static Word16 ivas_qmetadata_reorder_azimuth_index_fx(
    3109             :     const Word16 azimuth_index,
    3110             :     const Word16 avg_azimuth_index,
    3111             :     const Word16 azimuth_alphabet )
    3112             : {
    3113             :     Word16 azimuth_alphabet_half;
    3114             :     Word16 azimuth_index_reordered;
    3115             : 
    3116     8792898 :     azimuth_index_reordered = sub( azimuth_index, avg_azimuth_index );
    3117             : 
    3118     8792898 :     test();
    3119     8792898 :     IF( NE_16( azimuth_alphabet, 1 ) && EQ_16( s_and( azimuth_alphabet, 0x01 ), 1 ) )
    3120             :     {
    3121     3647619 :         return ( ivas_qmetadata_reorder_elevation_index_fx( azimuth_index, avg_azimuth_index, azimuth_alphabet ) );
    3122             :     }
    3123     5145279 :     ELSE IF( NE_16( azimuth_alphabet, 1 ) )
    3124             :     {
    3125     5140548 :         azimuth_alphabet_half = shr( azimuth_alphabet, 1 );
    3126             :         /* reduce the distance for the index azimuth to the range [-azimuth_alphabet_half, azimuth_alphabet_half - 1] */
    3127     5140548 :         IF( LT_16( azimuth_index_reordered, negate( azimuth_alphabet_half ) ) )
    3128             :         {
    3129      108410 :             azimuth_index_reordered = add( azimuth_index_reordered, azimuth_alphabet );
    3130             :         }
    3131     5032138 :         ELSE IF( GT_16( azimuth_index_reordered, sub( azimuth_alphabet_half, 1 ) ) )
    3132             :         {
    3133      358549 :             azimuth_index_reordered = sub( azimuth_index_reordered, azimuth_alphabet );
    3134             :         }
    3135             :         /* fold reduced signed distance value for converting to unsigned */
    3136     5140548 :         azimuth_index_reordered = ivas_qmetadata_reorder_generic_fx( azimuth_index_reordered );
    3137             :     }
    3138             :     ELSE
    3139             :     {
    3140             :         /* for North and South poles, a single azimuth direction exists */
    3141        4731 :         azimuth_index_reordered = 0;
    3142        4731 :         move16();
    3143             :     }
    3144             : 
    3145     5145279 :     return azimuth_index_reordered;
    3146             : }
    3147             : 
    3148             : /*-------------------------------------------------------------------------
    3149             :  * ivas_qmetadata_encode_extended_gr_fx()
    3150             :  *
    3151             :  *
    3152             :  *------------------------------------------------------------------------*/
    3153     4565381 : void ivas_qmetadata_encode_extended_gr_fx(
    3154             :     BSTR_ENC_HANDLE hMetaData,
    3155             :     const UWord16 value,
    3156             :     const UWord16 alphabet_size,
    3157             :     const Word16 gr_param )
    3158             : {
    3159             :     UWord16 msb_alphabet_size;
    3160             :     UWord16 msb, lsb, cnt;
    3161             : 
    3162             : 
    3163     4565381 :     msb_alphabet_size = (UWord16) L_shr( L_add( alphabet_size, L_sub( L_shl( 1U, gr_param ), 1 ) ), gr_param );
    3164             : 
    3165     4565381 :     IF( LE_32( msb_alphabet_size, 3 ) )
    3166             :     {
    3167             :         /* EncodeQuasiUniform is always equal or better than Limited GR with up to 3 msb values */
    3168      307684 :         ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, value, alphabet_size );
    3169             :     }
    3170             :     ELSE
    3171             :     {
    3172     4257697 :         msb = (UWord16) L_shr( value, gr_param );
    3173     4257697 :         lsb = (UWord16) L_and( value, L_sub( L_shl( 1U, gr_param ), 1 ) );
    3174             : 
    3175     7527045 :         FOR( cnt = 0; cnt < msb; cnt++ )
    3176             :         {
    3177             :             /* leading one bits */
    3178     3269348 :             push_next_indice( hMetaData, 1, 1 );
    3179             :         }
    3180             : 
    3181     4257697 :         IF( LT_32( msb, L_sub( msb_alphabet_size, 1 ) ) )
    3182             :         {
    3183     4233842 :             push_next_indice( hMetaData, 0, 1 ); /* terminating zero bit, if not the largest msb (Limited GR) */
    3184     4233842 :             IF( gr_param > 0 )
    3185             :             {
    3186     1587182 :                 push_next_indice( hMetaData, lsb, gr_param );
    3187             :             }
    3188             :         }
    3189             :         ELSE
    3190             :         {
    3191       23855 :             ivas_qmetadata_encode_quasi_uniform_fx( hMetaData, lsb, (UWord16) L_sub( alphabet_size, L_shl( L_sub( msb_alphabet_size, 1 ), gr_param ) ) );
    3192             :         }
    3193             :     }
    3194             : 
    3195     4565381 :     return;
    3196             : }
    3197             : 
    3198             : /*-----------------------------------------------------------------------*
    3199             :  * Local functions (EC3, requantize directions)
    3200             :  *-----------------------------------------------------------------------*/
    3201        3265 : static Word16 truncGR0_fx(
    3202             :     Word32 *data_fx,     // Q22
    3203             :     Word32 *data_hat_fx, // Q22
    3204             :     UWord16 *data_idx,
    3205             :     const Word16 len,
    3206             :     const Word16 bits_allowed,
    3207             :     Word32 *st_fx, // Q31
    3208             :     Word32 *ct_fx  // Q31
    3209             : )
    3210             : {
    3211             :     Word16 i;
    3212             :     Word16 bits;
    3213        3265 :     const Word16 remap3b[8] = { 1, 6, 2, 4, 0, 5, 3, 7 };
    3214        3265 :     const Word16 remap2b[4] = { 1, 2, 0, 3 };
    3215             :     Word32 diff_fx[MAX_PARAM_SPATIAL_SUBFRAMES];
    3216             :     Word16 indx[MAX_PARAM_SPATIAL_SUBFRAMES];
    3217             :     Word32 L_temp;
    3218        3265 :     move16();
    3219        3265 :     move16();
    3220        3265 :     move16();
    3221        3265 :     move16();
    3222        3265 :     move16();
    3223        3265 :     move16();
    3224        3265 :     move16();
    3225        3265 :     move16();
    3226        3265 :     move16();
    3227        3265 :     move16();
    3228        3265 :     move16();
    3229        3265 :     move16();
    3230        3265 :     bits = 0;
    3231        3265 :     move16();
    3232        3265 :     set_val_Word32( data_hat_fx, 0, len );
    3233        3265 :     set_val_Word32( diff_fx, 10000, len );
    3234             : 
    3235        3265 :     IF( LE_16( bits_allowed, add( len, 1 ) ) )
    3236             :     {
    3237         246 :         bits = s_min( bits_allowed, len );
    3238         246 :         set_val_Word32( data_hat_fx, 0, len );
    3239             : 
    3240        1190 :         FOR( i = 0; i < bits; i++ )
    3241             :         {
    3242         944 :             IF( LE_32( L_abs( data_fx[i] ), 377487360 ) ) // 90 in Q22
    3243             :             {
    3244         861 :                 data_idx[i] = 0;
    3245         861 :                 move16();
    3246         861 :                 data_hat_fx[i] = 0;
    3247         861 :                 move32();
    3248             :             }
    3249             :             ELSE
    3250             :             {
    3251          83 :                 data_idx[i] = 1;
    3252          83 :                 move16();
    3253          83 :                 data_hat_fx[i] = -754974720; //-180 in Q22
    3254          83 :                 move32();
    3255             :             }
    3256             :         }
    3257             : 
    3258         246 :         return bits;
    3259             :     }
    3260             : 
    3261       14891 :     FOR( i = 0; i < len; i++ )
    3262             :     {
    3263       11872 :         data_idx[i] = quantize_phi_enc_fx( L_add( data_fx[i], DEGREE_180_Q_22 ), 0, &data_hat_fx[i], 8 );
    3264       11872 :         move16();
    3265       11872 :         data_hat_fx[i] = L_sub( data_hat_fx[i], DEGREE_180_Q_22 );
    3266       11872 :         move32();
    3267       11872 :         data_idx[i] = remap3b[data_idx[i]];
    3268       11872 :         move16();
    3269       11872 :         bits = add( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[i], 8, 0 ) );
    3270             :         // diff[i] = -st[i] - ct[i] * cosf( PI_OVER_180 * ( data[i] - data_hat[i] ) ); /*(data[i] - data_hat[i])*(data[i] - data_hat[i]);*/
    3271       11872 :         L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( L_sub( data_fx[i], data_hat_fx[i] ), 91 ), 7 ) ) ) ); // Q31
    3272       11872 :         diff_fx[i] = L_negate( L_add( L_shr( st_fx[i], 1 ), L_shr( Mpy_32_32( ct_fx[i], L_temp ), 1 ) ) );                         // Q30
    3273       11872 :         move32();
    3274             :     }
    3275             : 
    3276        3019 :     i = 0;
    3277        3019 :     move16();
    3278        3019 :     IF( GT_16( bits, bits_allowed ) )
    3279             :     {
    3280        2706 :         sort_desc_ind_32_fx( diff_fx, len, indx );
    3281       11330 :         FOR( i = len - 1; i >= 0; i-- )
    3282             :         {
    3283        9723 :             IF( GT_32( data_idx[indx[i]], 3 ) )
    3284             :             {
    3285        5400 :                 bits = sub( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[indx[i]], 8, 0 ) );
    3286             :                 // data_idx[indx[i]] = quantize_phi( data[indx[i]] + 180, 0, &data_hat[indx[i]], 4 );
    3287        5400 :                 data_idx[indx[i]] = quantize_phi_enc_fx( L_add( data_fx[indx[i]], DEGREE_180_Q_22 ), 0, &data_hat_fx[indx[i]], 4 );
    3288        5400 :                 move16();
    3289             :                 // data_hat[indx[i]] -= 180;
    3290        5400 :                 data_hat_fx[indx[i]] = L_sub( data_hat_fx[indx[i]], DEGREE_180_Q_22 );
    3291        5400 :                 move32();
    3292        5400 :                 data_idx[indx[i]] = remap2b[data_idx[indx[i]]];
    3293        5400 :                 move16();
    3294        5400 :                 bits = add( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[indx[i]], 8, 0 ) );
    3295             :                 // diff[indx[i]] = -st[i] - ct[i] * cosf( PI_OVER_180 * ( data[indx[i]] - data_hat[indx[i]] ) );
    3296        5400 :                 L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( L_sub( data_fx[indx[i]], data_hat_fx[indx[i]] ), 91 ), 7 ) ) ) ); // Q31
    3297             : 
    3298        5400 :                 diff_fx[indx[i]] = L_negate( L_add( L_shr( st_fx[i], 1 ), L_shr( Mpy_32_32( ct_fx[i], L_temp ), 1 ) ) ); // Q30
    3299        5400 :                 move32();
    3300             :             }
    3301        9723 :             IF( LE_16( bits, bits_allowed ) )
    3302             :             {
    3303        1099 :                 BREAK;
    3304             :             }
    3305             :         }
    3306             :     }
    3307             : 
    3308        3019 :     IF( GT_16( bits, bits_allowed ) )
    3309             :     {
    3310        1607 :         sort_desc_ind_32_fx( diff_fx, len, indx );
    3311        3380 :         FOR( i = len - 1; i >= 0; i-- )
    3312             :         {
    3313             : 
    3314        3347 :             IF( GT_16( data_idx[indx[i]], 1 ) )
    3315             :             {
    3316        2874 :                 bits = sub( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[indx[i]], 8, 0 ) );
    3317             : 
    3318        2874 :                 IF( LE_32( L_abs( data_fx[indx[i]] ), 377487360 ) ) // 90 in Q22
    3319             :                 {
    3320        1830 :                     data_idx[indx[i]] = 0;
    3321        1830 :                     move16();
    3322             :                     // data_hat[i] = 0.0f;
    3323        1830 :                     data_hat_fx[indx[i]] = 0;
    3324        1830 :                     move32();
    3325             :                 }
    3326             :                 ELSE
    3327             :                 {
    3328        1044 :                     data_idx[indx[i]] = 1;
    3329        1044 :                     move16();
    3330             :                     // data_hat[i] = -180.0f;
    3331        1044 :                     data_hat_fx[indx[i]] = -754974720; //-180 in Q22
    3332        1044 :                     move32();
    3333             :                 }
    3334             : 
    3335        2874 :                 bits = add( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[indx[i]], 8, 0 ) );
    3336             :                 // diff[indx[i]] = -st[i] - ct[i] * cosf( PI_OVER_180 * ( data[indx[i]] - data_hat[indx[i]] ) );
    3337        2874 :                 L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( L_sub( data_fx[indx[i]], data_hat_fx[indx[i]] ), 91 ), 7 ) ) ) ); // Q31
    3338             : 
    3339        2874 :                 diff_fx[indx[i]] = L_negate( L_add( L_shr( st_fx[i], 1 ), L_shr( Mpy_32_32( ct_fx[i], L_temp ), 1 ) ) ); // Q30
    3340        2874 :                 move32();
    3341             :             }
    3342             : 
    3343        3347 :             IF( LE_16( bits, bits_allowed ) )
    3344             :             {
    3345        1574 :                 BREAK;
    3346             :             }
    3347             :         }
    3348             :     }
    3349             : 
    3350        3019 :     IF( GT_16( bits, bits_allowed ) )
    3351             :     {
    3352             : 
    3353          33 :         sort_desc_ind_32_fx( diff_fx, len, indx );
    3354          34 :         FOR( i = len - 1; i >= 0; i-- )
    3355             :         {
    3356             : 
    3357          34 :             IF( data_idx[indx[i]] > 0 )
    3358             :             {
    3359          33 :                 bits = sub( bits, data_idx[indx[i]] );
    3360          33 :                 data_idx[indx[i]] = 0;
    3361          33 :                 move16();
    3362          33 :                 data_hat_fx[indx[i]] = 0;
    3363          33 :                 move32();
    3364             :             }
    3365          34 :             IF( LE_16( bits, bits_allowed ) )
    3366             :             {
    3367          33 :                 BREAK;
    3368             :             }
    3369             :         }
    3370             :     }
    3371             : 
    3372        3019 :     return bits;
    3373             : }
    3374             : /*-------------------------------------------------------------------*
    3375             :  * truncGR0_chan()
    3376             :  *
    3377             :  *
    3378             :  *-------------------------------------------------------------------*/
    3379         526 : static Word16 truncGR0_chan_fx(
    3380             :     const Word32 *data_fx, // Q22
    3381             :     Word32 *data_hat_fx,   // Q22
    3382             :     UWord16 *data_idx,
    3383             :     const Word16 len,
    3384             :     const Word16 bits_allowed,
    3385             :     Word32 *st_fx,  // Q31
    3386             :     Word32 *ct_fx ) // Q31
    3387             : {
    3388             :     Word16 i, idx_crt;
    3389             :     Word16 bits;
    3390             :     Word32 diff_fx[MAX_PARAM_SPATIAL_SUBFRAMES], sort_diff_fx[MAX_PARAM_SPATIAL_SUBFRAMES], min_diff_fx, sum_diff_fx;
    3391             :     Word16 indx[MAX_PARAM_SPATIAL_SUBFRAMES];
    3392             :     Word32 L_temp;
    3393         526 :     bits = 0;
    3394         526 :     move16();
    3395         526 :     set_val_Word32( data_hat_fx, 0, len );
    3396         526 :     set_val_Word32( diff_fx, 10000, len );
    3397         526 :     Word16 gb = find_guarded_bits_fx( len );
    3398         526 :     IF( LE_16( bits_allowed, add( len, 1 ) ) )
    3399             :     {
    3400           0 :         bits = s_min( bits_allowed, len );
    3401           0 :         set_val_Word32( data_hat_fx, 0, len );
    3402             : 
    3403           0 :         FOR( i = 0; i < bits; i++ )
    3404             :         {
    3405           0 :             IF( LE_32( L_abs( data_fx[i] ), 377487360 ) ) // 90 in Q22
    3406             :             {
    3407           0 :                 data_idx[i] = 0;
    3408           0 :                 move16();
    3409           0 :                 data_hat_fx[i] = 0;
    3410           0 :                 move32();
    3411             :             }
    3412             :             ELSE
    3413             :             {
    3414           0 :                 data_idx[i] = 1;
    3415           0 :                 move16();
    3416             :                 // data_hat[i] = -180.0f;
    3417           0 :                 data_hat_fx[i] = -754974720; //-180 in Q22
    3418           0 :                 move32();
    3419             :             }
    3420             :         }
    3421           0 :         return bits;
    3422             :     }
    3423             : 
    3424        2618 :     FOR( i = 0; i < len; i++ )
    3425             :     {
    3426        2092 :         data_idx[i] = quantize_phi_chan_lbr_fx( data_fx[i], &data_hat_fx[i], 9 );
    3427        2092 :         move16();
    3428        2092 :         bits = add( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[i], 9, 0 ) );
    3429             :         // diff[i] = -st[i] - ct[i] * cosf( ( data[i] - data_hat[i] ) * PI_OVER_180 );
    3430        2092 :         L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( L_sub( data_fx[i], data_hat_fx[i] ), 91 ), 7 ) ) ) ); // Q31
    3431        2092 :         diff_fx[i] = L_negate( L_add( L_shr( st_fx[i], 1 ), L_shr( Mpy_32_32( ct_fx[i], L_temp ), 1 ) ) );                         // Q30
    3432        2092 :         move32();
    3433             :     }
    3434             : 
    3435         744 :     WHILE( ( bits > bits_allowed ) )
    3436             :     {
    3437             :         //  min_diff = 1000.0f;
    3438         218 :         min_diff_fx = 2097152000; // 1000 in Q21
    3439         218 :         move32();
    3440         218 :         Word16 min_diff_e = Q31 - Q21;
    3441         218 :         move16();
    3442         218 :         idx_crt = -1;
    3443         218 :         move16();
    3444         218 :         Copy32( diff_fx, sort_diff_fx, len );
    3445        1078 :         FOR( i = 0; i < len; i++ )
    3446             :         {
    3447         860 :             IF( data_idx[i] > 0 )
    3448             :             {
    3449             :                 // sort_diff[i] = -st[i] - ct[i] * cosf( ( fabsf( data[i] ) - cb_azi_chan[( ( data_idx[i] + 1 ) >> 1 ) - 1] ) * PI_OVER_180 );
    3450         701 :                 L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( L_sub( L_abs( data_fx[i] ), cb_azi_chan_fx[( ( data_idx[i] + 1 ) >> 1 ) - 1] ), 91 ), 7 ) ) ) ); // Q31
    3451         701 :                 sort_diff_fx[i] = L_negate( L_add( L_shr( st_fx[i], 1 ), L_shr( Mpy_32_32( ct_fx[i], L_temp ), 1 ) ) );                                                               // Q30
    3452         701 :                 move32();
    3453         701 :                 sum_diff_fx = sum2_f_32_fx( sort_diff_fx, len, gb ); // Q(2*Q30-31-gb)= Q(Q29-gb)
    3454         701 :                 Word16 flag = BASOP_Util_Cmp_Mant32Exp( sum_diff_fx, sub( Q31, sub( Q29, gb ) ), min_diff_fx, min_diff_e );
    3455         701 :                 IF( EQ_16( flag, -1 ) )
    3456             :                 {
    3457         423 :                     min_diff_fx = sum_diff_fx;
    3458         423 :                     move32();
    3459         423 :                     min_diff_e = sub( Q31, sub( Q29, gb ) );
    3460         423 :                     idx_crt = i;
    3461         423 :                     move16();
    3462             :                 }
    3463         701 :                 sort_diff_fx[i] = diff_fx[i]; // Q30
    3464         701 :                 move32();
    3465             :             }
    3466             :         }
    3467             : 
    3468         218 :         IF( GT_16( idx_crt, -1 ) )
    3469             :         {
    3470         218 :             bits = sub( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[idx_crt], 9, 0 ) );
    3471         218 :             data_idx[idx_crt] = quantize_phi_chan_lbr_fx( data_fx[idx_crt], &data_hat_fx[idx_crt], add( data_idx[idx_crt], 1 ) );
    3472         218 :             move16();
    3473         218 :             bits = add( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[idx_crt], 9, 0 ) );
    3474             :             // diff[idx_crt] = -st[idx_crt] - ct[idx_crt] * cosf( ( data[idx_crt] - data_hat[idx_crt] ) * PI_OVER_180 );
    3475         218 :             L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( L_sub( data_fx[idx_crt], data_hat_fx[idx_crt] ), 91 ), 7 ) ) ) ); // Q31
    3476             : 
    3477         218 :             diff_fx[idx_crt] = L_negate( L_add( L_shr( st_fx[idx_crt], 1 ), L_shr( Mpy_32_32( ct_fx[idx_crt], L_temp ), 1 ) ) ); // Q30
    3478         218 :             move32();
    3479             :         }
    3480             :         ELSE
    3481             :         {
    3482           0 :             BREAK;
    3483             :         }
    3484             :     }
    3485             : 
    3486         526 :     IF( GT_16( bits, bits_allowed ) )
    3487             :     {
    3488           0 :         Copy32( diff_fx, sort_diff_fx, len );
    3489           0 :         sort_desc_ind_32_fx( sort_diff_fx, len, indx );
    3490             : 
    3491           0 :         FOR( i = len - 1; i >= 0; i-- )
    3492             :         {
    3493           0 :             idx_crt = indx[i];
    3494           0 :             move16();
    3495           0 :             IF( data_idx[idx_crt] > 0 )
    3496             :             {
    3497           0 :                 bits = sub( bits, ivas_qmetadata_encode_extended_gr_length_fx( data_idx[idx_crt], 9, 0 ) );
    3498           0 :                 data_idx[idx_crt] = 0;
    3499           0 :                 move16();
    3500           0 :                 data_hat_fx[idx_crt] = 0;
    3501           0 :                 move32();
    3502           0 :                 bits = add( bits, 1 );
    3503             :             }
    3504             : 
    3505           0 :             IF( LE_16( bits, bits_allowed ) )
    3506             :             {
    3507           0 :                 BREAK;
    3508             :             }
    3509             :         }
    3510             :     }
    3511             : 
    3512         526 :     return bits;
    3513             : }
    3514             : 
    3515             : /*-------------------------------------------------------------------*
    3516             :  * common_direction()
    3517             :  *
    3518             :  *
    3519             :  *-------------------------------------------------------------------*/
    3520        3481 : static Word16 common_direction_fx(
    3521             :     IVAS_QDIRECTION *q_direction,
    3522             :     const Word16 band_idx,
    3523             :     const Word16 len,
    3524             :     const Word16 bits_allowed,
    3525             :     BSTR_ENC_HANDLE hMetaData,
    3526             :     Word32 *elevation_orig_fx, // Q22
    3527             :     Word32 *azimuth_orig_fx    // Q22
    3528             : )
    3529             : {
    3530             :     Word16 nbits;
    3531             :     Word16 no_th, i, id_th, k;
    3532             :     Word32 theta_cb_fx[5];
    3533             :     Word32 dist_fx, best_dist_fx;
    3534             :     Word32 ct_fx[MAX_PARAM_SPATIAL_SUBFRAMES], st_fx[MAX_PARAM_SPATIAL_SUBFRAMES];
    3535             : 
    3536        3481 :     nbits = 0;
    3537        3481 :     move16();
    3538        3481 :     IF( bits_allowed == 0 )
    3539             :     {
    3540           0 :         FOR( i = 0; i < len; i++ )
    3541             :         {
    3542           0 :             q_direction->band_data[band_idx].elevation_fx[i] = 0;
    3543           0 :             move32();
    3544           0 :             q_direction->band_data[band_idx].azimuth_fx[i] = 0;
    3545           0 :             move32();
    3546             :         }
    3547             : 
    3548           0 :         return 0;
    3549             :     }
    3550             : 
    3551        3481 :     IF( LE_16( bits_allowed, add( len, 1 ) ) )
    3552             :     {
    3553          80 :         set_val_Word32( q_direction->band_data[band_idx].elevation_fx, 0, len );
    3554          80 :         set_val_Word32( st_fx, 0, len );
    3555             : 
    3556         400 :         FOR( i = 0; i < len; i++ )
    3557             :         {
    3558             :             // ct[i] = cosf( elevation_orig[i] * PI_OVER_180 );
    3559         320 :             ct_fx[i] = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( elevation_orig_fx[i], 91 ), 7 ) ) ) ); // Q31
    3560         320 :             move32();
    3561             :         }
    3562             : 
    3563          80 :         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    3564             :         {
    3565           0 :             nbits = truncGR0_chan_fx( azimuth_orig_fx, q_direction->band_data[band_idx].azimuth_fx, q_direction->band_data[band_idx].azimuth_index, len, bits_allowed, st_fx, ct_fx );
    3566             :         }
    3567             :         ELSE
    3568             :         {
    3569          80 :             nbits = truncGR0_fx( azimuth_orig_fx, q_direction->band_data[band_idx].azimuth_fx, q_direction->band_data[band_idx].azimuth_index, len, bits_allowed, st_fx, ct_fx );
    3570             :         }
    3571             : 
    3572         400 :         FOR( i = 0; i < nbits; i++ )
    3573             :         {
    3574         320 :             push_next_indice( hMetaData, q_direction->band_data[band_idx].azimuth_index[i], 1 );
    3575             :         }
    3576             : 
    3577          80 :         return nbits;
    3578             :     }
    3579             : 
    3580        3401 :     no_th = add( no_theta_masa[0], 3 ); /* only 5 values for theta; the lat 2 are +/-90 */
    3581             : 
    3582        3401 :     theta_cb_fx[0] = 0;
    3583        3401 :     move32();
    3584        3401 :     theta_cb_fx[1] = delta_theta_masa_fx[2];
    3585        3401 :     move32();
    3586        3401 :     theta_cb_fx[2] = -theta_cb_fx[1];
    3587        3401 :     move32();
    3588             :     // theta_cb[3] = 90.0f;
    3589        3401 :     theta_cb_fx[3] = 377487360; // 90.0f in Q22
    3590        3401 :     move32();
    3591             :     // theta_cb[4] = -90.0f;
    3592        3401 :     theta_cb_fx[4] = -377487360; //-90.0f in Q22
    3593        3401 :     move32();
    3594             :     // best_dist = 900000.0f;
    3595        3401 :     best_dist_fx = 1843200000; // 900000.0f in Q11
    3596        3401 :     move32();
    3597        3401 :     Word16 best_dist_q = Q11;
    3598        3401 :     move16();
    3599        3401 :     id_th = 0;
    3600        3401 :     move16();
    3601        3401 :     Word16 gb = find_guarded_bits_fx( len );
    3602       20406 :     FOR( i = 0; i < no_th; i++ )
    3603             :     {
    3604             :         // dist = 0.0f;
    3605       17005 :         dist_fx = 0;
    3606       17005 :         move32();
    3607       85025 :         FOR( k = 0; k < len; k++ )
    3608             :         {
    3609             :             // dist += ( elevation_orig[k] - theta_cb[i] ) * ( elevation_orig[k] - theta_cb[i] );
    3610       68020 :             dist_fx = L_add( dist_fx, L_shr( Mpy_32_32( L_sub( elevation_orig_fx[k], theta_cb_fx[i] ), L_sub( elevation_orig_fx[k], theta_cb_fx[i] ) ), gb ) ); // Q(2*Q22-31) = Q13-gb
    3611             :         }
    3612       17005 :         IF( LT_32( L_shr( dist_fx, sub( sub( Q13, gb ), best_dist_q ) ), best_dist_fx ) )
    3613             :         {
    3614        4479 :             id_th = i;
    3615        4479 :             move16();
    3616        4479 :             best_dist_fx = dist_fx;
    3617        4479 :             move32();
    3618        4479 :             best_dist_q = sub( Q13, gb );
    3619             :         }
    3620             :     }
    3621             : 
    3622        3401 :     set_val_Word32( q_direction->band_data[band_idx].elevation_fx, theta_cb_fx[id_th], len );
    3623             : 
    3624       17005 :     FOR( i = 0; i < len; i++ )
    3625             :     {
    3626       13604 :         q_direction->band_data[band_idx].elevation_index[i] = id_th;
    3627       13604 :         move16();
    3628             :     }
    3629             : 
    3630        3401 :     IF( id_th == 0 )
    3631             :     {
    3632        2331 :         push_next_indice( hMetaData, 0, 1 ); /* average theta index */
    3633             :                                              // set_f( st, 0.0f, len );
    3634        2331 :         set_val_Word32( st_fx, 0, len );
    3635             : 
    3636       11655 :         FOR( i = 0; i < len; i++ )
    3637             :         {
    3638             :             //  ct[i] = cosf( elevation_orig[i] * PI_OVER_180 );
    3639        9324 :             ct_fx[i] = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( elevation_orig_fx[i], 91 ), 7 ) ) ) ); // Q31
    3640        9324 :             move32();
    3641             :         }
    3642             : 
    3643        2331 :         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    3644             :         {
    3645         181 :             nbits = truncGR0_chan_fx( /*azimuth_orig,*/ azimuth_orig_fx, /*q_direction->band_data[band_idx].azimuth,*/ q_direction->band_data[band_idx].azimuth_fx, q_direction->band_data[band_idx].azimuth_index, len, sub( bits_allowed, 1 ), /* st,*/ st_fx, /*ct,*/ ct_fx ) + 1;
    3646             :         }
    3647             :         ELSE
    3648             :         {
    3649             : 
    3650        2150 :             nbits = truncGR0_fx( azimuth_orig_fx, q_direction->band_data[band_idx].azimuth_fx, q_direction->band_data[band_idx].azimuth_index, len, bits_allowed - 1, st_fx, ct_fx ) + 1;
    3651             :         }
    3652             :     }
    3653             :     ELSE
    3654             :     {
    3655        1070 :         IF( GE_16( id_th, 3 ) )
    3656             :         {
    3657             :             /* theta is 90 or -90; only theta is sent */
    3658           8 :             push_next_indice( hMetaData, add( id_th, 11 ), 4 ); /* average theta index */
    3659             : 
    3660           8 :             set_val_Word32( q_direction->band_data[band_idx].azimuth_fx, 0, len );
    3661          40 :             FOR( i = 0; i < len; i++ )
    3662             :             {
    3663          32 :                 q_direction->band_data[band_idx].azimuth_index[i] = 0;
    3664          32 :                 move16();
    3665             :             }
    3666           8 :             nbits = 4;
    3667           8 :             move16();
    3668           8 :             return nbits;
    3669             :         }
    3670             : 
    3671        1062 :         set_val_Word32( st_fx, L_deposit_h( getSineWord16R2( extract_l( L_shr( Mpy_32_16_1( theta_cb_fx[id_th], 91 ), 7 ) ) ) ), len );
    3672        1062 :         set_val_Word32( ct_fx, L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( theta_cb_fx[id_th], 91 ), 7 ) ) ) ), len );
    3673             : 
    3674        5310 :         FOR( i = 0; i < len; i++ )
    3675             :         {
    3676             :             // st[i] *= sinf( elevation_orig[i] * PI_OVER_180 );
    3677        4248 :             st_fx[i] = Mpy_32_32( st_fx[i], L_deposit_h( getSineWord16R2( extract_l( L_shr( Mpy_32_16_1( elevation_orig_fx[i], 91 ), 7 ) ) ) ) ); // Q31;
    3678        4248 :             move32();
    3679             :             // ct[i] *= cosf( elevation_orig[i] * PI_OVER_180 );
    3680        4248 :             ct_fx[i] = Mpy_32_32( ct_fx[i], L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( elevation_orig_fx[i], 91 ), 7 ) ) ) ) ); // Q31;
    3681        4248 :             move32();
    3682        4248 :             q_direction->band_data[band_idx].azimuth_index[i] = 0;
    3683        4248 :             move16();
    3684             :         }
    3685             : 
    3686        1062 :         IF( EQ_16( id_th, 1 ) )
    3687             :         {
    3688         646 :             push_next_indice( hMetaData, 2, 2 ); /* average theta index */
    3689             :         }
    3690             :         ELSE
    3691             :         {
    3692         416 :             assert( id_th == 2 );
    3693         416 :             push_next_indice( hMetaData, 6, 3 ); /* average theta index */
    3694             :         }
    3695             : 
    3696        1062 :         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    3697             :         {
    3698         337 :             nbits = add( truncGR0_chan_fx( azimuth_orig_fx, q_direction->band_data[band_idx].azimuth_fx, q_direction->band_data[band_idx].azimuth_index, len, sub( bits_allowed, add( id_th, 1 ) ), st_fx, ct_fx ), add( id_th, 1 ) );
    3699             :         }
    3700             :         ELSE
    3701             :         {
    3702             : 
    3703         725 :             nbits = add( truncGR0_fx( azimuth_orig_fx, q_direction->band_data[band_idx].azimuth_fx, q_direction->band_data[band_idx].azimuth_index, len, sub( bits_allowed, add( id_th, 1 ) ), st_fx, ct_fx ), add( id_th, 1 ) );
    3704             :         }
    3705             :     }
    3706             : 
    3707        3393 :     IF( LE_16( sub( bits_allowed, add( id_th, 1 ) ), add( len, 1 ) ) )
    3708             :     {
    3709             : 
    3710          89 :         FOR( i = 0; i < s_min( len, sub( bits_allowed, add( id_th, 1 ) ) ); i++ )
    3711             :         {
    3712          71 :             push_next_indice( hMetaData, q_direction->band_data[band_idx].azimuth_index[i], 1 );
    3713             :         }
    3714             :     }
    3715             :     ELSE
    3716             :     {
    3717        3375 :         IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    3718             :         {
    3719        2590 :             FOR( i = 0; i < len; i++ )
    3720             :             {
    3721        2072 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, q_direction->band_data[band_idx].azimuth_index[i], 9, 0 );
    3722             :             }
    3723             :         }
    3724             :         ELSE
    3725             :         {
    3726       14285 :             FOR( i = 0; i < len; i++ )
    3727             :             {
    3728       11428 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, q_direction->band_data[band_idx].azimuth_index[i], 8, 0 );
    3729             :             }
    3730             :         }
    3731             :     }
    3732             : 
    3733        3393 :     return nbits;
    3734             : }
    3735             : 
    3736             : /*-------------------------------------------------------------------*
    3737             :  * encode_directions_subband()
    3738             :  *
    3739             :  *
    3740             :  *-------------------------------------------------------------------*/
    3741       42006 : static Word16 encode_directions_subband_fx(
    3742             :     IVAS_QDIRECTION *q_direction,
    3743             :     Word16 coding_subbands,
    3744             :     BSTR_ENC_HANDLE hMetaData,
    3745             :     const Word16 j,
    3746             :     const Word16 next_j,
    3747             :     const Word16 no_subframes,
    3748             :     const Word16 last_subband,
    3749             :     Word16 *p_diff,
    3750             :     Word32 *elevation_orig_fx, // Q22
    3751             :     Word32 *azimuth_orig_fx    // Q22
    3752             : )
    3753             : {
    3754             :     Word16 allowed_bits, use_vq, max_nb_idx, k;
    3755             :     Word16 diff;
    3756             :     Word32 d1_fx, d2_fx;
    3757             :     Word16 nbits;
    3758             :     Word16 *bits_dir0;
    3759             : 
    3760       42006 :     nbits = 0;
    3761       42006 :     move16();
    3762       42006 :     diff = *p_diff;
    3763       42006 :     move16();
    3764       42006 :     bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
    3765       42006 :     move16();
    3766       42006 :     allowed_bits = sum16_fx( bits_dir0, no_subframes );
    3767             : 
    3768       42006 :     IF( allowed_bits > 0 )
    3769             :     {
    3770       42006 :         use_vq = 0;
    3771       42006 :         move16();
    3772       42006 :         max_nb_idx = 0;
    3773       42006 :         move16();
    3774      152820 :         FOR( k = 0; k < no_subframes; k++ )
    3775             :         {
    3776      110814 :             IF( GT_16( bits_dir0[k], use_vq ) )
    3777             :             {
    3778       50391 :                 use_vq = bits_dir0[k];
    3779       50391 :                 move16();
    3780       50391 :                 max_nb_idx = k;
    3781       50391 :                 move16();
    3782             :             }
    3783             :         }
    3784             : 
    3785       42006 :         IF( GT_16( no_subframes, 1 ) )
    3786             :         {
    3787       22936 :             test();
    3788       22936 :             IF( GT_16( use_vq, 1 ) && LE_16( use_vq, LIMIT_USE_COMMON ) )
    3789             :             {
    3790        3539 :                 bits_dir0[max_nb_idx] = sub( bits_dir0[max_nb_idx], 1 );
    3791        3539 :                 move16();
    3792        3539 :                 allowed_bits = sub( allowed_bits, 1 );
    3793             :             }
    3794             :         }
    3795       42006 :         IF( GT_16( no_subframes, 1 ) )
    3796             :         {
    3797       22936 :             IF( LE_16( use_vq, LIMIT_USE_COMMON ) )
    3798             :             {
    3799             :                 /* calculate the two distances */
    3800             :                 Word16 Q_out;
    3801        3593 :                 calculate_two_distances_fx( q_direction->band_data[j].elevation_fx, bits_dir0, allowed_bits, no_subframes, &d1_fx, &d2_fx, &Q_out );
    3802        3593 :                 test();
    3803        3593 :                 test();
    3804        3593 :                 IF( ( GT_16( use_vq, 1 ) && LE_32( d2_fx, d1_fx ) ) || LE_16( use_vq, 1 ) )
    3805             :                 {
    3806        3481 :                     IF( GT_16( use_vq, 1 ) )
    3807             :                     {
    3808        3427 :                         push_next_indice( hMetaData, 1, 1 ); /* signal VQ */
    3809             :                     }
    3810             : 
    3811        3481 :                     diff = add( diff, sub( common_direction_fx( q_direction, j, no_subframes, allowed_bits, hMetaData, /*elevation_orig,*/ elevation_orig_fx, /*azimuth_orig,*/ azimuth_orig_fx ), allowed_bits ) );
    3812             : 
    3813        3481 :                     IF( last_subband == 0 )
    3814             :                     {
    3815        2403 :                         update_bits_next_block_fx( q_direction, &diff, next_j, coding_subbands, no_subframes );
    3816             :                     }
    3817             :                 }
    3818             :                 ELSE
    3819             :                 {
    3820         112 :                     push_next_indice( hMetaData, 0, 1 );
    3821             : 
    3822         112 :                     IF( last_subband == 0 )
    3823             :                     {
    3824          57 :                         Copy32( elevation_orig_fx, q_direction->band_data[j].elevation_fx, no_subframes ); // Q22
    3825          57 :                         Copy32( azimuth_orig_fx, q_direction->band_data[j].azimuth_fx, no_subframes );     // Q22
    3826          57 :                         joint_encoding_fx( q_direction, j, next_j, coding_subbands, bits_dir0, allowed_bits, hMetaData, &diff );
    3827             :                     }
    3828             :                     ELSE
    3829             :                     {
    3830         275 :                         FOR( k = 0; k < no_subframes; k++ )
    3831             :                         {
    3832             :                             /* requantize the direction */
    3833         440 :                             q_direction->band_data[j].spherical_index[k] = quantize_direction_fx( elevation_orig_fx[k], azimuth_orig_fx[k], q_direction->band_data[j].bits_sph_idx[k], &q_direction->band_data[j].elevation_fx[k], &q_direction->band_data[j].azimuth_fx[k],
    3834         220 :                                                                                                   &q_direction->band_data[j].elevation_index[k], &q_direction->band_data[j].azimuth_index[k], q_direction->cfg.mc_ls_setup );
    3835         220 :                             move16();
    3836             :                         }
    3837             : 
    3838          55 :                         IF( allowed_bits > 0 )
    3839             :                         {
    3840          55 :                             nbits = write_fixed_rate_direction_fx( hMetaData, q_direction, j, no_subframes );
    3841             :                         }
    3842             :                     }
    3843             :                 }
    3844             :             }
    3845             :             ELSE
    3846             :             {
    3847             :                 /* there is only joint coding */
    3848       19343 :                 Copy32( elevation_orig_fx, q_direction->band_data[j].elevation_fx, no_subframes ); // Q22
    3849       19343 :                 Copy32( azimuth_orig_fx, q_direction->band_data[j].azimuth_fx, no_subframes );     // Q22
    3850             : 
    3851       19343 :                 IF( last_subband == 0 )
    3852             :                 {
    3853       12558 :                     joint_encoding_fx( q_direction, j, next_j, coding_subbands, bits_dir0, allowed_bits, hMetaData, &diff );
    3854             :                 }
    3855             :                 ELSE
    3856             :                 {
    3857       33925 :                     FOR( k = 0; k < no_subframes; k++ )
    3858             :                     {
    3859             :                         /* requantize the direction */
    3860       54280 :                         q_direction->band_data[j].spherical_index[k] = quantize_direction_fx( elevation_orig_fx[k], azimuth_orig_fx[k], q_direction->band_data[j].bits_sph_idx[k], &q_direction->band_data[j].elevation_fx[k], &q_direction->band_data[j].azimuth_fx[k],
    3861       27140 :                                                                                               &q_direction->band_data[j].elevation_index[k], &q_direction->band_data[j].azimuth_index[k], q_direction->cfg.mc_ls_setup );
    3862       27140 :                         move16();
    3863             :                     }
    3864             : 
    3865        6785 :                     IF( allowed_bits > 0 )
    3866             :                     {
    3867        6785 :                         nbits = write_fixed_rate_direction_fx( hMetaData, q_direction, j, no_subframes );
    3868             :                     }
    3869             :                 }
    3870             :             }
    3871             :         }
    3872             :         ELSE
    3873             :         {
    3874             :             /* 1 subframe case */
    3875             :             /* there is only joint coding */
    3876       19070 :             Copy32( elevation_orig_fx, q_direction->band_data[j].elevation_fx, no_subframes ); // Q22
    3877       19070 :             Copy32( azimuth_orig_fx, q_direction->band_data[j].azimuth_fx, no_subframes );     // Q22
    3878             : 
    3879       19070 :             IF( last_subband == 0 )
    3880             :             {
    3881       12780 :                 joint_encoding_fx( q_direction, j, next_j, coding_subbands, bits_dir0, allowed_bits, hMetaData, &diff );
    3882             :             }
    3883             :             ELSE
    3884             :             {
    3885       12580 :                 FOR( k = 0; k < no_subframes; k++ )
    3886             :                 {
    3887             :                     /* requantize the direction */
    3888       12580 :                     q_direction->band_data[j].spherical_index[k] = quantize_direction_fx( elevation_orig_fx[k], azimuth_orig_fx[k], q_direction->band_data[j].bits_sph_idx[k], &q_direction->band_data[j].elevation_fx[k], &q_direction->band_data[j].azimuth_fx[k],
    3889        6290 :                                                                                           &q_direction->band_data[j].elevation_index[k], &q_direction->band_data[j].azimuth_index[k], q_direction->cfg.mc_ls_setup );
    3890        6290 :                     move16();
    3891             :                 }
    3892             : 
    3893        6290 :                 IF( allowed_bits > 0 )
    3894             :                 {
    3895        6290 :                     nbits = write_fixed_rate_direction_fx( hMetaData, q_direction, j, no_subframes );
    3896             :                 }
    3897             :             }
    3898             :         }
    3899             :     }
    3900             :     ELSE
    3901             :     {
    3902           0 :         set_val_Word32( q_direction->band_data[j].elevation_fx, 0, no_subframes );
    3903           0 :         set_val_Word32( q_direction->band_data[j].azimuth_fx, 0, no_subframes );
    3904             :     }
    3905             : 
    3906       42006 :     *p_diff = diff;
    3907       42006 :     move16();
    3908       42006 :     return nbits;
    3909             : }
    3910             : 
    3911             : /*-------------------------------------------------------------------*
    3912             :  * calc_var_azi()
    3913             :  *
    3914             :  *
    3915             :  *-------------------------------------------------------------------*/
    3916             : 
    3917        3415 : static Word16 calc_var_azi_fx(
    3918             :     const IVAS_QDIRECTION *q_direction,
    3919             :     const Word16 diffuseness_index_max_ec_frame,
    3920             :     const Word32 avg_azimuth, /* Q22 */
    3921             :     Word32 *avg_azimuth_out /* Q22 */ )
    3922             : {
    3923             :     Word32 var_band, dif;                                     /* Q22 */
    3924             :     Word32 avg_direction_vector_band[3], direction_vector[3]; /* Q25 */
    3925             :     Word32 avg_azimuth_band[24];                              /* Q22 */
    3926             :     Word32 avg_elevation;                                     /* Q22 */
    3927             :     Word16 i, j, idx;
    3928             : 
    3929        3415 :     idx = 0;
    3930        3415 :     move16();
    3931        3415 :     set32_fx( avg_azimuth_band, 0, 24 );
    3932             : 
    3933       20490 :     FOR( i = 0; i < q_direction->cfg.nbands; i++ )
    3934             :     {
    3935       17075 :         set32_fx( avg_direction_vector_band, 0, 3 );
    3936       17075 :         IF( LE_16( q_direction->band_data[i].energy_ratio_index_mod[0], diffuseness_index_max_ec_frame ) )
    3937             :         {
    3938       57560 :             FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
    3939             :             {
    3940             :                 /*compute the average direction */
    3941       46048 :                 ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( q_direction->band_data[i].azimuth_fx[j], q_direction->band_data[i].elevation_fx[j], direction_vector );
    3942       46048 :                 v_shr_32( direction_vector, direction_vector, 3, 5 ); // Q30 -> Q25
    3943       46048 :                 v_add_32( avg_direction_vector_band, direction_vector, avg_direction_vector_band, 3 );
    3944             :             }
    3945       11512 :             ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( avg_direction_vector_band, 30 - 5, &avg_azimuth_band[idx], &avg_elevation );
    3946       11512 :             idx += 1;
    3947             :         }
    3948             :     }
    3949             : 
    3950        3415 :     var_band = 0; /* Q11 */
    3951        3415 :     move32();
    3952             : 
    3953       14927 :     FOR( i = 0; i < idx; i++ )
    3954             :     {
    3955       11512 :         dif = L_sub( avg_azimuth_band[idx], avg_azimuth );
    3956       11512 :         if ( dif < 0 )
    3957             :         {
    3958        2831 :             dif = L_negate( dif );
    3959             :         }
    3960       11512 :         if ( GT_32( dif, DEGREE_180_Q_22 ) )
    3961             :         {
    3962           0 :             dif = L_sub( DEGREE_360_Q_22, dif );
    3963             :         }
    3964             : 
    3965       11512 :         var_band = Madd_32_32( var_band, dif, dif ); /* Q11 */
    3966             :     }
    3967             : 
    3968        3415 :     IF( idx > 0 )
    3969             :     {
    3970        3415 :         Word16 mul = div_s( 1, idx );
    3971        3415 :         var_band = Mpy_32_16_1( var_band, mul ); /* Q11 */
    3972        3415 :         var_band = L_shr_r( var_band, 11 );      /* Q0 */
    3973             :     }
    3974             : 
    3975        3415 :     IF( LE_32( var_band, VAR_AZI_THRESH ) )
    3976             :     {
    3977         980 :         *avg_azimuth_out = avg_azimuth;
    3978         980 :         move32();
    3979         980 :         return 0;
    3980             :     }
    3981             :     ELSE
    3982             :     {
    3983        2435 :         *avg_azimuth_out = avg_azimuth_band[0];
    3984        2435 :         move32();
    3985        2435 :         return 1;
    3986             :     }
    3987             : }
    3988             : 
    3989             : 
    3990             : /*-------------------------------------------------------------------*
    3991             :  * requantize_direction_EC_3()
    3992             :  *
    3993             :  *
    3994             :  *-------------------------------------------------------------------*/
    3995        9338 : static ivas_error requantize_direction_EC_3_fx(
    3996             :     Word16 *extra_bits,
    3997             :     IVAS_QDIRECTION *q_direction,
    3998             :     const Word16 coding_subbands,
    3999             :     BSTR_ENC_HANDLE hMetaData,
    4000             :     Word32 elevation_orig_fx[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], // Q22
    4001             :     Word32 azimuth_orig_fx[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],   // Q22
    4002             :     Word16 *ind_order )
    4003             : {
    4004             :     /* gradually increase the bits following the performance of the EC layer*/
    4005             :     Word16 j, k;
    4006             :     Word16 use_vq;
    4007             :     Word16 diff, allowed_bits, nbits, last_j;
    4008             :     Word16 no_subframes, start_band;
    4009             :     Word32 st_fx[MAX_PARAM_SPATIAL_SUBFRAMES], ct_fx[MAX_PARAM_SPATIAL_SUBFRAMES];
    4010             : 
    4011             :     Word16 *bits_dir0;
    4012             : 
    4013        9338 :     nbits = 0;
    4014        9338 :     move16();
    4015        9338 :     no_subframes = q_direction->cfg.nblocks;
    4016        9338 :     move16();
    4017        9338 :     start_band = q_direction->cfg.start_band;
    4018        9338 :     move16();
    4019             : 
    4020             : 
    4021        9338 :     IF( GT_16( q_direction->not_in_2D, MASA_LIMIT_2D ) )
    4022             :     {
    4023        8838 :         j = ind_order[coding_subbands - 1];
    4024        8838 :         move16();
    4025        8838 :         bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
    4026        8838 :         allowed_bits = sum_s( bits_dir0, no_subframes );
    4027        8838 :         last_j = sub( j, ( allowed_bits == 0 ) );
    4028        8838 :         diff = 0;
    4029        8838 :         move16();
    4030        8838 :         IF( EQ_16( coding_subbands, 1 ) )
    4031             :         {
    4032         143 :             last_j = start_band;
    4033         143 :             move16();
    4034             :         }
    4035       36636 :         FOR( j = 0; j < last_j; j++ )
    4036             :         {
    4037       27798 :             k = ind_order[j];
    4038       27798 :             move16();
    4039       27798 :             encode_directions_subband_fx( q_direction, coding_subbands, hMetaData, k, ind_order[j + 1], no_subframes, 0, &diff, elevation_orig_fx[k], azimuth_orig_fx[k] );
    4040             :         }
    4041             : 
    4042             :         /* last subbands to be written in fixed rate */
    4043       23046 :         FOR( j = last_j; j < coding_subbands; j++ )
    4044             :         {
    4045       14208 :             k = ind_order[j];
    4046       14208 :             move16();
    4047       14208 :             encode_directions_subband_fx( q_direction, coding_subbands, hMetaData, k, 0, no_subframes, 1, &diff, elevation_orig_fx[k], azimuth_orig_fx[k] );
    4048             :         }
    4049             :     }
    4050             :     ELSE /* 2D */
    4051             :     {
    4052         500 :         diff = 0;
    4053         500 :         nbits = 0;
    4054         500 :         move16();
    4055         500 :         move16();
    4056        2199 :         FOR( j = start_band; j < coding_subbands; j++ )
    4057             :         {
    4058        1699 :             bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
    4059        1699 :             move16();
    4060        1699 :             allowed_bits = sum_s( bits_dir0, no_subframes );
    4061        1699 :             move16();
    4062        1699 :             use_vq = 0;
    4063        1699 :             move16();
    4064        6947 :             FOR( k = 0; k < no_subframes; k++ )
    4065             :             {
    4066        5248 :                 IF( GT_16( bits_dir0[k], use_vq ) )
    4067             :                 {
    4068        1988 :                     use_vq = bits_dir0[k];
    4069        1988 :                     move16();
    4070             :                 }
    4071             :             }
    4072             : 
    4073        1699 :             test();
    4074        1699 :             IF( LE_16( use_vq, 3 ) && LE_16( allowed_bits, 11 ) )
    4075             :             {
    4076             : 
    4077         318 :                 set_val_Word32( st_fx, 0, no_subframes );
    4078             : 
    4079        1335 :                 FOR( k = 0; k < no_subframes; k++ )
    4080             :                 {
    4081             :                     // ct[k] = cosf( elevation_orig[j][k] * PI_OVER_180 );
    4082        1017 :                     ct_fx[k] = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( elevation_orig_fx[j][k], 91 ), 7 ) ) ) ); // Q31
    4083        1017 :                     move32();
    4084             :                 }
    4085             : 
    4086         318 :                 IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    4087             :                 {
    4088             :                     // nbits += truncGR0_chan( azimuth_orig[j], q_direction->band_data[j].azimuth, q_direction->band_data[j].azimuth_index, no_subframes, allowed_bits, st, ct );
    4089           8 :                     nbits = add( nbits, truncGR0_chan_fx( /*azimuth_orig,*/ azimuth_orig_fx[j], /*q_direction->band_data[j].azimuth,*/ q_direction->band_data[j].azimuth_fx, q_direction->band_data[j].azimuth_index, no_subframes, allowed_bits, /*st,*/ st_fx, /*ct,*/ ct_fx ) );
    4090             :                 }
    4091             :                 ELSE
    4092             :                 {
    4093         310 :                     nbits = add( nbits, truncGR0_fx( azimuth_orig_fx[j], q_direction->band_data[j].azimuth_fx, q_direction->band_data[j].azimuth_index, no_subframes, allowed_bits, st_fx, ct_fx ) );
    4094             :                 }
    4095             : 
    4096         318 :                 IF( LE_16( allowed_bits, add( no_subframes, 1 ) ) )
    4097             :                 {
    4098         148 :                     Word16 len = s_min( no_subframes, allowed_bits );
    4099         701 :                     FOR( k = 0; k < len; k++ )
    4100             :                     {
    4101         553 :                         push_next_indice( hMetaData, q_direction->band_data[j].azimuth_index[k], 1 );
    4102             :                     }
    4103             :                 }
    4104             :                 ELSE
    4105             :                 {
    4106         634 :                     FOR( k = 0; k < no_subframes; k++ )
    4107             :                     {
    4108         464 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, q_direction->band_data[j].azimuth_index[k], q_direction->cfg.mc_ls_setup != MC_LS_SETUP_INVALID ? 9 : 8, 0 );
    4109             :                     }
    4110             :                 }
    4111             :             }
    4112             :             ELSE
    4113             :             {
    4114        5612 :                 FOR( k = 0; k < no_subframes; k++ )
    4115             :                 {
    4116             :                     /* requantize the direction */
    4117        8462 :                     q_direction->band_data[j].spherical_index[k] = quantize_direction2D_fx( azimuth_orig_fx[j][k], 1 << q_direction->band_data[j].bits_sph_idx[k], &q_direction->band_data[j].azimuth_fx[k],
    4118        4231 :                                                                                             &q_direction->band_data[j].azimuth_index[k], q_direction->cfg.mc_ls_setup );
    4119        4231 :                     move16();
    4120        4231 :                     q_direction->band_data[j].elevation_index[k] = 0;
    4121        4231 :                     move16();
    4122             :                 }
    4123        1381 :                 nbits = add( nbits, write_fixed_rate_direction_fx( hMetaData, q_direction, j, no_subframes ) );
    4124             :             }
    4125             :         }
    4126             :     }
    4127             : 
    4128        9338 :     *extra_bits = -diff;
    4129        9338 :     move16();
    4130        9338 :     return IVAS_ERR_OK;
    4131             : }
    4132             : 
    4133             : /*-------------------------------------------------------------------*
    4134             :  * write_fixed_rate_direction()
    4135             :  *
    4136             :  * writing of the spherical indexes
    4137             :  *-------------------------------------------------------------------*/
    4138             : /*! r: number of bits written */
    4139       32147 : static Word16 write_fixed_rate_direction_fx(
    4140             :     BSTR_ENC_HANDLE hMetaData,   /* i  : MASA metadata structure                        */
    4141             :     IVAS_QDIRECTION *qdirection, /* i/o: quantized directional parameters               */
    4142             :     const Word16 j_idx,          /* i  : index of subband for which the data is written */
    4143             :     const Word16 len             /* i  : number of data                                 */
    4144             : )
    4145             : {
    4146             :     Word16 nbits, i;
    4147             : 
    4148       32147 :     nbits = 0;
    4149       32147 :     move16();
    4150      102490 :     FOR( i = 0; i < len; i++ )
    4151             :     {
    4152       70343 :         push_next_indice( hMetaData, qdirection->band_data[j_idx].spherical_index[i], qdirection->band_data[j_idx].bits_sph_idx[i] );
    4153       70343 :         nbits = extract_l( L_add( nbits, qdirection->band_data[j_idx].bits_sph_idx[i] ) );
    4154             :     }
    4155             : 
    4156       32147 :     return nbits;
    4157             : }
    4158             : 
    4159             : /*-------------------------------------------------------------------*
    4160             :  * joint_encoding()
    4161             :  *
    4162             :  * joint encoding of elevation and azimuth
    4163             :  *-------------------------------------------------------------------*/
    4164       25395 : static void joint_encoding_fx(
    4165             :     IVAS_QDIRECTION *q_direction, /* i/o: quantized directional parameters                         */
    4166             :     const Word16 j,               /* i  : subband index                                            */
    4167             :     const Word16 next_j,          /* i  : next subband index                                       */
    4168             :     const Word16 coding_subbands, /* i  : total number of subband                                  */
    4169             :     Word16 *bits_dir0,            /* i/o: number of bits for each tile in each subband             */
    4170             :     const Word16 allowed_bits,    /* i  : maximum number of bits available for the current subband */
    4171             :     BSTR_ENC_HANDLE hMetaData,    /* i/o: metadata bitstream handle                                */
    4172             :     Word16 *diff                  /* o  : bits to be given/taken to next subband                   */
    4173             : )
    4174             : {
    4175             :     Word16 k;
    4176             :     Word16 GR_ord_azimuth, use_context, GR_ord_elevation;
    4177             :     UWord8 method;
    4178             :     Word16 nbits;
    4179             :     Word16 same;
    4180             :     UWord16 data[MAX_PARAM_SPATIAL_SUBFRAMES];
    4181       25395 :     Word16 len_data = 0;
    4182       25395 :     move16();
    4183             :     Word16 no_symb_ele[MAX_PARAM_SPATIAL_SUBFRAMES];
    4184             : 
    4185       88635 :     FOR( k = 0; k < q_direction->cfg.nblocks; k++ )
    4186             :     {
    4187       63240 :         q_direction->band_data[j].bits_sph_idx[k] = bits_dir0[k];
    4188       63240 :         move16();
    4189             : 
    4190             :         /* requantize the direction */
    4191      126480 :         q_direction->band_data[j].spherical_index[k] = quantize_direction_fx( q_direction->band_data[j].elevation_fx[k], q_direction->band_data[j].azimuth_fx[k], q_direction->band_data[j].bits_sph_idx[k], &q_direction->band_data[j].elevation_fx[k],
    4192       63240 :                                                                               &q_direction->band_data[j].azimuth_fx[k], &q_direction->band_data[j].elevation_index[k], &q_direction->band_data[j].azimuth_index[k], q_direction->cfg.mc_ls_setup );
    4193             : 
    4194       63240 :         move16();
    4195       63240 :         IF( GE_32( bits_dir0[k], 3 ) )
    4196             :         {
    4197       62976 :             IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
    4198             :             {
    4199        3619 :                 q_direction->band_data[j].elevation_m_alphabet[k] = no_theta_masa[bits_dir0[k] - 3];
    4200        3619 :                 move16();
    4201        3619 :                 q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[bits_dir0[k] - 1][q_direction->band_data[j].elevation_index[k]];
    4202        3619 :                 move16();
    4203             :             }
    4204             :             ELSE
    4205             :             {
    4206       59357 :                 q_direction->band_data[j].elevation_m_alphabet[k] = sub( shl( no_theta_masa[bits_dir0[k] - 3], 1 ), 1 );
    4207       59357 :                 move16();
    4208       59357 :                 q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[bits_dir0[k] - 1][( q_direction->band_data[j].elevation_index[k] + 1 ) >> 1];
    4209       59357 :                 move16();
    4210             :             }
    4211       62976 :             assert( q_direction->band_data[j].elevation_index[k] != MASA_NO_INDEX );
    4212             :         }
    4213         264 :         ELSE IF( bits_dir0[k] > 0 )
    4214             :         {
    4215         264 :             q_direction->band_data[j].elevation_m_alphabet[k] = 1;
    4216         264 :             move16();
    4217         264 :             q_direction->band_data[j].azimuth_m_alphabet[k] = no_phi_masa[bits_dir0[k] - 1][0];
    4218         264 :             move16();
    4219             :         }
    4220             :         ELSE
    4221             :         {
    4222           0 :             q_direction->band_data[j].elevation_m_alphabet[k] = 1;
    4223           0 :             move16();
    4224           0 :             q_direction->band_data[j].azimuth_m_alphabet[k] = 1;
    4225           0 :             move16();
    4226             :         }
    4227             :     }
    4228             : 
    4229       88635 :     FOR( k = 0; k < q_direction->cfg.nblocks; k++ )
    4230             :     {
    4231       63240 :         IF( LE_32( q_direction->band_data[j].bits_sph_idx[k], 2 ) )
    4232             :         {
    4233         264 :             q_direction->band_data[j].elevation_index[k] = MASA_NO_INDEX;
    4234         264 :             move16();
    4235             :         }
    4236             :         ELSE
    4237             :         {
    4238       62976 :             no_symb_ele[len_data] = q_direction->band_data[j].elevation_m_alphabet[k];
    4239       62976 :             move16();
    4240       62976 :             data[len_data++] = q_direction->band_data[j].elevation_index[k];
    4241       62976 :             move16();
    4242             :         }
    4243             :     }
    4244             : 
    4245             : 
    4246             :     /* encode indexes for current subband and count the number of bits */
    4247       25395 :     test();
    4248       25395 :     IF( EQ_16( q_direction->cfg.nblocks, 1 ) && LE_32( q_direction->band_data[j].bits_sph_idx[0], MASA_MIN_BITS_TF + 1 ) )
    4249             :     {
    4250             :         /* encode with fixed rate only if only one subframe and very low number of bits */
    4251        6554 :         nbits = write_fixed_rate_direction_fx( hMetaData, q_direction, j, q_direction->cfg.nblocks );
    4252             :     }
    4253             :     ELSE
    4254             :     {
    4255             : 
    4256       18841 :         IF( len_data > 0 )
    4257             :         {
    4258       18841 :             nbits = GR_bits_new_fx( data, no_symb_ele, len_data, MASA_GR_ORD_EL, 1, &GR_ord_elevation );
    4259             :         }
    4260             :         ELSE
    4261             :         {
    4262           0 :             nbits = 0;
    4263           0 :             move16();
    4264           0 :             GR_ord_elevation = MASA_GR_ORD_EL;
    4265           0 :             move16();
    4266             :         }
    4267             : 
    4268       18841 :         same = 1;
    4269       18841 :         move16();
    4270       56686 :         FOR( k = 1; k < q_direction->cfg.nblocks; k++ )
    4271             :         {
    4272       37845 :             if ( NE_32( q_direction->band_data[j].elevation_index[k], q_direction->band_data[j].elevation_index[0] ) )
    4273             :             {
    4274        9424 :                 same = 0;
    4275        9424 :                 move16();
    4276             :             }
    4277             :         }
    4278       18841 :         test();
    4279       18841 :         IF( EQ_16( same, 1 ) && LT_32( q_direction->band_data[j].elevation_index[0], 4 ) )
    4280             :         {
    4281       12574 :             nbits = 3;
    4282       12574 :             move16();
    4283             :         }
    4284             :         ELSE
    4285             :         {
    4286        6267 :             same = 0;
    4287        6267 :             move16();
    4288        6267 :             nbits = add( nbits, 1 );
    4289             :         }
    4290             : 
    4291       18841 :         nbits = add( nbits, GR_bits_azimuth_context_fx( q_direction->band_data[j].azimuth_index,
    4292       18841 :                                                         q_direction->band_data[j].azimuth_m_alphabet, q_direction->cfg.nblocks, MASA_GR_ORD_AZ,
    4293       18841 :                                                         q_direction->band_data[j].bits_sph_idx, &GR_ord_azimuth, &use_context ) );
    4294             : 
    4295       18841 :         IF( allowed_bits == 0 )
    4296             :         {
    4297           0 :             nbits = 0;
    4298           0 :             move16();
    4299             :         }
    4300             :         ELSE
    4301             :         {
    4302       18841 :             IF( GE_16( nbits, allowed_bits ) )
    4303             :             {
    4304       11082 :                 nbits = add( allowed_bits, 1 ); /* fixed rate encoding */
    4305       11082 :                 method = 1;
    4306       11082 :                 move16();
    4307       11082 :                 push_next_indice( hMetaData, method, 1 );
    4308             : 
    4309             :                 /* write current subband data */
    4310       11082 :                 nbits = add( 1, write_fixed_rate_direction_fx( hMetaData, q_direction, j, q_direction->cfg.nblocks ) );
    4311             :             }
    4312             :             ELSE
    4313             :             {
    4314        7759 :                 nbits = add( nbits, 1 ); /* EC coding */
    4315        7759 :                 method = 0;
    4316        7759 :                 move16();
    4317        7759 :                 push_next_indice( hMetaData, method, 1 );
    4318             : 
    4319             :                 /* write current subband data */
    4320        7759 :                 write_ec_direction_fx( &nbits, hMetaData, q_direction, j, q_direction->cfg.nblocks, GR_ord_elevation, GR_ord_azimuth, use_context, same );
    4321        7759 :                 nbits = add( nbits, 1 );
    4322             :             }
    4323             :         }
    4324             :     }
    4325       25395 :     *diff = add( *diff, sub( nbits, allowed_bits ) );
    4326       25395 :     move16();
    4327       25395 :     update_bits_next_block_fx( q_direction, diff, next_j, coding_subbands, q_direction->cfg.nblocks );
    4328             : 
    4329       25395 :     return;
    4330             : }
    4331             : 
    4332             : /*-------------------------------------------------------------------*
    4333             :  * calculate_two_distances()
    4334             :  *
    4335             :  * calculate estimated distortions if encoding with VQ or not
    4336             :  *-------------------------------------------------------------------*/
    4337        3593 : static void calculate_two_distances_fx(
    4338             :     Word32 *el_fx,           /* i  : elevation values                 Q22 */
    4339             :     Word16 *bits,            /* i  : number of bits for each tile      */
    4340             :     const Word16 total_bits, /* i  : total number of bits for subband  */
    4341             :     const Word16 len,        /* i  : number of tiles                   */
    4342             :     Word32 *p_d1,            /* o  : first distortion                Q_out  */
    4343             :     Word32 *p_d2,            /* o  : second distortion               Q_out  */
    4344             :     Word16 *Q_out )
    4345             : {
    4346             :     Word16 i;
    4347             :     Word32 d1_fx, d2_fx, el_av_fx;
    4348        3593 :     const Word32 cos_delta_phi_cb_fx[] = { // Q31
    4349             :                                            1821066112,
    4350             :                                            1930158336,
    4351             :                                            1991146880,
    4352             :                                            2053638656,
    4353             :                                            2092508032,
    4354             :                                            2107969920,
    4355             :                                            2121069568,
    4356             :                                            2131377536
    4357             :     };
    4358        3593 :     move32();
    4359        3593 :     move32();
    4360        3593 :     move32();
    4361        3593 :     move32();
    4362        3593 :     move32();
    4363        3593 :     move32();
    4364        3593 :     move32();
    4365        3593 :     move32();
    4366             :     Word32 var_el_fx;
    4367        3593 :     d1_fx = 0;
    4368        3593 :     move32();
    4369        3593 :     d2_fx = 0;
    4370        3593 :     move32();
    4371             :     Word16 temp, temp1;
    4372             :     Word32 L_temp, L_temp1, L_temp2, L_temp3;
    4373        3593 :     Word16 gb = find_guarded_bits_fx( len );
    4374        3593 :     el_av_fx = L_shl( mean_no_sat_Word32_fx( el_fx, len, gb ), gb ); // Q22-gb
    4375        3593 :     IF( GT_16( total_bits, 9 ) )
    4376             :     {
    4377       16510 :         FOR( i = 0; i < len; i++ )
    4378             :         {
    4379       13208 :             IF( GT_16( bits[i], 2 ) )
    4380             :             {
    4381        9173 :                 IF( LT_32( L_abs( el_fx[i] ), L_abs( ( L_sub( L_abs( el_fx[i] ), 188743680 ) ) ) ) ) // 188743680 =  45 in Q22
    4382             :                 {
    4383             :                     /* el_hat  = 0*/
    4384        6046 :                     IF( EQ_16( bits[i], 3 ) )
    4385             :                     {
    4386             :                         // d1 += 1 - 0.7f * cosf( el[i] * PI_OVER_180 );
    4387        6046 :                         temp = getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) );                         // Q15
    4388        6046 :                         d1_fx = L_add( d1_fx, L_shr( L_sub( ONE_IN_Q30, L_shr( Mpy_32_16_1( 1503238554, temp ), 1 ) ), gb ) ); // 1503238554 = 0.7 in Q31
    4389             :                                                                                                                                //  Q30-gb
    4390             :                     }
    4391             :                     ELSE
    4392             :                     {
    4393             :                         // d1 += 1 - 0.92f * cosf( el[i] * PI_OVER_180 );
    4394           0 :                         temp = getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) );                         // Q15
    4395           0 :                         d1_fx = L_add( d1_fx, L_shr( L_sub( ONE_IN_Q30, L_shr( Mpy_32_16_1( 1975684956, temp ), 1 ) ), gb ) ); // 1975684956 = 0.92 in Q31
    4396             :                         //  Q30-gb
    4397             :                     }
    4398             :                 }
    4399             :                 ELSE
    4400             :                 {
    4401        3127 :                     IF( EQ_16( bits[i], 3 ) )
    4402             :                     {
    4403             :                         // d1 += 1 - sinf( el[i] * PI_OVER_180 ) * 0.7f * sign( el[i] );
    4404        3127 :                         temp = getSineWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) );                                                          // Q15
    4405        3127 :                         d1_fx = L_add( d1_fx, L_shr( L_sub( ONE_IN_Q30, L_shr( Mpy_32_16_1( imult3216( 1503238554, sign_fx( el_fx[i] ) ), temp ), 1 ) ), gb ) ); // 1503238554 = 0.7 in Q31
    4406             :                         //  Q30-gb
    4407             :                     }
    4408             :                     ELSE
    4409             :                     {
    4410             :                         // d1 += 1 - 0.7f * 0.92f * cosf( el[i] * PI_OVER_180 ) - sinf( fabsf( el[i] * PI_OVER_180 ) ) * 0.7f;
    4411           0 :                         temp = getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) );                                                                                // Q15
    4412           0 :                         temp1 = getSineWord16R2( extract_l( L_shr( Mpy_32_16_1( L_abs( el_fx[i] ), 91 ), 7 ) ) );                                                                     // Q15
    4413           0 :                         d1_fx = L_add( d1_fx, L_shr( L_sub( L_sub( ONE_IN_Q30, L_shr( Mpy_32_16_1( 1422493168, temp ), 1 ) ), L_shr( Mpy_32_16_1( 1503238554, temp1 ), 1 ) ), gb ) ); // 1422493168 = 0.92* 0.7 in Q31 ;1503238554 = 0.7 in Q31
    4414             :                         // Q30-gb
    4415             :                     }
    4416             :                 }
    4417             :             }
    4418             :             ELSE
    4419             :             {
    4420        4035 :                 IF( EQ_16( bits[i], 2 ) )
    4421             :                 {
    4422             :                     // d1 += 1 - cosf( el[i] * PI_OVER_180 ) * 0.7f;
    4423        4035 :                     temp = getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) );                         // Q15
    4424        4035 :                     d1_fx = L_add( d1_fx, L_shr( L_sub( ONE_IN_Q30, L_shr( Mpy_32_16_1( 1503238554, temp ), 1 ) ), gb ) ); // 1503238554 = 0.7 in Q31
    4425             :                     // Q31-gb
    4426             :                 }
    4427             :                 ELSE
    4428             :                 {
    4429             :                     // d1 += 1;
    4430           0 :                     d1_fx = L_add( d1_fx, L_shr( ONE_IN_Q30, gb ) );
    4431             :                 }
    4432             :             }
    4433             :             // d2 += 1 - sinf( el_av * PI_OVER_180 ) * sinf( el[i] * PI_OVER_180 ) - cosf( el[i] * PI_OVER_180 ) * cosf( el_av * PI_OVER_180 ) * cos_delta_phi_cb[total_bits - 9];
    4434       13208 :             L_temp = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) ) ); //*91/7 to convert angle in Q22 to radians
    4435             :                                                                                                             // Q15
    4436       13208 :             L_temp1 = L_deposit_h( getSineWord16R2( extract_l( L_shr( Mpy_32_16_1( el_fx[i], 91 ), 7 ) ) ) );
    4437       13208 :             L_temp2 = L_deposit_h( getSineWord16R2( extract_l( L_shr( Mpy_32_16_1( el_av_fx, 91 ), 7 ) ) ) );
    4438       13208 :             L_temp3 = L_deposit_h( getCosWord16R2( extract_l( L_shr( Mpy_32_16_1( el_av_fx, 91 ), 7 ) ) ) );
    4439             :             // temp1f = sinf( el_av * PI_OVER_180 ) * sinf( el[i] * PI_OVER_180 );
    4440             :             // L_temp4 = Mpy_32_32( L_temp2, L_temp1 );
    4441       13208 :             d2_fx = L_add( d2_fx, L_shr( L_sub( L_sub( ONE_IN_Q30, L_shr( Mpy_32_32( L_temp2, L_temp1 ), 1 ) ), L_shr( Mpy_32_32( Mpy_32_32( L_temp, L_temp3 ), cos_delta_phi_cb_fx[total_bits - 9] ), 1 ) ), gb ) ); // Q30-gb
    4442             :         }
    4443             :     }
    4444        3593 :     Word16 Qin = Q22;
    4445        3593 :     move16();
    4446             :     //  var_el = var( el, len );
    4447        3593 :     var_el_fx = var_fx_32in_32out( el_fx, &Qin, len, gb );
    4448        3593 :     Word16 flag = BASOP_Util_Cmp_Mant32Exp( var_el_fx, sub( 31, Qin ), 1300, 31 );
    4449        3593 :     if ( EQ_16( flag, 1 ) )
    4450             :     {
    4451             :         //  d2 = d1 + 0.1f;
    4452         112 :         d2_fx = L_add( d1_fx, L_shr( 214748365, sub( Q31, sub( Q30, gb ) ) ) ); // 214748365 = 0.1f in Q31
    4453             :     }
    4454             : 
    4455        3593 :     *p_d1 = d1_fx;
    4456        3593 :     move32();
    4457        3593 :     *p_d2 = d2_fx;
    4458        3593 :     move32();
    4459        3593 :     *Q_out = sub( Q30, gb );
    4460        3593 :     move16();
    4461        3593 :     return;
    4462             : }
    4463             : 
    4464             : /*-------------------------------------------------------------------*
    4465             :  * write_ec_direction()
    4466             :  *
    4467             :  * write metadata using entropy encoding
    4468             :  *-------------------------------------------------------------------*/
    4469             : /*! r: number of bits written */
    4470        7759 : static ivas_error write_ec_direction_fx(
    4471             :     Word16 *num_bits_written,      /* o  : Number of bits written                          */
    4472             :     BSTR_ENC_HANDLE hMetaData,     /* i  : MASA metadata structure                         */
    4473             :     IVAS_QDIRECTION *qdirection,   /* i  : quantized directional info                      */
    4474             :     const Word16 j_idx,            /* i  : index of subband to encode and write            */
    4475             :     const Word16 len,              /* i  : number of tiles                                 */
    4476             :     const Word16 GR_ord_elevation, /* i  : GR order for elevation encoding                 */
    4477             :     const Word16 GR_ord_azimuth,   /* i  : GR order for azimuth encoding                   */
    4478             :     const Word16 use_context,      /* i  : flag for context usiage in azimuth encoding     */
    4479             :     const Word16 same              /* i  : flag if elevation indexes are the same or not   */
    4480             : )
    4481             : {
    4482             :     Word16 i, nbits, bits_crt, nr_NO_INDEX;
    4483             :     UWord16 data;
    4484             :     Word16 min_val, max_val;
    4485             : 
    4486        7759 :     nr_NO_INDEX = 0;
    4487        7759 :     move16();
    4488        7759 :     nbits = 0;
    4489        7759 :     move16();
    4490             :     /* write elevation */
    4491       38537 :     FOR( i = 0; i < len; i++ )
    4492             :     {
    4493       30778 :         data = qdirection->band_data[j_idx].elevation_index[i];
    4494       30778 :         test();
    4495       30778 :         if ( EQ_32( data, MASA_NO_INDEX ) || ( qdirection->band_data[j_idx].bits_sph_idx[i] == 0 ) )
    4496             :         {
    4497           3 :             nr_NO_INDEX = add( nr_NO_INDEX, 1 );
    4498             :         }
    4499             :     }
    4500             : 
    4501        7759 :     IF( LT_16( nr_NO_INDEX, len ) )
    4502             :     {
    4503        7759 :         IF( EQ_16( same, 1 ) )
    4504             :         {
    4505        6021 :             push_next_indice( hMetaData, 1, 1 );
    4506        6021 :             nbits = add( nbits, 1 );
    4507        6021 :             push_next_indice( hMetaData, qdirection->band_data[j_idx].elevation_index[0], 2 );
    4508        6021 :             nbits = add( nbits, 2 );
    4509             :         }
    4510             :         ELSE
    4511             :         {
    4512        1738 :             push_next_indice( hMetaData, 0, 1 );
    4513        1738 :             nbits = add( nbits, 1 );
    4514             : 
    4515        1738 :             push_next_indice( hMetaData, sub( 1, (Word16) EQ_16( GR_ord_elevation, MASA_GR_ORD_EL ) ), 1 );
    4516        1738 :             nbits = add( nbits, 1 );
    4517             : 
    4518        8690 :             FOR( i = 0; i < len; i++ )
    4519             :             {
    4520        6952 :                 data = qdirection->band_data[j_idx].elevation_index[i];
    4521        6952 :                 IF( LT_32( data, MASA_NO_INDEX ) )
    4522             :                 {
    4523        6949 :                     bits_crt = hMetaData->nb_bits_tot;
    4524        6949 :                     move16();
    4525        6949 :                     ivas_qmetadata_encode_extended_gr_fx( hMetaData, data, qdirection->band_data[j_idx].elevation_m_alphabet[i], GR_ord_elevation );
    4526        6949 :                     nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_crt ) );
    4527             :                 }
    4528             :             }
    4529             :         }
    4530             :     }
    4531             : 
    4532             :     /* write azimuth */
    4533        7759 :     IF( use_context < 0 )
    4534             :     {
    4535        7759 :         IF( EQ_16( use_context, -1 ) )
    4536             :         {
    4537             :             /* regular GR coding */
    4538        2530 :             push_next_indice( hMetaData, 0, 1 );
    4539        2530 :             nbits = add( nbits, 1 );
    4540        2530 :             push_next_indice( hMetaData, sub( 1, (Word16) EQ_16( GR_ord_azimuth, MASA_GR_ORD_AZ ) ), 1 );
    4541        2530 :             nbits = add( nbits, 1 );
    4542             : 
    4543       12392 :             FOR( i = 0; i < len; i++ )
    4544             :             {
    4545        9862 :                 data = qdirection->band_data[j_idx].azimuth_index[i];
    4546        9862 :                 IF( LT_32( data, MASA_NO_INDEX ) )
    4547             :                 {
    4548        9860 :                     bits_crt = hMetaData->nb_bits_tot;
    4549        9860 :                     move16();
    4550        9860 :                     ivas_qmetadata_encode_extended_gr_fx( hMetaData, data, qdirection->band_data[j_idx].azimuth_m_alphabet[i], GR_ord_azimuth );
    4551        9860 :                     nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_crt ) );
    4552             :                 }
    4553             :             }
    4554             :         }
    4555        5229 :         ELSE IF( EQ_16( use_context, -2 ) )
    4556             :         {
    4557             :             /* min removed GR coding */
    4558        5229 :             push_next_indice( hMetaData, 1, 1 );
    4559        5229 :             nbits = add( nbits, 1 );
    4560        5229 :             push_next_indice( hMetaData, sub( 1, (Word16) EQ_16( GR_ord_azimuth, sub( MASA_GR_ORD_AZ, 1 ) ) ), 1 );
    4561        5229 :             nbits = add( nbits, 1 );
    4562             : 
    4563             :             /* find min */
    4564        5229 :             min_val = MASA_NO_INDEX;
    4565        5229 :             move16();
    4566       26145 :             FOR( i = 0; i < len; i++ )
    4567             :             {
    4568       20916 :                 if ( LT_32( qdirection->band_data[j_idx].azimuth_index[i], min_val ) )
    4569             :                 {
    4570        6733 :                     min_val = qdirection->band_data[j_idx].azimuth_index[i];
    4571        6733 :                     move16();
    4572             :                 }
    4573             :             }
    4574             : 
    4575             : 
    4576             :             /* write min*/
    4577        5229 :             bits_crt = hMetaData->nb_bits_tot;
    4578        5229 :             move16();
    4579        5229 :             maximum_s( qdirection->band_data[j_idx].azimuth_m_alphabet, len, &max_val );
    4580        5229 :             ivas_qmetadata_encode_extended_gr_fx( hMetaData, min_val, max_val, MASA_GR_ORD_AZ );
    4581        5229 :             nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_crt ) );
    4582             : 
    4583       26145 :             FOR( i = 0; i < len; i++ )
    4584             :             {
    4585       20916 :                 data = (UWord16) L_sub( qdirection->band_data[j_idx].azimuth_index[i], min_val );
    4586       20916 :                 IF( LT_32( data, sub( MASA_NO_INDEX, min_val ) ) )
    4587             :                 {
    4588       20916 :                     bits_crt = hMetaData->nb_bits_tot;
    4589       20916 :                     move16();
    4590       20916 :                     ivas_qmetadata_encode_extended_gr_fx( hMetaData, data, qdirection->band_data[j_idx].azimuth_m_alphabet[i], GR_ord_azimuth );
    4591       20916 :                     nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_crt ) );
    4592             :                 }
    4593             :             }
    4594             :         }
    4595             :     }
    4596             :     ELSE
    4597             :     {
    4598           0 :         FOR( i = 0; i < len; i++ )
    4599             :         {
    4600           0 :             data = qdirection->band_data[j_idx].azimuth_index[i];
    4601           0 :             IF( LT_32( data, MASA_NO_INDEX ) )
    4602             :             {
    4603           0 :                 SWITCH( qdirection->band_data[j_idx].bits_sph_idx[i] )
    4604             :                 {
    4605           0 :                     case 0:
    4606           0 :                         BREAK;
    4607           0 :                     case 1:
    4608           0 :                         nbits = add( nbits, 1 );
    4609           0 :                         push_next_indice( hMetaData, data, 1 );
    4610           0 :                         BREAK;
    4611           0 :                     case 2:
    4612           0 :                         bits_crt = hMetaData->nb_bits_tot;
    4613           0 :                         move16();
    4614           0 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, data, qdirection->band_data[j_idx].azimuth_m_alphabet[i], MASA_GR_ORD_AZ - 1 );
    4615           0 :                         nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_crt ) );
    4616           0 :                         BREAK;
    4617           0 :                     default:
    4618           0 :                         bits_crt = hMetaData->nb_bits_tot;
    4619           0 :                         move16();
    4620           0 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, data, qdirection->band_data[j_idx].azimuth_m_alphabet[i], MASA_GR_ORD_AZ );
    4621           0 :                         nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_crt ) );
    4622           0 :                         BREAK;
    4623             :                 }
    4624           0 :             }
    4625             :         }
    4626             :     }
    4627             : 
    4628        7759 :     *num_bits_written = nbits;
    4629        7759 :     move16();
    4630        7759 :     return IVAS_ERR_OK;
    4631             : }
    4632             : 
    4633             : /*-----------------------------------------------------------------------*
    4634             :  * Local functions (coherence Q and coding)
    4635             :  *-----------------------------------------------------------------------*/
    4636             : /*! r: index */
    4637       34134 : static UWord64 create_combined_index_fx(
    4638             :     UWord16 *idx_dct,       /* i  : indexes to combine */
    4639             :     const Word16 len,       /* i  : number of indexes */
    4640             :     const Word16 *no_cb_vec /* i  : how many codewords for each position */
    4641             : )
    4642             : {
    4643             :     Word16 i;
    4644             :     UWord64 idx, base;
    4645             : 
    4646       34134 :     base = 1;
    4647       34134 :     move64();
    4648       34134 :     idx = 0;
    4649       34134 :     move64();
    4650      238281 :     FOR( i = 0; i < len; i++ )
    4651             :     {
    4652      204147 :         idx = W_add( idx, base * idx_dct[i] );
    4653      204147 :         base *= no_cb_vec[i];
    4654             :     }
    4655             : 
    4656       34134 :     return idx;
    4657             : }
    4658             : 
    4659             : /*-----------------------------------------------------------------------*
    4660             :  * encoding DCT0 coeffs with joint index
    4661             :  *-----------------------------------------------------------------------*/
    4662             : /*! r: number of bits written */
    4663       23095 : static Word16 encode_coherence_indexesDCT0_fx(
    4664             :     UWord16 *idx_dct,  /* i  : indexes to be encoded                 */
    4665             :     const Word16 len,  /* i  : number of indexes                     */
    4666             :     Word16 *no_cb_vec, /* i  : number of codewords for each position */
    4667             :     BSTR_ENC_HANDLE hMetaData,
    4668             :     const Word16 indice_coherence,
    4669             :     const Word16 nbits,
    4670             :     const Word16 nbits1 )
    4671             : {
    4672             :     Word16 i;
    4673             :     UWord64 idx;
    4674             :     Word16 no_idx16;
    4675             :     Word16 k;
    4676             :     Word16 half_len, j;
    4677             :     UWord64 idx1;
    4678             : 
    4679             :     /* calculate bits for dct0 components with joint encoding */
    4680       23095 :     IF( nbits1 > 0 )
    4681             :     {
    4682         174 :         half_len = shr( len, 1 );
    4683         174 :         idx = create_combined_index_fx( idx_dct, half_len, no_cb_vec );
    4684         174 :         idx1 = create_combined_index_fx( &idx_dct[half_len], half_len, &no_cb_vec[half_len] );
    4685             :     }
    4686             :     ELSE
    4687             :     {
    4688       22921 :         idx = create_combined_index_fx( idx_dct, len, no_cb_vec );
    4689       22921 :         idx1 = 0;
    4690       22921 :         move16();
    4691             :     }
    4692             : 
    4693             :     // if ( nbits % 16 == 0 )
    4694       23095 :     IF( s_and( nbits, 15 ) == 0 )
    4695             :     {
    4696         310 :         no_idx16 = shr( nbits, 4 );
    4697             :     }
    4698             :     ELSE
    4699             :     {
    4700             :         // no_idx16 = (Word16) round_f( ( nbits / 16.0f + 0.5f ) );
    4701       22785 :         no_idx16 = shr_r( add( nbits, ONE_IN_Q3 ), 4 );
    4702             :     }
    4703             : 
    4704       23095 :     k = nbits;
    4705       23095 :     move16();
    4706       23095 :     i = 0;
    4707       23095 :     move16();
    4708       27206 :     FOR( i = 0; i < no_idx16 - 1; i++ )
    4709             :     {
    4710        4111 :         k = sub( k, 16 );
    4711        4111 :         hMetaData->ind_list[indice_coherence + i].value = ( ( idx >> k ) & 65535 ); /* 16 bits */
    4712        4111 :         move16();
    4713             :     }
    4714       23095 :     hMetaData->ind_list[indice_coherence + i].value = ( idx & ( ( 1 << k ) - 1 ) );
    4715       23095 :     move16();
    4716             : 
    4717       23095 :     IF( nbits1 > 0 )
    4718             :     {
    4719             :         // if ( nbits1 % 16 == 0 )
    4720         174 :         IF( s_and( nbits1, 15 ) == 0 )
    4721             :         {
    4722           0 :             no_idx16 = shr( nbits1, 4 );
    4723             :         }
    4724             :         ELSE
    4725             :         {
    4726             :             // no_idx16 = (Word16) round_f( ( nbits1 / 16.0f + 0.5f ) );
    4727         174 :             no_idx16 = shr_r( add( nbits1, ONE_IN_Q3 ), 4 );
    4728             :         }
    4729             : 
    4730         174 :         k = nbits1;
    4731         174 :         move16();
    4732             : 
    4733         348 :         FOR( j = i + 1; j < no_idx16 + i; j++ )
    4734             :         {
    4735         174 :             k = sub( k, 16 );
    4736         174 :             hMetaData->ind_list[indice_coherence + j].value = ( ( idx1 >> k ) & 65535 ); /* 16 bits */
    4737         174 :             move16();
    4738             :         }
    4739         174 :         hMetaData->ind_list[indice_coherence + j].value = ( idx1 & ( ( 1 << k ) - 1 ) );
    4740         174 :         move16();
    4741             :     }
    4742             : 
    4743       23095 :     return add( nbits, nbits1 );
    4744             : }
    4745             : 
    4746             : /*-------------------------------------------------------------------*
    4747             :  * coherence_coding_length()
    4748             :  *
    4749             :  *
    4750             :  *-------------------------------------------------------------------*/
    4751       42720 : static Word16 coherence_coding_length(
    4752             :     const UWord16 *idx_sur_coh_shift,
    4753             :     const UWord8 idx_shift_len,
    4754             :     const Word16 coding_subbands,
    4755             :     const Word16 *no_cv,
    4756             :     UWord16 *mr_idx,
    4757             :     Word16 *no_cv_shift,
    4758             :     Word16 *p_min_idx,
    4759             :     Word16 *GR_ord,
    4760             :     Word16 *nbits_fr,
    4761             :     Word16 *nbits_fr1 )
    4762             : {
    4763             :     Word16 half_coding_subbands;
    4764             :     Word16 j;
    4765             :     Word16 nbits;
    4766             :     UWord64 no_cb;
    4767             :     Word16 min_idx;
    4768             : 
    4769       42720 :     half_coding_subbands = 0;
    4770       42720 :     move16();
    4771             : 
    4772       42720 :     IF( GT_16( sum16_fx( no_cv, coding_subbands ), MASA_COH_LIMIT_2IDX ) )
    4773             :     {
    4774             : 
    4775        2745 :         no_cb = 1;
    4776        2745 :         move16();
    4777        2745 :         half_coding_subbands = shr( coding_subbands, 1 );
    4778        2745 :         move16();
    4779       35042 :         FOR( j = 0; j < half_coding_subbands; j++ )
    4780             :         {
    4781       32297 :             no_cb = no_cb * no_cv[j];
    4782             :         }
    4783             :         //*nbits_fr = (Word16) ceilf( logf( (float) no_cb ) * INV_LOG_2 );
    4784        2745 :         IF( LE_64( no_cb, 1 ) )
    4785             :         {
    4786           0 :             *nbits_fr = 0;
    4787             :         }
    4788             :         ELSE
    4789             :         {
    4790        2745 :             *nbits_fr = sub( 63, W_norm( W_sub( no_cb, 1 ) ) );
    4791             :         }
    4792        2745 :         move16();
    4793        2745 :         no_cb = 1;
    4794        2745 :         move16();
    4795       35166 :         FOR( j = half_coding_subbands; j < coding_subbands; j++ )
    4796             :         {
    4797       32421 :             no_cb = no_cb * no_cv[j];
    4798             :         }
    4799             :         //*nbits_fr1 = (Word16) ceilf( logf( (float) no_cb ) * INV_LOG_2 );
    4800        2745 :         IF( LE_64( no_cb, 1 ) )
    4801             :         {
    4802           0 :             *nbits_fr1 = 0;
    4803             :         }
    4804             :         ELSE
    4805             :         {
    4806        2745 :             *nbits_fr1 = sub( 63, W_norm( W_sub( no_cb, 1 ) ) );
    4807             :         }
    4808        2745 :         move16();
    4809             :     }
    4810             :     ELSE
    4811             :     {
    4812       39975 :         no_cb = 1;
    4813      435931 :         FOR( j = 0; j < coding_subbands; j++ )
    4814             :         {
    4815      395956 :             no_cb = no_cb * no_cv[j];
    4816             :         }
    4817             :         //*nbits_fr = (Word16) ceilf( logf( (float) no_cb ) * INV_LOG_2 );
    4818       39975 :         IF( LE_64( no_cb, 1 ) )
    4819             :         {
    4820         292 :             *nbits_fr = 0;
    4821             :         }
    4822             :         ELSE
    4823             :         {
    4824       39683 :             *nbits_fr = sub( 63, W_norm( W_sub( no_cb, 1 ) ) );
    4825             :         }
    4826       39975 :         move16();
    4827       39975 :         *nbits_fr1 = 0;
    4828       39975 :         move16();
    4829             :     }
    4830             : 
    4831             : 
    4832       42720 :     minimum_s( (const Word16 *) idx_sur_coh_shift, (Word16) idx_shift_len, &min_idx );
    4833      501293 :     FOR( j = 0; j < idx_shift_len; j++ )
    4834             :     {
    4835      458573 :         mr_idx[j] = sub( idx_sur_coh_shift[j], min_idx );
    4836      458573 :         move16();
    4837      458573 :         no_cv_shift[j] = sub( no_cv_shift[j], min_idx );
    4838      458573 :         move16();
    4839             :     }
    4840       42720 :     nbits = add( add( min_idx, 1 ), GR_bits_new_fx( mr_idx, no_cv_shift, idx_shift_len, *GR_ord, 1, GR_ord ) );
    4841       42720 :     *p_min_idx = min_idx;
    4842       42720 :     move16();
    4843             : 
    4844       42720 :     return nbits;
    4845             : }
    4846             : 
    4847             : /*-------------------------------------------------------------------*
    4848             :  * encode_spread_coherence_1sf()
    4849             :  *
    4850             :  * Encoding spread coherence for 1 subframe bands
    4851             :  *-------------------------------------------------------------------*/
    4852             : /*! r: number of bits written */
    4853        8168 : static Word16 encode_spread_coherence_1sf_fx(
    4854             :     IVAS_QMETADATA *q_metadata,    /* i  : quantized metadata                        */
    4855             :     const Word16 idx_d,            /* i  : current direction index                   */
    4856             :     BSTR_ENC_HANDLE hMasaMetaData, /* i/o: metadata bitstream handle                 */
    4857             :     const Word16 hrmasa_flag       /* i  : flag indicating high-rate MASA MD coding  */
    4858             : )
    4859             : {
    4860             :     Word16 i, j, k;
    4861             :     Word16 idx_ER;
    4862             :     Word16 nbits, nbits_fr;
    4863             :     UWord16 idx_sp_coh[MASA_MAXIMUM_CODING_SUBBANDS]; // Q15
    4864             :     UWord16 mr_idx_sp_coh[MASA_MAXIMUM_CODING_SUBBANDS];
    4865             :     Word16 GR_ord, bits_GR;
    4866             :     UWord64 idx, idx1;
    4867             :     Word16 no_idx16;
    4868             :     Word16 no_cv[MASA_MAXIMUM_CODING_SUBBANDS];
    4869             :     IVAS_QDIRECTION *q_direction;
    4870             :     Word16 half_coding_subbands, nbits_fr1, coding_subbands;
    4871             :     UWord16 idx_sp_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS];
    4872             :     UWord8 idx_shift;
    4873        8168 :     Word16 max_val = 0, nbits_max;
    4874        8168 :     move16();
    4875             :     Word16 extra_cv;
    4876             :     Word16 no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx;
    4877             : 
    4878        8168 :     coding_subbands = q_metadata->q_direction[idx_d].cfg.nbands;
    4879        8168 :     move16();
    4880        8168 :     q_direction = &( q_metadata->q_direction[idx_d] );
    4881        8168 :     nbits = 0;
    4882        8168 :     move16();
    4883        8168 :     GR_ord = 1;
    4884        8168 :     move16();
    4885        8168 :     idx_shift = 0;
    4886        8168 :     move16();
    4887             : 
    4888             :     /* number of codevectors added dependent on number of subbands */
    4889             :     // extra_cv = coding_subbands / MASA_FACTOR_CV_COH;
    4890        8168 :     Word16 tmp = 0;
    4891        8168 :     move16();
    4892        8168 :     extra_cv = -1;
    4893        8168 :     move16();
    4894       21610 :     WHILE( ( tmp <= coding_subbands ) )
    4895             :     {
    4896       13442 :         tmp = add( tmp, 6 );
    4897       13442 :         extra_cv = add( extra_cv, 1 );
    4898             :     }
    4899       69576 :     FOR( j = 0; j < coding_subbands; j++ )
    4900             :     {
    4901       61408 :         IF( hrmasa_flag )
    4902             :         {
    4903           0 :             idx_ER = add( sub( 7, shr( q_direction->band_data[j].energy_ratio_index_mod[0], 1 ) ), extra_cv );
    4904             :         }
    4905             :         ELSE
    4906             :         {
    4907       61408 :             idx_ER = add( sub( 7, q_direction->band_data[j].energy_ratio_index_mod[0] ), extra_cv );
    4908             :         }
    4909             : 
    4910       61408 :         IF( idx_ER > 0 )
    4911             :         {
    4912             :             // idx_sp_coh[j] = (uint16_t) roundf( q_direction->coherence_band_data[j].spread_coherence[0] / ( 255.0f / (float) idx_ER ) );
    4913       48297 :             idx_sp_coh[j] = extract_l( Mpy_32_32_r( imult1616( q_direction->coherence_band_data[j].spread_coherence[0], idx_ER ), 8421505 /* 1/255.f in Q31 */ ) );
    4914       48297 :             move16();
    4915             :             // q_direction->coherence_band_data[j].spread_coherence[0] = (UWord8) roundf( idx_sp_coh[j] * ( 255.0f / (float) idx_ER ) );
    4916       48297 :             IF( idx_sp_coh[j] )
    4917             :             {
    4918       22753 :                 q_direction->coherence_band_data[j].spread_coherence[0] = (UWord8) idiv1616( imult1616( idx_sp_coh[j], 255 ), idx_ER );
    4919       22753 :                 move16();
    4920             :             }
    4921             :             ELSE
    4922             :             {
    4923       25544 :                 q_direction->coherence_band_data[j].spread_coherence[0] = 0;
    4924       25544 :                 move16();
    4925             :             }
    4926             :         }
    4927             :         ELSE
    4928             :         {
    4929       13111 :             idx_sp_coh[j] = 0;
    4930       13111 :             move16();
    4931       13111 :             q_direction->coherence_band_data[j].spread_coherence[0] = 0;
    4932       13111 :             move16();
    4933             :         }
    4934       61408 :         no_cv[j] = add( idx_ER, 1 );
    4935       61408 :         move16();
    4936             : 
    4937       61408 :         no_cv_shift[idx_shift] = no_cv[j];
    4938       61408 :         move16();
    4939       61408 :         idx_sp_coh_shift[idx_shift++] = idx_sp_coh[j];
    4940       61408 :         move16();
    4941             :     }
    4942             : 
    4943        8168 :     IF( EQ_16( sum16_fx( no_cv, coding_subbands ), coding_subbands ) )
    4944             :     {
    4945         621 :         return 0;
    4946             :     }
    4947             : 
    4948        7547 :     nbits_max = 0;
    4949        7547 :     move16();
    4950        7547 :     IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) )
    4951             :     {
    4952        1962 :         j = maximum_s( (Word16 *) idx_sp_coh, coding_subbands, &max_val );
    4953       33582 :         FOR( j = 0; j < coding_subbands; j++ )
    4954             :         {
    4955       31620 :             IF( GT_16( no_cv[j], add( max_val, 1 ) ) )
    4956             :             {
    4957       30477 :                 no_cv[j] = add( max_val, 1 );
    4958       30477 :                 move16();
    4959             :             }
    4960             :         }
    4961        1962 :         nbits_max = add( sub( MASA_MAX_NO_CV_SUR_COH, max_val ), extra_cv );
    4962             :     }
    4963             : 
    4964        7547 :     nbits = coherence_coding_length( idx_sp_coh_shift, idx_shift, coding_subbands, no_cv,
    4965             :                                      mr_idx_sp_coh, no_cv_shift, &min_idx, &GR_ord, &nbits_fr, &nbits_fr1 );
    4966        7547 :     half_coding_subbands = 0;
    4967        7547 :     move16();
    4968        7547 :     idx1 = 0;
    4969        7547 :     move16();
    4970             : 
    4971        7547 :     IF( LT_16( add( add( nbits_fr, nbits_fr1 ), nbits_max ), nbits ) )
    4972             :     {
    4973             :         /* write flag*/
    4974        4976 :         push_next_indice( hMasaMetaData, 0, 1 );
    4975             : 
    4976             :         /* create combined index */
    4977        4976 :         nbits = add( add( nbits_fr, nbits_fr1 ), 1 );
    4978             : 
    4979        4976 :         IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) )
    4980             :         {
    4981             :             /* write max value*/
    4982         179 :             bits_GR = hMasaMetaData->nb_bits_tot;
    4983         179 :             move16();
    4984         179 :             ivas_qmetadata_encode_extended_gr_fx( hMasaMetaData, add( sub( sub( MASA_MAX_NO_CV_SUR_COH, max_val ), 1 ), extra_cv ), add( MASA_MAX_NO_CV_SUR_COH, extra_cv ), 0 );
    4985         179 :             nbits = add( nbits, sub( hMasaMetaData->nb_bits_tot, bits_GR ) );
    4986             :         }
    4987             : 
    4988        4976 :         IF( nbits_fr1 > 0 )
    4989             :         {
    4990          24 :             half_coding_subbands = shr( coding_subbands, 1 );
    4991          24 :             idx = create_combined_index_fx( idx_sp_coh, half_coding_subbands, no_cv );
    4992          24 :             idx1 = create_combined_index_fx( &idx_sp_coh[half_coding_subbands], half_coding_subbands, &no_cv[half_coding_subbands] );
    4993             :         }
    4994             :         ELSE
    4995             :         {
    4996        4952 :             idx = create_combined_index_fx( idx_sp_coh, coding_subbands, no_cv );
    4997             :         }
    4998             : 
    4999             :         // if ( nbits_fr % 16 == 0 )
    5000        4976 :         IF( s_and( nbits_fr, 15 ) == 0 )
    5001             :         {
    5002          88 :             no_idx16 = shr( nbits_fr, 4 );
    5003             :         }
    5004             :         ELSE
    5005             :         {
    5006             :             // no_idx16 = (Word16) round_f( ( nbits_fr / 16.0f + 0.5f ) );
    5007        4888 :             no_idx16 = shr_r( add( nbits_fr, ONE_IN_Q3 ), 4 );
    5008             :         }
    5009             : 
    5010             :         /* write combined index */
    5011        4976 :         k = nbits_fr;
    5012        4976 :         move16();
    5013        5093 :         FOR( i = 0; i < no_idx16 - 1; i++ )
    5014             :         {
    5015         117 :             k = sub( k, 16 );
    5016         117 :             push_next_indice( hMasaMetaData, ( ( idx >> k ) & 65535 ), 16 ); /* 16 bits */
    5017             :         }
    5018             : 
    5019        4976 :         push_next_indice( hMasaMetaData, ( idx & ( ( 1 << k ) - 1 ) ), k );
    5020             : 
    5021        4976 :         IF( nbits_fr1 > 0 )
    5022             :         {
    5023             :             // if ( nbits_fr1 % 16 == 0 )
    5024          24 :             IF( s_and( nbits_fr1, 15 ) == 0 )
    5025             :             {
    5026           0 :                 no_idx16 = shr( nbits_fr1, 4 );
    5027             :             }
    5028             :             ELSE
    5029             :             {
    5030             :                 // no_idx16 = (Word16) round_f( ( nbits_fr1 / 16.0f + 0.5f ) );
    5031          24 :                 no_idx16 = shr_r( add( nbits_fr1, ONE_IN_Q3 ), 4 );
    5032             :             }
    5033             : 
    5034          24 :             assert( no_idx16 <= 4 );
    5035             : 
    5036          24 :             k = nbits_fr1;
    5037          24 :             move16();
    5038          56 :             FOR( i = 0; i < no_idx16 - 1; i++ )
    5039             :             {
    5040          32 :                 k = sub( k, 16 );
    5041          32 :                 push_next_indice( hMasaMetaData, ( ( idx1 >> k ) & 65535 ), 16 ); /* 16 bits */
    5042             :             }
    5043          24 :             push_next_indice( hMasaMetaData, ( idx1 & ( ( 1 << k ) - 1 ) ), k );
    5044             :         }
    5045             :     }
    5046             :     ELSE
    5047             :     {
    5048             :         /* write flag */
    5049        2571 :         nbits = 1;
    5050        2571 :         move16();
    5051             : 
    5052             :         /* write flag*/
    5053        2571 :         push_next_indice( hMasaMetaData, 1, 1 );
    5054             : 
    5055             :         /* write GR_ord */
    5056        2571 :         push_next_indice( hMasaMetaData, GR_ord, 1 );
    5057        2571 :         nbits = add( nbits, 1 );
    5058             : 
    5059             :         /* write the min */
    5060        2571 :         bits_GR = hMasaMetaData->nb_bits_tot;
    5061        2571 :         move16();
    5062        2571 :         ivas_qmetadata_encode_extended_gr_fx( hMasaMetaData, min_idx, add( MASA_MAX_NO_CV_SUR_COH, extra_cv ), 0 );
    5063        2571 :         nbits = add( nbits, sub( hMasaMetaData->nb_bits_tot, bits_GR ) );
    5064             : 
    5065             :         /* write GR data */
    5066       35032 :         FOR( j = 0; j < idx_shift; j++ )
    5067             :         {
    5068       32461 :             bits_GR = hMasaMetaData->nb_bits_tot;
    5069       32461 :             move16();
    5070       32461 :             ivas_qmetadata_encode_extended_gr_fx( hMasaMetaData, mr_idx_sp_coh[j], no_cv_shift[j], GR_ord );
    5071       32461 :             nbits = add( nbits, sub( hMasaMetaData->nb_bits_tot, bits_GR ) );
    5072             :         }
    5073             :     }
    5074             : 
    5075        7547 :     return nbits;
    5076             : }
    5077             : 
    5078             : /*-------------------------------------------------------------------*
    5079             :  * encode_surround_coherence()
    5080             :  *
    5081             :  * encoding surround coherence
    5082             :  *-------------------------------------------------------------------*/
    5083             : 
    5084             : /*! r: number of bits written */
    5085       26519 : static Word16 encode_surround_coherence_fx(
    5086             :     IVAS_QMETADATA *hQMetaData, /* i  : quantized metadata            */
    5087             :     BSTR_ENC_HANDLE hMetaData   /* i/o: metadata bitstream handle     */
    5088             : )
    5089             : {
    5090             :     Word16 i, j, k;
    5091             :     Word16 idx_ER, idx16;
    5092             :     Word16 nbits, nbits_fr;
    5093             :     UWord16 idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS];
    5094             :     UWord16 mr_idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS];
    5095             :     Word16 GR_ord, bits_GR;
    5096             :     UWord64 idx, idx1;
    5097             :     Word16 no_idx16;
    5098             :     Word16 no_cv[MASA_MAXIMUM_CODING_SUBBANDS];
    5099             :     Word32 error_ratio_surr; // Q30
    5100             :     IVAS_QDIRECTION *q_direction;
    5101             :     Word16 half_coding_subbands, nbits_fr1, coding_subbands;
    5102             :     Word16 all_coherence_zero;
    5103             :     UWord16 idx_sur_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS];
    5104             :     UWord8 idx_shift;
    5105       26519 :     Word16 max_val = 0, nbits_max;
    5106       26519 :     move16();
    5107             :     Word16 no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx;
    5108             : 
    5109       26519 :     coding_subbands = hQMetaData->q_direction[0].cfg.nbands;
    5110       26519 :     move16();
    5111       26519 :     all_coherence_zero = hQMetaData->all_coherence_zero;
    5112       26519 :     move16();
    5113       26519 :     q_direction = &( hQMetaData->q_direction[0] );
    5114       26519 :     nbits = 0;
    5115       26519 :     move16();
    5116             : 
    5117       26519 :     IF( EQ_16( all_coherence_zero, 1 ) )
    5118             :     {
    5119           0 :         nbits = 0;
    5120           0 :         move16();
    5121             :     }
    5122             :     ELSE
    5123             :     {
    5124       26519 :         GR_ord = 1;
    5125       26519 :         move16();
    5126       26519 :         k = 0;
    5127       26519 :         move16();
    5128       26519 :         idx_shift = 0;
    5129       26519 :         move16();
    5130      221629 :         FOR( j = 0; j < coding_subbands; j++ )
    5131             :         {
    5132      195110 :             IF( EQ_16( hQMetaData->no_directions, 2 ) )
    5133             :             {
    5134       39552 :                 k = add( k, hQMetaData->twoDirBands[j] );
    5135       39552 :                 idx16 = s_max( sub( k, 1 ), 0 );
    5136       39552 :                 error_ratio_surr = W_sat_l( W_sub( W_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ), W_mult0_32_32( q_direction[1].band_data[idx16].energy_ratio_fx[0], hQMetaData->twoDirBands[j] ) ) ); // Q30
    5137             :             }
    5138             :             ELSE
    5139             :             {
    5140      155558 :                 error_ratio_surr = L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[0] ); // Q30
    5141             :             }
    5142             : 
    5143      195110 :             IF( error_ratio_surr <= 0 )
    5144             :             {
    5145         457 :                 error_ratio_surr = 0;
    5146         457 :                 move16();
    5147         457 :                 idx_sur_coh[j] = 0;
    5148         457 :                 move16();
    5149         457 :                 no_cv[j] = 1;
    5150         457 :                 move16();
    5151         457 :                 hQMetaData->surcoh_band_data[j].surround_coherence[0] = 0; /* sur_coherence_cb_masa[idx_cb_sur_coh_masa[DIRAC_DIFFUSE_LEVELS - 1] * MASA_MAX_NO_CV_SUR_COH]; */
    5152         457 :                 move16();
    5153             :             }
    5154             :             ELSE
    5155             :             {
    5156      194653 :                 idx_ER = masa_sq_fx( error_ratio_surr, diffuseness_thresholds_fx, DIRAC_DIFFUSE_LEVELS );
    5157             : 
    5158      389306 :                 idx_sur_coh[j] = squant_int_fx( hQMetaData->surcoh_band_data[j].surround_coherence[0], &hQMetaData->surcoh_band_data[j].surround_coherence[0],
    5159      194653 :                                                 &sur_coherence_cb_masa[idx_cb_sur_coh_masa[idx_ER] * MASA_MAX_NO_CV_SUR_COH], add( idx_cb_sur_coh_masa[idx_ER], 2 ) );
    5160      194653 :                 move16();
    5161             : 
    5162      194653 :                 no_cv[j] = add( idx_cb_sur_coh_masa[idx_ER], 2 );
    5163      194653 :                 move16();
    5164      194653 :                 no_cv_shift[idx_shift] = no_cv[j];
    5165      194653 :                 move16();
    5166      194653 :                 idx_sur_coh_shift[idx_shift++] = idx_sur_coh[j];
    5167      194653 :                 move16();
    5168             :             }
    5169             :         }
    5170             : 
    5171       26519 :         IF( EQ_16( sum16_fx( no_cv, coding_subbands ), coding_subbands ) )
    5172             :         {
    5173           0 :             return 0;
    5174             :         }
    5175             : 
    5176       26519 :         nbits_max = 0;
    5177       26519 :         move16();
    5178       26519 :         IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) )
    5179             :         {
    5180        4855 :             j = maximum_s( (Word16 *) idx_sur_coh, coding_subbands, &max_val );
    5181       89707 :             FOR( j = 0; j < coding_subbands; j++ )
    5182             :             {
    5183       84852 :                 IF( GT_16( no_cv[j], add( max_val, 1 ) ) )
    5184             :                 {
    5185       70940 :                     no_cv[j] = add( max_val, 1 );
    5186       70940 :                     move16();
    5187             :                 }
    5188             :             }
    5189        4855 :             nbits_max = sub( MASA_MAX_NO_CV_SUR_COH, max_val ); /* encoded with GR0 as max_no_vals - no_vals*/
    5190             :         }
    5191             : 
    5192       26519 :         nbits = coherence_coding_length( idx_sur_coh_shift, idx_shift, coding_subbands, no_cv,
    5193             :                                          mr_idx_sur_coh, no_cv_shift, &min_idx, &GR_ord, &nbits_fr, &nbits_fr1 );
    5194       26519 :         half_coding_subbands = shr( coding_subbands, 1 );
    5195       26519 :         idx1 = 0;
    5196       26519 :         move16();
    5197             : 
    5198             :         /* should check how to encode the average - check distribution */
    5199       26519 :         IF( LT_16( add( add( nbits_fr, nbits_fr1 ), nbits_max ), nbits ) )
    5200             :         {
    5201             :             /* write flag*/
    5202        5580 :             push_next_indice( hMetaData, 0, 1 );
    5203             : 
    5204             :             /* create combined index */
    5205        5580 :             nbits = add( add( nbits_fr, nbits_fr1 ), 1 );
    5206        5580 :             IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) )
    5207             :             {
    5208             :                 /* write max value*/
    5209         321 :                 bits_GR = hMetaData->nb_bits_tot;
    5210         321 :                 move16();
    5211         321 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( MASA_MAX_NO_CV_SUR_COH - 1, max_val ), MASA_MAX_NO_CV_SUR_COH, 0 );
    5212         321 :                 nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) );
    5213             :             }
    5214             : 
    5215        5580 :             IF( nbits_fr1 > 0 )
    5216             :             {
    5217          40 :                 idx = create_combined_index_fx( idx_sur_coh, half_coding_subbands, no_cv );
    5218          40 :                 idx1 = create_combined_index_fx( &idx_sur_coh[half_coding_subbands], half_coding_subbands, &no_cv[half_coding_subbands] );
    5219             :             }
    5220             :             ELSE
    5221             :             {
    5222        5540 :                 idx = create_combined_index_fx( idx_sur_coh, coding_subbands, no_cv );
    5223             :             }
    5224             : 
    5225             :             // if ( nbits_fr % 16 == 0 )
    5226        5580 :             IF( s_and( nbits_fr, 15 ) == 0 )
    5227             :             {
    5228         207 :                 no_idx16 = shr( nbits_fr, 4 );
    5229             :             }
    5230             :             ELSE
    5231             :             {
    5232             :                 // no_idx16 = (Word16) round_f( ( nbits_fr / 16.0f + 0.5f ) );
    5233        5373 :                 no_idx16 = shr_r( add( nbits_fr, ONE_IN_Q3 ), 4 );
    5234             :             }
    5235             : 
    5236             :             /* write combined index */
    5237        5580 :             k = nbits_fr;
    5238        5580 :             move16();
    5239        5739 :             FOR( i = 0; i < no_idx16 - 1; i++ )
    5240             :             {
    5241         159 :                 k = sub( k, 16 );
    5242         159 :                 push_next_indice( hMetaData, ( ( idx >> k ) & 65535 ), 16 ); /* 16 bits */
    5243             :             }
    5244             : 
    5245        5580 :             push_next_indice( hMetaData, ( idx & ( ( 1 << k ) - 1 ) ), k );
    5246             : 
    5247        5580 :             IF( nbits_fr1 > 0 )
    5248             :             {
    5249             :                 // if ( nbits_fr1 % 16 == 0 )
    5250          40 :                 IF( s_and( nbits_fr1, 15 ) == 0 )
    5251             :                 {
    5252           0 :                     no_idx16 = shr( nbits_fr1, 4 );
    5253             :                 }
    5254             :                 ELSE
    5255             :                 {
    5256             :                     // no_idx16 = (Word16) round_f( ( nbits_fr1 / 16.0f + 0.5f ) );
    5257          40 :                     no_idx16 = shr_r( add( nbits_fr1, ONE_IN_Q3 ), 4 );
    5258             :                 }
    5259             : 
    5260          40 :                 assert( no_idx16 <= 4 );
    5261             : 
    5262          40 :                 k = nbits_fr1;
    5263          40 :                 move16();
    5264         106 :                 FOR( i = 0; i < no_idx16 - 1; i++ )
    5265             :                 {
    5266          66 :                     k = sub( k, 16 );
    5267          66 :                     push_next_indice( hMetaData, ( ( idx1 >> k ) & 65535 ), 16 ); /* 16 bits */
    5268             :                 }
    5269             : 
    5270          40 :                 push_next_indice( hMetaData, ( idx1 & ( ( 1 << k ) - 1 ) ), k );
    5271             :             }
    5272             :         }
    5273             :         ELSE
    5274             :         {
    5275             :             /* write flag */
    5276       20939 :             nbits = 1;
    5277       20939 :             move16();
    5278             : 
    5279             :             /* write flag*/
    5280       20939 :             push_next_indice( hMetaData, 1, 1 );
    5281             : 
    5282             :             /* write GR_ord */
    5283       20939 :             push_next_indice( hMetaData, GR_ord, 1 );
    5284       20939 :             nbits = add( nbits, 1 );
    5285             : 
    5286             :             /* write the min */
    5287       20939 :             bits_GR = hMetaData->nb_bits_tot;
    5288       20939 :             move16();
    5289       20939 :             ivas_qmetadata_encode_extended_gr_fx( hMetaData, min_idx, MASA_MAX_NO_CV_SUR_COH, 0 );
    5290       20939 :             nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) );
    5291             : 
    5292             :             /* write GR data */
    5293      189695 :             FOR( j = 0; j < idx_shift; j++ )
    5294             :             {
    5295      168756 :                 bits_GR = hMetaData->nb_bits_tot;
    5296      168756 :                 move16();
    5297             : 
    5298      168756 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, mr_idx_sur_coh[j], no_cv_shift[j], GR_ord );
    5299             : 
    5300      168756 :                 nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) );
    5301             :             }
    5302             :         }
    5303             :     }
    5304             : 
    5305       26519 :     return nbits;
    5306             : }
    5307             : 
    5308        2276 : static Word16 encode_surround_coherence_hr_fx(
    5309             :     IVAS_QMETADATA *hQMetaData, /* i  : quantized metadata            */
    5310             :     BSTR_ENC_HANDLE hMetaData   /* i/o: metadata bitstream handle     */
    5311             : )
    5312             : {
    5313             :     Word16 i, j, k, sf;
    5314             :     Word16 nbits, nbits_fr, nbits_sf;
    5315             :     UWord16 idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS];
    5316             :     UWord16 mr_idx_sur_coh[MASA_MAXIMUM_CODING_SUBBANDS];
    5317             :     Word16 GR_ord, bits_GR;
    5318             :     UWord64 idx, idx1;
    5319             :     Word16 no_idx16;
    5320             :     Word16 no_cv[MASA_MAXIMUM_CODING_SUBBANDS];
    5321             :     Word32 error_ratio_surr; // Q30
    5322             :     IVAS_QDIRECTION *q_direction;
    5323             :     Word16 half_coding_subbands, nbits_fr1, coding_subbands;
    5324             :     Word16 all_coherence_zero;
    5325             :     UWord16 idx_sur_coh_shift[MASA_MAXIMUM_CODING_SUBBANDS];
    5326             :     UWord8 idx_shift;
    5327        2276 :     Word16 max_val = 0, nbits_max;
    5328             :     Word16 no_cv_shift[MASA_MAXIMUM_CODING_SUBBANDS], min_idx;
    5329             :     Word16 idx16;
    5330        2276 :     move16();
    5331             : 
    5332        2276 :     coding_subbands = hQMetaData->q_direction[0].cfg.nbands;
    5333        2276 :     all_coherence_zero = hQMetaData->all_coherence_zero;
    5334        2276 :     q_direction = &( hQMetaData->q_direction[0] );
    5335        2276 :     nbits = 0;
    5336        2276 :     move16();
    5337        2276 :     move16();
    5338        2276 :     move16();
    5339             : 
    5340        2276 :     IF( EQ_16( all_coherence_zero, 1 ) )
    5341             :     {
    5342           0 :         nbits = 0;
    5343           0 :         move16();
    5344             :     }
    5345             :     ELSE
    5346             :     {
    5347       10930 :         FOR( sf = 0; sf < hQMetaData->q_direction[0].cfg.nblocks; sf++ )
    5348             :         {
    5349        8654 :             GR_ord = 1;
    5350        8654 :             k = 0;
    5351        8654 :             idx_shift = 0;
    5352        8654 :             move16();
    5353        8654 :             move16();
    5354        8654 :             move16();
    5355      215600 :             FOR( j = 0; j < coding_subbands; j++ )
    5356             :             {
    5357      206946 :                 IF( EQ_16( hQMetaData->no_directions, 2 ) )
    5358             :                 {
    5359      109026 :                     k = add( k, hQMetaData->twoDirBands[j] );
    5360      109026 :                     idx16 = s_max( sub( k, 1 ), 0 );
    5361      109026 :                     error_ratio_surr = L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[sf] ); // Q30
    5362      109026 :                     IF( hQMetaData->twoDirBands[j] )
    5363             :                     {
    5364       64416 :                         error_ratio_surr = L_sub( error_ratio_surr, q_direction[1].band_data[idx16].energy_ratio_fx[sf] ); // Q30
    5365             :                     }
    5366             :                 }
    5367             :                 ELSE
    5368             :                 {
    5369       97920 :                     error_ratio_surr = L_sub( ONE_IN_Q30, q_direction[0].band_data[j].energy_ratio_fx[sf] ); // Q30
    5370             :                 }
    5371             : 
    5372             :                 /* if ( error_ratio_surr <= 0 ) Restricting precision to 7 decimal places */
    5373      206946 :                 IF( LE_32( error_ratio_surr, 107 /* 1e-7 in Q30 */ ) )
    5374             :                 {
    5375        1644 :                     error_ratio_surr = 0;
    5376        1644 :                     idx_sur_coh[j] = 0;
    5377        1644 :                     no_cv[j] = 1;
    5378        1644 :                     hQMetaData->surcoh_band_data[j].surround_coherence[sf] = 0; /* sur_coherence_cb_masa[idx_cb_sur_coh_masa[DIRAC_DIFFUSE_LEVELS - 1] * MASA_MAX_NO_CV_SUR_COH]; */
    5379        1644 :                     move32();
    5380        1644 :                     move16();
    5381        1644 :                     move16();
    5382        1644 :                     move16();
    5383             :                 }
    5384             :                 ELSE
    5385             :                 {
    5386      410604 :                     idx_sur_coh[j] = squant_int_fx( hQMetaData->surcoh_band_data[j].surround_coherence[sf], &hQMetaData->surcoh_band_data[j].surround_coherence[sf],
    5387      205302 :                                                     &sur_coherence_cb_masa[idx_cb_sur_coh_masa[7] * MASA_MAX_NO_CV_SUR_COH], idx_cb_sur_coh_masa[7] + 2 );
    5388      205302 :                     no_cv[j] = add( idx_cb_sur_coh_masa[7], 2 );
    5389      205302 :                     no_cv_shift[idx_shift] = no_cv[j];
    5390      205302 :                     idx_sur_coh_shift[idx_shift++] = idx_sur_coh[j];
    5391      205302 :                     move16();
    5392      205302 :                     move16();
    5393      205302 :                     move16();
    5394      205302 :                     move16();
    5395             :                 }
    5396             :             }
    5397             : 
    5398        8654 :             IF( NE_16( sum16_fx( no_cv, coding_subbands ), coding_subbands ) )
    5399             :             {
    5400        8654 :                 nbits_max = 0;
    5401        8654 :                 move16();
    5402        8654 :                 IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) )
    5403             :                 {
    5404        8654 :                     j = maximum_s( (Word16 *) idx_sur_coh, coding_subbands, &max_val );
    5405      215600 :                     FOR( j = 0; j < coding_subbands; j++ )
    5406             :                     {
    5407      206946 :                         IF( GT_16( no_cv[j], add( max_val, 1 ) ) )
    5408             :                         {
    5409      205302 :                             no_cv[j] = add( max_val, 1 );
    5410      205302 :                             move16();
    5411             :                         }
    5412             :                     }
    5413        8654 :                     nbits_max = sub( MASA_MAX_NO_CV_SUR_COH, max_val ); /* encoded with GR0 as max_no_vals - no_vals*/
    5414             :                 }
    5415        8654 :                 IF( max_val == 0 )
    5416             :                 {
    5417          74 :                     FOR( j = 0; j < coding_subbands; j++ )
    5418             :                     {
    5419          71 :                         hQMetaData->surcoh_band_data[j].surround_coherence[sf] = 0;
    5420          71 :                         move16();
    5421             :                     }
    5422             :                 }
    5423        8654 :                 nbits_sf = coherence_coding_length( idx_sur_coh_shift, idx_shift, coding_subbands, no_cv,
    5424             :                                                     mr_idx_sur_coh, no_cv_shift, &min_idx, &GR_ord, &nbits_fr, &nbits_fr1 );
    5425        8654 :                 half_coding_subbands = shr( coding_subbands, 1 );
    5426        8654 :                 idx1 = 0;
    5427        8654 :                 move16();
    5428             : 
    5429             :                 /* should check how to encode the average - check distribution */
    5430        8654 :                 IF( LT_16( add( add( nbits_fr, nbits_fr1 ), nbits_max ), nbits_sf ) )
    5431             :                 {
    5432             :                     /* write flag*/
    5433         177 :                     push_next_indice( hMetaData, 0, 1 );
    5434             : 
    5435             :                     /* create combined index */
    5436         177 :                     nbits = add( nbits, add( nbits_fr, add( nbits_fr1, 1 ) ) );
    5437         177 :                     IF( GT_16( coding_subbands, MASA_LIMIT_NO_BANDS_SUR_COH ) )
    5438             :                     {
    5439             :                         /* write max value*/
    5440         177 :                         bits_GR = hMetaData->nb_bits_tot;
    5441         177 :                         move16();
    5442         177 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, sub( MASA_MAX_NO_CV_SUR_COH - 1, max_val ), MASA_MAX_NO_CV_SUR_COH, 0 );
    5443         177 :                         nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) );
    5444             :                     }
    5445             : 
    5446         177 :                     IF( nbits_fr1 > 0 )
    5447             :                     {
    5448          68 :                         idx = create_combined_index_fx( idx_sur_coh, half_coding_subbands, no_cv );
    5449          68 :                         idx1 = create_combined_index_fx( &idx_sur_coh[half_coding_subbands], half_coding_subbands, &no_cv[half_coding_subbands] );
    5450             :                     }
    5451             :                     ELSE
    5452             :                     {
    5453         109 :                         idx = create_combined_index_fx( idx_sur_coh, coding_subbands, no_cv );
    5454             :                     }
    5455             : 
    5456         177 :                     IF( nbits_fr % 16 == 0 )
    5457             :                     {
    5458          23 :                         no_idx16 = shr( nbits_fr, 4 );
    5459             :                     }
    5460             :                     ELSE
    5461             :                     {
    5462         154 :                         no_idx16 = add( shr( nbits_fr, 4 ), 1 );
    5463             :                     }
    5464             : 
    5465             :                     /* write combined index */
    5466         177 :                     k = nbits_fr;
    5467         177 :                     move16();
    5468         376 :                     FOR( i = 0; i < no_idx16 - 1; i++ )
    5469             :                     {
    5470         199 :                         k = sub( k, 16 );
    5471         199 :                         push_next_indice( hMetaData, ( ( idx >> k ) & 65535 ), 16 ); /* 16 bits */
    5472             :                     }
    5473             : 
    5474         177 :                     push_next_indice( hMetaData, ( idx & ( ( 1 << k ) - 1 ) ), k );
    5475             : 
    5476         177 :                     IF( nbits_fr1 > 0 )
    5477             :                     {
    5478          68 :                         IF( nbits_fr1 % 16 == 0 )
    5479             :                         {
    5480          34 :                             no_idx16 = shr( nbits_fr1, 4 );
    5481             :                         }
    5482             :                         ELSE
    5483             :                         {
    5484          34 :                             no_idx16 = add( shr( nbits_fr1, 4 ), 1 );
    5485             :                         }
    5486             : 
    5487          68 :                         assert( no_idx16 <= 4 );
    5488             : 
    5489          68 :                         k = nbits_fr1;
    5490          68 :                         move16();
    5491         163 :                         FOR( i = 0; i < no_idx16 - 1; i++ )
    5492             :                         {
    5493          95 :                             k = sub( k, 16 );
    5494          95 :                             push_next_indice( hMetaData, ( ( idx1 >> k ) & 65535 ), 16 ); /* 16 bits */
    5495             :                         }
    5496             : 
    5497          68 :                         push_next_indice( hMetaData, ( idx1 & ( ( 1 << k ) - 1 ) ), k );
    5498             :                     }
    5499             :                 }
    5500             :                 ELSE
    5501             :                 {
    5502             :                     /* write flag */
    5503        8477 :                     nbits = add( nbits, 1 );
    5504             : 
    5505             :                     /* write flag*/
    5506        8477 :                     push_next_indice( hMetaData, 1, 1 );
    5507             : 
    5508             :                     /* write GR_ord */
    5509        8477 :                     push_next_indice( hMetaData, GR_ord, 1 );
    5510        8477 :                     nbits = add( nbits, 1 );
    5511             : 
    5512             :                     /* write the min */
    5513        8477 :                     bits_GR = hMetaData->nb_bits_tot;
    5514        8477 :                     move16();
    5515        8477 :                     ivas_qmetadata_encode_extended_gr_fx( hMetaData, min_idx, MASA_MAX_NO_CV_SUR_COH, 0 );
    5516        8477 :                     nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) );
    5517             : 
    5518             :                     /* write GR data */
    5519      209609 :                     FOR( j = 0; j < idx_shift; j++ )
    5520             :                     {
    5521      201132 :                         bits_GR = hMetaData->nb_bits_tot;
    5522      201132 :                         move16();
    5523             : 
    5524      201132 :                         ivas_qmetadata_encode_extended_gr_fx( hMetaData, mr_idx_sur_coh[j], no_cv_shift[j], GR_ord );
    5525             : 
    5526      201132 :                         nbits = add( nbits, sub( hMetaData->nb_bits_tot, bits_GR ) );
    5527             :                     }
    5528             :                 }
    5529             :             }
    5530             :         }
    5531             :     }
    5532             : 
    5533        2276 :     return nbits;
    5534             : }
    5535             : 
    5536             : 
    5537             : /*-------------------------------------------------------------------*
    5538             :  * quantize_DCT_0_coh()
    5539             :  *
    5540             :  * quanization of DCT component of order zero for transformed coherence vector
    5541             :  *-------------------------------------------------------------------*/
    5542             : /*! r: quantized value */
    5543      147722 : static Word32 quantize_DCT_0_coh_fx( // o:Q21
    5544             :     const Word16 x,                  /* i  : input value                                              Q14  */
    5545             :     const Word16 j,                  /* i  : subband index                                              */
    5546             :     const Word16 *coherence_cb,      /* i  : coherence codebook                                       Q14  */
    5547             :     const Word16 delta_var,          /* i  : azimuth variance threshold                               Q6  */
    5548             :     const Word16 no_cb,              /* i  : maximum number of codewords                                */
    5549             :     IVAS_QDIRECTION *q_direction,    /* i  : quantized metadata                                         */
    5550             :     UWord16 *idx_x,                  /* o  : codewords index                                            */
    5551             :     Word16 *p_no_cb,                 /* o  : actual number of codewords dependent on energy ratio value */
    5552             :     const Word16 hrmasa_flag         /* i  : flag indicating high-rate MASA MD coding                   */
    5553             : )
    5554             : {
    5555             :     Word16 var_azi /*Q6*/, xhat;
    5556             :     Word16 idx_sub_cb, idx;
    5557             :     Word16 min_index;
    5558             :     Word16 azimuth_16[MAX_PARAM_SPATIAL_SUBFRAMES];                                                             // Q6
    5559      147722 :     Copy_Scale_sig_32_16( q_direction->band_data[j].azimuth_fx, azimuth_16, MAX_PARAM_SPATIAL_SUBFRAMES, -16 ); // Q22->Q6
    5560             :     /* quantize first DCT component */
    5561      147722 :     var_azi = var_fx( azimuth_16, Q6, q_direction->cfg.nblocks );
    5562             : 
    5563      147722 :     IF( hrmasa_flag )
    5564             :     {
    5565           0 :         minimum_s( (Word16 *) ( q_direction->band_data[j].energy_ratio_index ), q_direction->cfg.nblocks, &min_index );
    5566           0 :         min_index = shr( min_index, 1 );
    5567             :     }
    5568             :     ELSE
    5569             :     {
    5570      147722 :         min_index = q_direction->band_data[j].energy_ratio_index[0];
    5571      147722 :         move16();
    5572             :     }
    5573             : 
    5574      147722 :     IF( LT_16( var_azi, delta_var ) )
    5575             :     {
    5576       36005 :         idx_sub_cb = imult1616( no_cb, min_index );
    5577             :     }
    5578             :     ELSE
    5579             :     {
    5580      111717 :         idx_sub_cb = imult1616( no_cb, add( min_index, DIRAC_DIFFUSE_LEVELS ) );
    5581             :     }
    5582             : 
    5583      147722 :     idx = squant_fx( x, &xhat, &coherence_cb[idx_sub_cb], len_cb_dct0_masa[min_index] );
    5584             : 
    5585      147722 :     *p_no_cb = len_cb_dct0_masa[min_index];
    5586      147722 :     move16();
    5587      147722 :     *idx_x = idx;
    5588      147722 :     move16();
    5589             : 
    5590      147722 :     return L_shl( xhat, 7 ); // Q21
    5591             : }
    5592             : 
    5593             : /*-------------------------------------------------------------------*
    5594             :  * encode_coherence_indexesDCT1()
    5595             :  *
    5596             :  * Encoding DCT1 coeffs with joint index or EC
    5597             :  *-------------------------------------------------------------------*/
    5598             : /*! r: number of bits written */
    5599       23095 : static Word16 encode_coherence_indexesDCT1_fx(
    5600             :     UWord16 *idx_dct,         /* i  : data to be encoded   */
    5601             :     const Word16 len,         /* i  : number of data       */
    5602             :     BSTR_ENC_HANDLE hMetaData /* i  : metadata handle      */
    5603             : )
    5604             : {
    5605             :     Word16 i, nbits, GR_ord;
    5606             :     UWord16 av;
    5607             :     UWord16 mr_idx_dct[MASA_MAXIMUM_CODING_SUBBANDS];
    5608             : 
    5609       23095 :     GR_ord = 0;
    5610       23095 :     move16();
    5611       23095 :     nbits = 0;
    5612       23095 :     move16();
    5613             : 
    5614       23095 :     nbits = mean_removed_GR_new_fx( idx_dct, MASA_NO_CV_COH1, len, 0, &GR_ord, &av, mr_idx_dct );
    5615             : 
    5616      170817 :     FOR( i = 0; i < len; i++ )
    5617             :     {
    5618      147722 :         ivas_qmetadata_encode_extended_gr_fx( hMetaData, mr_idx_dct[i], 2 * MASA_NO_CV_COH1, GR_ord );
    5619             :     }
    5620             : 
    5621       23095 :     nbits = add( nbits, len_huf_masa[av] );
    5622             : 
    5623       23095 :     push_next_indice( hMetaData, huff_code_av_masa[av], len_huf_masa[av] );
    5624             : 
    5625       23095 :     return nbits;
    5626             : }
    5627             : 
    5628             : /*-------------------------------------------------------------------*
    5629             :  * dct4_transform()
    5630             :  *
    5631             :  * 4D implementation of DCT transform
    5632             :  *-------------------------------------------------------------------*/
    5633      295444 : static void dct4_transform_fx(
    5634             :     UWord8 *v,    /* i  : input 4D vector */
    5635             :     Word32 *dct_v /* o  : output transformed vector Q21 */
    5636             : )
    5637             : {
    5638             :     Word32 a, b, c, d;
    5639             : 
    5640      295444 :     a = L_shl( L_add( v[0], v[3] ), Q12 ); //*0.5f / 256.0f;
    5641      295444 :     b = L_shl( L_add( v[1], v[2] ), Q12 ); //*0.5f / 256.0f;
    5642      295444 :     c = L_shl( L_sub( v[0], v[3] ), Q13 ); // / 256.0f;
    5643      295444 :     d = L_shl( L_sub( v[1], v[2] ), Q13 ); // / 256.0f;
    5644             : 
    5645      295444 :     dct_v[0] = L_add( a, b ); // 0.5f * (a + b);
    5646      295444 :     move32();
    5647      295444 :     dct_v[1] = L_add( Mpy_32_32_r( 1402911301 /*0.653281482438188f.Q31*/, c ), Mpy_32_32_r( 581104888 /*0.270598050073099f.Q31*/, d ) );
    5648      295444 :     move32();
    5649      295444 :     dct_v[2] = L_sub( a, b ); // 0.5f * (a - b);
    5650      295444 :     move32();
    5651      295444 :     dct_v[3] = L_sub( Mpy_32_32_r( 581104888 /*0.270598050073099f.Q31*/, c ), Mpy_32_32_r( 1402911301 /*0.653281482438188f.Q31*/, d ) );
    5652      295444 :     move32();
    5653             : 
    5654      295444 :     return;
    5655             : }
    5656             : 
    5657             : /*-------------------------------------------------------------------*
    5658             :  * ivas_qmetadata_quantize_coherence_hr_512()
    5659             :  *
    5660             :  *
    5661             :  *-------------------------------------------------------------------*/
    5662        3532 : static Word16 ivas_qmetadata_quantize_coherence_hr_512_fx(
    5663             :     IVAS_QMETADATA *hQMetaData,      /* i/o: quantized metadata            */
    5664             :     const Word16 idx_d,              /* i  : current direction index       */
    5665             :     const Word16 all_coherence_zero, /* i  : all coherence is zero - flag  */
    5666             :     BSTR_ENC_HANDLE hMetaData,       /* i  : metadata handle               */
    5667             :     const Word16 bits_coh )
    5668             : {
    5669             :     Word16 j, k;
    5670             :     Word16 nbands, nblocks;
    5671             :     Word16 nbits;
    5672             :     Word16 nbits1, nbits0, nbits_av;
    5673             :     UWord16 idx_coh[MASA_MAXIMUM_CODING_SUBBANDS];
    5674             :     IVAS_QDIRECTION *q_direction;
    5675             :     Word16 cbsize;
    5676             :     Word16 delta, tmp;
    5677             :     Word16 min_idx, GR_param, GR_param_av;
    5678             :     UWord16 av, mr_idx[MASA_MAXIMUM_CODING_SUBBANDS];
    5679             : 
    5680        3532 :     q_direction = &( hQMetaData->q_direction[idx_d] );
    5681        3532 :     nbands = q_direction->cfg.nbands;
    5682        3532 :     nblocks = q_direction->cfg.nblocks;
    5683        3532 :     nbits = 0;
    5684        3532 :     move16();
    5685        3532 :     move16();
    5686        3532 :     move16();
    5687             : 
    5688        3532 :     IF( EQ_16( all_coherence_zero, 1 ) )
    5689             :     {
    5690           0 :         return nbits;
    5691             :     }
    5692        3532 :     nbits = hMetaData->nb_bits_tot;
    5693        3532 :     move16();
    5694             : 
    5695        3532 :     cbsize = shl( 1, bits_coh );
    5696             :     // delta = 256.0f / cbsize;
    5697        3532 :     delta = div_l( 256, shr( cbsize, 1 ) ); // Q15
    5698             : 
    5699       16760 :     FOR( k = 0; k < nblocks; k++ )
    5700             :     {
    5701       13228 :         min_idx = 0;
    5702       13228 :         move16();
    5703      284590 :         FOR( j = 0; j < nbands; j++ )
    5704             :         {
    5705      271362 :             idx_coh[j] = usquant_fx( (Word16) ( q_direction->coherence_band_data[j].spread_coherence[k] ), &tmp, shr( delta, 1 ), shr( delta, 1 ) /* Q-1 */, cbsize );
    5706      271362 :             move16();
    5707      271362 :             q_direction->coherence_band_data[j].spread_coherence[k] = (UWord8) add( imult1616( idx_coh[j], delta ), shr( delta, 1 ) /*delta/2*/ ); // Q15
    5708      271362 :             if ( LT_16( idx_coh[j], min_idx ) )
    5709             :             {
    5710           0 :                 min_idx = idx_coh[j];
    5711           0 :                 move16();
    5712             :             }
    5713             :         }
    5714             : 
    5715       13228 :         nbits0 = 0;
    5716       13228 :         nbits1 = 0;
    5717       13228 :         move16();
    5718       13228 :         move16();
    5719             : 
    5720      284590 :         FOR( j = 0; j < nbands; j++ )
    5721             :         {
    5722      271362 :             idx_coh[j] = sub( idx_coh[j], min_idx );
    5723      271362 :             move16();
    5724      271362 :             nbits0 = add( nbits0, ivas_qmetadata_encode_extended_gr_length_fx( idx_coh[j], sub( cbsize, min_idx ), 0 ) );
    5725      271362 :             nbits1 = add( nbits1, ivas_qmetadata_encode_extended_gr_length_fx( idx_coh[j], sub( cbsize, min_idx ), 1 ) );
    5726             :         }
    5727       13228 :         IF( nbits0 < nbits1 )
    5728             :         {
    5729       12746 :             GR_param = 0;
    5730       12746 :             nbits1 = nbits0;
    5731       12746 :             move16();
    5732       12746 :             move16();
    5733             :         }
    5734             :         ELSE
    5735             :         {
    5736         482 :             GR_param = 1;
    5737         482 :             move16();
    5738             :         }
    5739             : 
    5740       13228 :         GR_param_av = 1;
    5741       13228 :         move16();
    5742       13228 :         nbits_av = mean_removed_GR_new_fx( idx_coh, cbsize, nbands, 1, &GR_param_av, &av, mr_idx );
    5743             : 
    5744       13228 :         IF( LT_16( nbits_av, nbits1 ) )
    5745             :         {
    5746         146 :             nbits1 = nbits_av;
    5747         146 :             GR_param = GR_param_av;
    5748         146 :             move16();
    5749         146 :             move16();
    5750             : 
    5751             :             /* use average removed */
    5752         146 :             push_next_indice( hMetaData, 1, 1 );
    5753             : 
    5754             :             /* write average */
    5755         146 :             push_next_indice( hMetaData, av, bits_coh );
    5756             : 
    5757             :             /*  write GR param */
    5758         146 :             push_next_indice( hMetaData, GR_param, 1 );
    5759             : 
    5760        2050 :             FOR( j = 0; j < nbands; j++ )
    5761             :             {
    5762        1904 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, mr_idx[j], imult1616( 2, cbsize ), GR_param );
    5763             :             }
    5764             :         }
    5765             :         ELSE
    5766             :         {
    5767             :             /* use min removed */
    5768       13082 :             push_next_indice( hMetaData, 0, 1 );
    5769             : 
    5770             :             /* write min index */
    5771       13082 :             push_next_indice( hMetaData, min_idx, bits_coh );
    5772             : 
    5773             :             /*  write GR param */
    5774       13082 :             push_next_indice( hMetaData, GR_param, 1 );
    5775             : 
    5776      282540 :             FOR( j = 0; j < nbands; j++ )
    5777             :             {
    5778      269458 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, idx_coh[j], sub( cbsize, min_idx ), GR_param );
    5779             :             }
    5780             :         }
    5781             :     }
    5782             : 
    5783        3532 :     nbits = sub( hMetaData->nb_bits_tot, nbits );
    5784        3532 :     return nbits;
    5785             : }
    5786             : 
    5787             : /*-------------------------------------------------------------------*
    5788             :  * ivas_qmetadata_quantize_coherence()
    5789             :  *
    5790             :  *
    5791             :  *-------------------------------------------------------------------*/
    5792             : 
    5793             : /*! r: number of bits written */
    5794       54358 : static Word16 ivas_qmetadata_quantize_coherence_fx(
    5795             :     IVAS_QMETADATA *hQMetaData,      /* i/o: quantized metadata                        */
    5796             :     const Word16 idx_d,              /* i  : current direction index                   */
    5797             :     const Word16 all_coherence_zero, /* i  : all coherence is zero - flag              */
    5798             :     BSTR_ENC_HANDLE hMetaData,       /* i  : metadata handle                           */
    5799             :     const Word16 write_flag,         /* i  : flag to actually write the data or not    */
    5800             :     Word16 *indice_coherence,
    5801             :     const Word16 hrmasa_flag /* i  : flag indicating high-rate MASA MD coding  */
    5802             : )
    5803             : {
    5804             :     Word16 j, k;
    5805             :     Word32 dct_coh[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; // Q21
    5806             :     UWord16 idx_dct[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_MAXIMUM_CODING_SUBBANDS];
    5807             :     Word16 coding_subbands;
    5808             :     Word16 nbits;
    5809             :     UWord64 no_cb;
    5810             :     Word16 MASA_grouping[MASA_MAXIMUM_CODING_SUBBANDS];
    5811             :     Word16 nbits1;
    5812             :     Word16 coding_subbands_0, d;
    5813             :     Word16 two_dir_band[MASA_MAXIMUM_CODING_SUBBANDS];
    5814             :     Word16 no_cb_vec[MASA_MAXIMUM_CODING_SUBBANDS];
    5815             :     IVAS_QDIRECTION *q_direction;
    5816             :     Word16 min_index;
    5817             :     Word16 tmp16;
    5818       54358 :     min_index = 0;
    5819       54358 :     move16();
    5820       54358 :     q_direction = &( hQMetaData->q_direction[idx_d] );
    5821       54358 :     coding_subbands = q_direction->cfg.nbands;
    5822       54358 :     move16();
    5823       54358 :     nbits = 0;
    5824       54358 :     move16();
    5825             : 
    5826       54358 :     IF( EQ_16( all_coherence_zero, 1 ) )
    5827             :     {
    5828           0 :         return nbits;
    5829             :     }
    5830             : 
    5831       54358 :     IF( EQ_16( hQMetaData->q_direction[idx_d].cfg.nblocks, 1 ) )
    5832             :     {
    5833        8168 :         nbits = encode_spread_coherence_1sf_fx( hQMetaData, idx_d, hMetaData, hrmasa_flag );
    5834             : 
    5835        8168 :         return nbits;
    5836             :     }
    5837             :     ELSE
    5838             :     {
    5839       46190 :         k = 0;
    5840       46190 :         move16();
    5841       46190 :         no_cb = 1;
    5842       46190 :         move64();
    5843       46190 :         coding_subbands_0 = hQMetaData->q_direction[0].cfg.nbands;
    5844       46190 :         move16();
    5845       46190 :         IF( LE_16( coding_subbands_0, 5 ) )
    5846             :         {
    5847      202968 :             FOR( j = 0; j < 5; j++ )
    5848             :             {
    5849      169140 :                 MASA_grouping[j] = j;
    5850      169140 :                 move16();
    5851             :             }
    5852             :         }
    5853             :         ELSE
    5854             :         {
    5855       12362 :             IF( LE_16( coding_subbands_0, 8 ) )
    5856             :             {
    5857        5092 :                 Copy( MASA_grouping_8_to_5, MASA_grouping, 8 );
    5858             :             }
    5859        7270 :             ELSE IF( LE_16( coding_subbands_0, 12 ) )
    5860             :             {
    5861        3022 :                 Copy( MASA_grouping_12_to_5, MASA_grouping, 12 );
    5862             :             }
    5863        4248 :             ELSE IF( LE_16( coding_subbands_0, 18 ) )
    5864             :             {
    5865        1880 :                 Copy( MASA_grouping_18_to_5, MASA_grouping, 18 );
    5866             :             }
    5867             :             ELSE
    5868             :             {
    5869        2368 :                 IF( LE_16( coding_subbands_0, 24 ) )
    5870             :                 {
    5871        2368 :                     Copy( MASA_grouping_24_to_5, MASA_grouping, 24 );
    5872             :                 }
    5873             :             }
    5874             :         }
    5875             : 
    5876       46190 :         IF( LT_16( coding_subbands, coding_subbands_0 ) )
    5877             :         {
    5878        7468 :             d = 0;
    5879        7468 :             move16();
    5880       58684 :             FOR( j = 0; j < coding_subbands_0; j++ )
    5881             :             {
    5882       51216 :                 IF( EQ_16( hQMetaData->twoDirBands[j], 1 ) )
    5883             :                 {
    5884       20312 :                     two_dir_band[d] = j;
    5885       20312 :                     move16();
    5886       20312 :                     d = add( d, 1 );
    5887             :                 }
    5888             :             }
    5889             :         }
    5890             : 
    5891      341634 :         FOR( j = 0; j < coding_subbands; j++ )
    5892             :         {
    5893             :             /* DCT transform */
    5894      295444 :             dct4_transform_fx( hQMetaData->q_direction[idx_d].coherence_band_data[j].spread_coherence, dct_coh[j] );
    5895             : 
    5896      295444 :             IF( hrmasa_flag )
    5897             :             {
    5898           0 :                 minimum_s( (Word16 *) ( q_direction->band_data[j].energy_ratio_index ), q_direction->cfg.nblocks, &min_index );
    5899           0 :                 no_cb_vec[j] = len_cb_dct0_masa[min_index >> 1];
    5900           0 :                 move16();
    5901             :             }
    5902             :             ELSE
    5903             :             {
    5904      295444 :                 no_cb_vec[j] = len_cb_dct0_masa[q_direction->band_data[j].energy_ratio_index[0]];
    5905      295444 :                 move16();
    5906             :             }
    5907             : 
    5908      295444 :             IF( write_flag )
    5909             :             {
    5910             :                 /* quantize first DCT parameter */
    5911      147722 :                 dct_coh[j][0] = quantize_DCT_0_coh_fx( extract_l( L_shr_r( dct_coh[j][0], 7 ) ), j, coherence_cb0_masa_Q14, MASA_DELTA_AZI_DCT0 << Q6, MASA_NO_CV_COH, q_direction, &idx_dct[k], &no_cb_vec[j], hrmasa_flag ); // Q21
    5912      147722 :                 move32();
    5913             :             }
    5914             : 
    5915      295444 :             IF( LT_16( coding_subbands, coding_subbands_0 ) )
    5916             :             {
    5917       20312 :                 idx_dct[k + coding_subbands] = squant_fx( extract_l( L_shr_r( dct_coh[j][1], 6 ) ), &tmp16, &coherence_cb1_masa_Q15[MASA_grouping[two_dir_band[j]] * MASA_NO_CV_COH1], MASA_NO_CV_COH1 );
    5918       20312 :                 move16();
    5919             :             }
    5920             :             ELSE
    5921             :             {
    5922      275132 :                 idx_dct[k + coding_subbands] = squant_fx( extract_l( L_shr_r( dct_coh[j][1], 6 ) ), &tmp16, &coherence_cb1_masa_Q15[MASA_grouping[j] * MASA_NO_CV_COH1], MASA_NO_CV_COH1 );
    5923      275132 :                 move16();
    5924             :             }
    5925      295444 :             dct_coh[j][1] = L_shl( tmp16, 6 );
    5926      295444 :             k = add( k, 1 );
    5927      295444 :             move16();
    5928             : 
    5929      295444 :             dct_coh[j][2] = 0;
    5930      295444 :             move32();
    5931      295444 :             dct_coh[j][3] = 0;
    5932      295444 :             move32();
    5933             :         }
    5934             : 
    5935       46190 :         nbits1 = 0;
    5936       46190 :         move16();
    5937       46190 :         IF( GT_16( sum_s( no_cb_vec, coding_subbands ), MASA_COH_LIMIT_2IDX ) )
    5938             :         {
    5939             :             /* make two indxes */
    5940         348 :             no_cb = 1;
    5941         348 :             move64();
    5942             : 
    5943        4524 :             FOR( j = 0; j < coding_subbands / 2; j++ )
    5944             :             {
    5945        4176 :                 no_cb = no_cb * no_cb_vec[j];
    5946             :             }
    5947             : 
    5948             :             // nbits = (Word16) ceilf( logf( (float) no_cb ) * INV_LOG_2 );
    5949         348 :             IF( LE_64( no_cb, 1 ) )
    5950             :             {
    5951           0 :                 nbits = 0;
    5952           0 :                 move16();
    5953             :             }
    5954             :             ELSE
    5955             :             {
    5956         348 :                 nbits = sub( 63, W_norm( W_sub( no_cb, 1 ) ) );
    5957             :             }
    5958         348 :             no_cb = 1;
    5959         348 :             move64();
    5960             : 
    5961        4524 :             FOR( j = coding_subbands / 2; j < coding_subbands; j++ )
    5962             :             {
    5963        4176 :                 no_cb = no_cb * no_cb_vec[j];
    5964             :             }
    5965             :             // nbits1 = (Word16) ceilf( logf( (float) no_cb ) * INV_LOG_2 );
    5966         348 :             IF( LE_64( no_cb, 1 ) )
    5967             :             {
    5968           0 :                 nbits1 = 0;
    5969           0 :                 move16();
    5970             :             }
    5971             :             ELSE
    5972             :             {
    5973         348 :                 nbits1 = sub( 63, W_norm( W_sub( no_cb, 1 ) ) );
    5974             :             }
    5975             :         }
    5976             :         ELSE
    5977             :         {
    5978       45842 :             no_cb = 1;
    5979       45842 :             move64();
    5980             : 
    5981      332934 :             FOR( j = 0; j < coding_subbands; j++ )
    5982             :             {
    5983      287092 :                 no_cb = no_cb * no_cb_vec[j];
    5984             :             }
    5985             : 
    5986             :             // nbits = (Word16) ceilf( logf( (float) no_cb ) * INV_LOG_2 );
    5987       45842 :             IF( LE_64( no_cb, 1 ) )
    5988             :             {
    5989           0 :                 nbits = 0;
    5990           0 :                 move16();
    5991             :             }
    5992             :             ELSE
    5993             :             {
    5994       45842 :                 nbits = sub( 63, W_norm( W_sub( no_cb, 1 ) ) );
    5995             :             }
    5996             :         }
    5997             : 
    5998       46190 :         IF( write_flag )
    5999             :         {
    6000      170817 :             FOR( j = 0; j < coding_subbands; j++ )
    6001             :             {
    6002             :                 /* inverse DCT transform */
    6003      147722 :                 invdct4_transform_fx( dct_coh[j], q_direction->coherence_band_data[j].spread_coherence, Q21 );
    6004             :             }
    6005             : 
    6006       23095 :             nbits = encode_coherence_indexesDCT0_fx( idx_dct, coding_subbands, no_cb_vec, hMetaData, *indice_coherence, nbits, nbits1 );
    6007             :         }
    6008             :         ELSE
    6009             :         {
    6010             :             /* write dummy data now and save the position */
    6011       23095 :             *indice_coherence = hMetaData->nb_ind_tot;
    6012       23095 :             move16();
    6013       23095 :             k = nbits;
    6014       23095 :             move16();
    6015       50301 :             WHILE( k > 0 )
    6016             :             {
    6017       27206 :                 push_next_indice( hMetaData, 0, s_min( 16, k ) );
    6018       27206 :                 k = sub( k, 16 );
    6019             :             }
    6020             : 
    6021       23095 :             IF( nbits1 > 0 )
    6022             :             {
    6023         174 :                 k = nbits1;
    6024         174 :                 move16();
    6025         522 :                 WHILE( k > 0 )
    6026             :                 {
    6027         348 :                     push_next_indice( hMetaData, 0, s_min( 16, k ) );
    6028         348 :                     k = sub( k, 16 );
    6029             :                 }
    6030             :             }
    6031       23095 :             nbits = add( nbits, nbits1 );
    6032       23095 :             set16_fx( no_cb_vec, MASA_NO_CV_COH1, coding_subbands );
    6033       23095 :             nbits = add( nbits, encode_coherence_indexesDCT1_fx( &idx_dct[coding_subbands], coding_subbands, hMetaData ) );
    6034             : 
    6035       23095 :             return nbits;
    6036             :         }
    6037             :     }
    6038       23095 :     return nbits;
    6039             : }
    6040             : 
    6041             : 
    6042             : /*-------------------------------------------------------------------*
    6043             :  * ivas_qmetadata_reorder_2dir_bands()
    6044             :  *
    6045             :  * Reorders metadata on 2dir bands such that direct-to-total ratio of first direction is
    6046             :  * always larger or equal to direct-to-total ratio of second direction.
    6047             :  *-------------------------------------------------------------------*/
    6048        4580 : static void ivas_qmetadata_reorder_2dir_bands_fx(
    6049             :     IVAS_QMETADATA_HANDLE hQMetaData )
    6050             : {
    6051             :     Word16 nbands;
    6052             :     Word16 nsubframes;
    6053             :     Word16 band, sf;
    6054             : 
    6055        4580 :     nbands = hQMetaData->q_direction[0].cfg.nbands;
    6056        4580 :     move16();
    6057        4580 :     nsubframes = hQMetaData->q_direction[0].cfg.nblocks;
    6058        4580 :     move16();
    6059             : 
    6060       44132 :     FOR( band = 0; band < nbands; band++ )
    6061             :     {
    6062       39552 :         IF( EQ_16( hQMetaData->twoDirBands[band], 1 ) )
    6063             :         {
    6064       13200 :             IF( LT_32( hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0], hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[0] ) )
    6065             :             {
    6066        5424 :                 UWord16 uint16_tmp = 0;
    6067        5424 :                 move16();
    6068        5424 :                 Word32 fx_tmp = 0;
    6069        5424 :                 move32();
    6070        5424 :                 UWord8 uint8_tmp = 0;
    6071        5424 :                 move16();
    6072             : 
    6073       23454 :                 FOR( sf = 0; sf < nsubframes; sf++ )
    6074             :                 {
    6075       18030 :                     uint16_tmp = hQMetaData->q_direction[0].band_data[band].spherical_index[sf];
    6076       18030 :                     move16();
    6077       18030 :                     hQMetaData->q_direction[0].band_data[band].spherical_index[sf] = hQMetaData->q_direction[1].band_data[band].spherical_index[sf];
    6078       18030 :                     move16();
    6079       18030 :                     hQMetaData->q_direction[1].band_data[band].spherical_index[sf] = uint16_tmp;
    6080       18030 :                     move16();
    6081             : 
    6082       18030 :                     fx_tmp = hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf]; // Q22
    6083       18030 :                     move32();
    6084       18030 :                     hQMetaData->q_direction[0].band_data[band].azimuth_fx[sf] = hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf];
    6085       18030 :                     move32();
    6086       18030 :                     hQMetaData->q_direction[1].band_data[band].azimuth_fx[sf] = fx_tmp;
    6087       18030 :                     move32();
    6088             : 
    6089       18030 :                     fx_tmp = hQMetaData->q_direction[0].band_data[band].elevation_fx[sf];
    6090       18030 :                     move32();
    6091       18030 :                     hQMetaData->q_direction[0].band_data[band].elevation_fx[sf] = hQMetaData->q_direction[1].band_data[band].elevation_fx[sf]; // Q22
    6092       18030 :                     move32();
    6093       18030 :                     hQMetaData->q_direction[1].band_data[band].elevation_fx[sf] = fx_tmp;
    6094       18030 :                     move32();
    6095             : 
    6096       18030 :                     uint8_tmp = hQMetaData->q_direction[0].band_data[band].distance[sf];
    6097       18030 :                     move16();
    6098       18030 :                     hQMetaData->q_direction[0].band_data[band].distance[sf] = hQMetaData->q_direction[1].band_data[band].distance[sf];
    6099       18030 :                     move16();
    6100       18030 :                     hQMetaData->q_direction[1].band_data[band].distance[sf] = uint8_tmp;
    6101       18030 :                     move16();
    6102             : 
    6103       18030 :                     IF( hQMetaData->coherence_flag )
    6104             :                     {
    6105       18030 :                         uint8_tmp = hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf];
    6106       18030 :                         move16();
    6107       18030 :                         hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf];
    6108       18030 :                         move16();
    6109       18030 :                         hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = uint8_tmp;
    6110       18030 :                         move16();
    6111             :                     }
    6112             :                 }
    6113        5424 :                 IF( hQMetaData->coherence_flag )
    6114             :                 {
    6115        5424 :                     fx_tmp = hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0];
    6116        5424 :                     move32();
    6117        5424 :                     hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[0] = hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[0]; // Q30
    6118        5424 :                     move32();
    6119        5424 :                     hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[0] = fx_tmp;
    6120        5424 :                     move32();
    6121             :                 }
    6122             :             }
    6123             :         }
    6124             :     }
    6125             : 
    6126        4580 :     return;
    6127             : }
    6128             : 
    6129             : /*-------------------------------------------------------------------*
    6130             :  * write_2dir_info()
    6131             :  *
    6132             :  *
    6133             :  *-------------------------------------------------------------------*/
    6134       21696 : static Word16 write_2dir_info(
    6135             :     BSTR_ENC_HANDLE hMetaData,
    6136             :     UWord8 *twoDirBands,
    6137             :     const Word16 n,
    6138             :     const Word16 k )
    6139             : {
    6140             :     Word16 nbits;
    6141             :     Word16 p[MASA_MAXIMUM_CODING_SUBBANDS];
    6142             :     UWord16 dif_p[MASA_MAXIMUM_CODING_SUBBANDS];
    6143             :     Word16 i, j;
    6144             : 
    6145       21696 :     j = 0;
    6146       21696 :     p[0] = 0;
    6147       21696 :     move16();
    6148       21696 :     move16();
    6149      276852 :     FOR( i = 0; i < n; i++ )
    6150             :     {
    6151      255156 :         IF( EQ_16( twoDirBands[i], 1 ) )
    6152             :         {
    6153      216414 :             p[j] = i;
    6154      216414 :             j = add( j, 1 );
    6155      216414 :             move16();
    6156             :         }
    6157             :     }
    6158             : 
    6159       21696 :     dif_p[0] = p[0];
    6160       21696 :     move16();
    6161      216414 :     FOR( i = 1; i < j; i++ )
    6162             :     {
    6163      194718 :         dif_p[i] = sub( sub( p[i], p[i - 1] ), 1 );
    6164      194718 :         move16();
    6165             :     }
    6166             : 
    6167       21696 :     j = hMetaData->nb_bits_tot;
    6168       21696 :     move16();
    6169      238110 :     FOR( i = 0; i < k; i++ )
    6170             :     {
    6171      216414 :         ivas_qmetadata_encode_extended_gr_fx( hMetaData, dif_p[i], 24, 0 );
    6172             :     }
    6173       21696 :     nbits = sub( hMetaData->nb_bits_tot, j );
    6174             : 
    6175       21696 :     return nbits;
    6176             : }
    6177             : 
    6178             : /*-------------------------------------------------------------------*
    6179             :  * transform_azimuth_dir2()
    6180             :  *
    6181             :  *
    6182             :  *-------------------------------------------------------------------*/
    6183       20820 : static void transform_azimuth_dir2_fx(
    6184             :     IVAS_QMETADATA_HANDLE hQMetaData,
    6185             :     Word16 *dir2_bands )
    6186             : {
    6187             :     Word16 i, b;
    6188             : 
    6189      228900 :     FOR( i = hQMetaData->q_direction[1].cfg.start_band; i < hQMetaData->q_direction[1].cfg.nbands; i++ )
    6190             :     {
    6191      208080 :         IF( LT_16( hQMetaData->q_direction[0].band_data[dir2_bands[i]].energy_ratio_index[0], 7 ) )
    6192             :         {
    6193             :             /* transform azimuth */
    6194      803759 :             FOR( b = 0; b < hQMetaData->q_direction[1].cfg.nblocks; b++ )
    6195             :             {
    6196             :                 Word64 azimuth;
    6197      641281 :                 azimuth = W_add( W_deposit32_l( L_sub( hQMetaData->q_direction[1].band_data[i].azimuth_fx[b], hQMetaData->q_direction[0].band_data[dir2_bands[i]].azimuth_fx[b] ) ), DEGREE_180_Q_22 ); // Q22
    6198             : 
    6199      641281 :                 IF( GE_64( azimuth, DEGREE_180_Q_22 ) )
    6200             :                 {
    6201       93868 :                     azimuth = W_sub( azimuth, DEGREE_360_Q_22 );
    6202             :                 }
    6203      641281 :                 IF( LT_64( azimuth, -DEGREE_180_Q_22 ) )
    6204             :                 {
    6205           0 :                     azimuth = W_add( azimuth, DEGREE_360_Q_22 );
    6206             :                 }
    6207      641281 :                 IF( GE_64( azimuth, DEGREE_180_Q_22 ) )
    6208             :                 {
    6209           0 :                     azimuth = W_sub( azimuth, DEGREE_360_Q_22 );
    6210             :                 }
    6211      641281 :                 IF( LT_64( azimuth, -DEGREE_180_Q_22 ) )
    6212             :                 {
    6213           0 :                     azimuth = W_add( azimuth, DEGREE_360_Q_22 );
    6214             :                 }
    6215             : 
    6216      641281 :                 hQMetaData->q_direction[1].band_data[i].azimuth_fx[b] = W_extract_l( azimuth );
    6217      641281 :                 move32();
    6218             :             }
    6219             :         }
    6220             :     }
    6221             : 
    6222       20820 :     return;
    6223             : }
    6224        4836 : static Word16 divide_GR_orders_fx(
    6225             :     const Word16 *q_idx,
    6226             :     const Word16 GR1,
    6227             :     const Word16 GR2,
    6228             :     const Word16 len,
    6229             :     const Word16 len_max_GR1,
    6230             :     Word16 *i_min )
    6231             : {
    6232             :     Word16 nb_GR_min;
    6233             :     Word16 i, j, nb_GR;
    6234        4836 :     nb_GR_min = 1000;
    6235        4836 :     *i_min = -1;
    6236        4836 :     move16();
    6237        4836 :     move16();
    6238       72840 :     FOR( i = 0; i < s_min( len_max_GR1, len ); i++ )
    6239             :     {
    6240       68004 :         nb_GR = 0;
    6241       68004 :         move16();
    6242             : 
    6243      587088 :         FOR( j = 0; j <= i; j++ )
    6244             :         {
    6245      519084 :             nb_GR = add( nb_GR, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR1 ) );
    6246             :         }
    6247      741204 :         FOR( j = i + 1; j < len; j++ )
    6248             :         {
    6249      673200 :             nb_GR = add( nb_GR, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR2 ) );
    6250             :         }
    6251             : 
    6252       68004 :         IF( LT_16( nb_GR, nb_GR_min ) )
    6253             :         {
    6254       16421 :             nb_GR_min = nb_GR;
    6255       16421 :             *i_min = add( i, 1 );
    6256       16421 :             move16();
    6257       16421 :             move16();
    6258             :         }
    6259             :     }
    6260             : 
    6261        4836 :     return nb_GR_min;
    6262             : }
    6263             : 
    6264             : 
    6265         250 : static Word16 find_optimal_GR_order_fx(
    6266             :     const Word16 *q_idx,
    6267             :     const Word16 len,
    6268             :     Word16 *GR )
    6269             : {
    6270             :     Word16 nb_GR_0, nb_GR_1;
    6271             :     Word16 i;
    6272             :     /* find optimum length of the part encoded with GR2 */
    6273         250 :     nb_GR_0 = 0;
    6274         250 :     nb_GR_1 = 0;
    6275         250 :     move16();
    6276         250 :     move16();
    6277        1226 :     FOR( i = 0; i < len; i++ )
    6278             :     {
    6279         976 :         nb_GR_0 = add( nb_GR_0, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[i], 100, 0 ) );
    6280         976 :         nb_GR_1 = add( nb_GR_1, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[i], 100, 1 ) );
    6281             :     }
    6282             : 
    6283         250 :     IF( LT_16( nb_GR_0, nb_GR_1 ) )
    6284             :     {
    6285         113 :         *GR = 0;
    6286         113 :         move16();
    6287         113 :         return nb_GR_0;
    6288             :     }
    6289             :     ELSE
    6290             :     {
    6291         137 :         *GR = 1;
    6292         137 :         move16();
    6293             : 
    6294         137 :         return nb_GR_1;
    6295             :     }
    6296             : }
    6297             : 
    6298             : 
    6299        1612 : static Word16 find_optimal_GR_orders_fx(
    6300             :     const Word16 *q_idx,
    6301             :     const Word16 len,
    6302             :     const Word16 len_max_GR1,
    6303             :     Word16 *GR1,
    6304             :     Word16 *GR2,
    6305             :     Word16 *i_min )
    6306             : {
    6307             :     Word16 nb_GR_20, nb_GR_21, nb_GR_10, nb_GR_min;
    6308             :     Word16 i_min_20, i_min_21, i_min_10;
    6309             :     /* find optimum length of the part encoded with GR2 */
    6310        1612 :     nb_GR_20 = divide_GR_orders_fx( q_idx, 2, 0, len, len_max_GR1, &i_min_20 );
    6311        1612 :     nb_GR_21 = divide_GR_orders_fx( q_idx, 2, 1, len, len_max_GR1, &i_min_21 );
    6312        1612 :     nb_GR_10 = divide_GR_orders_fx( q_idx, 1, 0, len, len_max_GR1, &i_min_10 );
    6313             : 
    6314        1612 :     test();
    6315        1612 :     IF( LT_16( nb_GR_20, nb_GR_21 ) && LT_16( nb_GR_20, nb_GR_10 ) )
    6316             :     {
    6317        1046 :         *GR1 = 2;
    6318        1046 :         *GR2 = 0;
    6319        1046 :         nb_GR_min = nb_GR_20;
    6320        1046 :         *i_min = i_min_20;
    6321        1046 :         move16();
    6322        1046 :         move16();
    6323        1046 :         move16();
    6324        1046 :         move16();
    6325             :     }
    6326             :     ELSE
    6327             :     {
    6328         566 :         test();
    6329         566 :         IF( LT_16( nb_GR_21, nb_GR_20 ) && LT_16( nb_GR_21, nb_GR_10 ) )
    6330             :         {
    6331         187 :             *GR1 = 2;
    6332         187 :             *GR2 = 1;
    6333         187 :             nb_GR_min = nb_GR_21;
    6334         187 :             *i_min = i_min_21;
    6335         187 :             move16();
    6336         187 :             move16();
    6337         187 :             move16();
    6338         187 :             move16();
    6339             :         }
    6340             :         ELSE
    6341             :         {
    6342         379 :             *GR1 = 1;
    6343         379 :             *GR2 = 0;
    6344         379 :             nb_GR_min = nb_GR_10;
    6345         379 :             *i_min = i_min_10;
    6346         379 :             move16();
    6347         379 :             move16();
    6348         379 :             move16();
    6349         379 :             move16();
    6350             :         }
    6351             :     }
    6352             : 
    6353        1612 :     return nb_GR_min;
    6354             : }
    6355             : 
    6356             : 
    6357        1862 : static Word16 write_stream_dct_coeffs_omasa_fx(
    6358             :     Word16 *q_idx,                /* i  : array of indexes to be written                                   */
    6359             :     const Word16 len_stream,      /* i  : array length                                                     */
    6360             :     BSTR_ENC_HANDLE hMetaData,    /* i/o: metadata bitstream                                               */
    6361             :     const Word16 first_line,      /* i  : is first line of the matrix? 1/0                                 */
    6362             :     const Word16 low_bitrate_mode /* i  : is low bitrate mode? if yes, limit the number of bits written    */
    6363             : )
    6364             : {
    6365        1862 :     Word16 nb_bits = 0, bits_pos;
    6366             :     UWord16 nb_GR_min;
    6367             :     Word16 i, j;
    6368             :     Word16 changed, update_needed;
    6369        1862 :     move16();
    6370             :     Word16 GR1, GR2, i_min;
    6371             :     Word16 max_bits;
    6372             : 
    6373        1862 :     bits_pos = hMetaData->nb_bits_tot;
    6374        1862 :     move16();
    6375        1862 :     IF( EQ_16( low_bitrate_mode, 1 ) )
    6376             :     {
    6377         250 :         max_bits = 50;
    6378         250 :         move16();
    6379             :     }
    6380             :     ELSE
    6381             :     {
    6382        1612 :         max_bits = 1000;
    6383        1612 :         move16();
    6384             :     }
    6385             : 
    6386             :     /* write DCT 0 component */
    6387             :     /* write sign only if not the very first DCT coeff */
    6388        1862 :     IF( first_line == 0 )
    6389             :     {
    6390           0 :         IF( q_idx[0] > 0 )
    6391             :         {
    6392           0 :             push_next_indice( hMetaData, 1, 1 );
    6393           0 :             push_next_indice( hMetaData, q_idx[0], BITS_MASA2TOTTAL_DCT0 );
    6394             :         }
    6395             :         ELSE
    6396             :         {
    6397           0 :             push_next_indice( hMetaData, 0, 1 );
    6398           0 :             push_next_indice( hMetaData, negate( q_idx[0] ), BITS_MASA2TOTTAL_DCT0 );
    6399             :         }
    6400           0 :         nb_bits = add( nb_bits, BITS_MASA2TOTTAL_DCT0 + 1 );
    6401             :     }
    6402             :     ELSE
    6403             :     {
    6404        1862 :         push_next_indice( hMetaData, q_idx[0], BITS_MASA2TOTTAL_DCT0 );
    6405        1862 :         nb_bits = add( nb_bits, BITS_MASA2TOTTAL_DCT0 );
    6406             :     }
    6407             : 
    6408        1862 :     IF( q_idx[0] != 0 )
    6409             :     {
    6410        1862 :         i_min = 1;
    6411        1862 :         GR2 = 0;
    6412        1862 :         move16();
    6413        1862 :         move16();
    6414        1862 :         IF( GE_16( len_stream, 8 ) )
    6415             :         {
    6416        1612 :             nb_GR_min = find_optimal_GR_orders_fx( &q_idx[1], sub( len_stream, 1 ), 15, &GR1, &GR2, &i_min );
    6417             :         }
    6418             :         ELSE
    6419             :         {
    6420         250 :             nb_GR_min = find_optimal_GR_order_fx( &q_idx[1], sub( len_stream, 1 ), &GR1 );
    6421             :         }
    6422             : 
    6423        1862 :         assert( nb_GR_min < 1000 );
    6424        1862 :         changed = 1;
    6425        1862 :         update_needed = 0;
    6426        1862 :         move16();
    6427        1862 :         move16();
    6428        1862 :         WHILE( ( len_stream >= 8 ) && ( nb_GR_min > max_bits ) && ( changed >= 1 ) )
    6429             :         {
    6430           0 :             test();
    6431           0 :             test();
    6432           0 :             update_needed = 1;
    6433           0 :             changed = 0;
    6434           0 :             move16();
    6435           0 :             move16();
    6436           0 :             FOR( j = len_stream - 1; j > 6; j-- )
    6437             :             {
    6438           0 :                 IF( GE_16( q_idx[j], 2 ) )
    6439             :                 {
    6440             : 
    6441           0 :                     IF( GT_16( j, i_min ) )
    6442             :                     {
    6443           0 :                         changed = 1;
    6444           0 :                         move16();
    6445           0 :                         nb_GR_min = sub( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR2 ) );
    6446           0 :                         q_idx[j] = sub( q_idx[j], 2 );
    6447           0 :                         move16();
    6448           0 :                         nb_GR_min = add( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR2 ) );
    6449             :                     }
    6450             :                     ELSE
    6451             :                     {
    6452           0 :                         changed = 1;
    6453           0 :                         move16();
    6454           0 :                         nb_GR_min = sub( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR1 ) );
    6455           0 :                         q_idx[j] = sub( q_idx[j], 2 );
    6456           0 :                         move16();
    6457           0 :                         nb_GR_min = add( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, 0 ) );
    6458             :                     }
    6459             :                 }
    6460           0 :                 ELSE IF( EQ_16( q_idx[j], 1 ) )
    6461             :                 {
    6462           0 :                     IF( GT_16( j, i_min ) )
    6463             :                     {
    6464           0 :                         changed = 1;
    6465           0 :                         move16();
    6466           0 :                         nb_GR_min = sub( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR2 ) );
    6467           0 :                         q_idx[j] = sub( q_idx[j], 1 );
    6468           0 :                         move16();
    6469             : 
    6470           0 :                         nb_GR_min = add( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR2 ) );
    6471             :                     }
    6472             :                     ELSE
    6473             :                     {
    6474           0 :                         changed = 1;
    6475           0 :                         move16();
    6476           0 :                         nb_GR_min = sub( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, GR1 ) );
    6477           0 :                         q_idx[j] = sub( q_idx[j], 1 );
    6478           0 :                         move16();
    6479           0 :                         nb_GR_min = add( nb_GR_min, ivas_qmetadata_encode_extended_gr_length_fx( q_idx[j], 100, 0 ) );
    6480             :                     }
    6481             :                 }
    6482           0 :                 IF( LT_16( nb_GR_min, max_bits ) )
    6483             :                 {
    6484           0 :                     BREAK;
    6485             :                 }
    6486             :             }
    6487             :         }
    6488             : 
    6489        1862 :         IF( EQ_16( update_needed, 1 ) )
    6490             :         {
    6491             :             /* re-calculate */
    6492             :             /* find optimum length of the part encoded with GR2 */
    6493           0 :             nb_GR_min = find_optimal_GR_orders_fx( &q_idx[1], sub( len_stream, 1 ), 15, &GR1, &GR2, &i_min );
    6494             :         }
    6495             : 
    6496        1862 :         IF( GE_16( len_stream, 8 ) )
    6497             :         {
    6498             :             /* write number of indexes encoded with GR2 on 4 bits  */
    6499        1612 :             push_next_indice( hMetaData, i_min, 4 );
    6500        1612 :             nb_bits = add( nb_bits, 4 );
    6501             :             /* write GR orders */
    6502        1612 :             push_next_indice( hMetaData, sub( GR1, 1 ), 1 );
    6503        1612 :             nb_bits = add( nb_bits, 1 );
    6504        1612 :             IF( EQ_16( GR1, 2 ) )
    6505             :             {
    6506        1233 :                 push_next_indice( hMetaData, GR2, 1 );
    6507        1233 :                 nb_bits = add( nb_bits, 1 );
    6508             :             }
    6509             : 
    6510             :             /* write GR data */
    6511        9246 :             FOR( i = 1; i <= i_min; i++ )
    6512             :             {
    6513        7634 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, q_idx[i], 100, GR1 );
    6514             :             }
    6515             : 
    6516       21582 :             FOR( i = i_min + 1; i < len_stream; i++ )
    6517             :             {
    6518       19970 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, q_idx[i], 100, GR2 );
    6519             :             }
    6520             :         }
    6521             :         ELSE
    6522             :         {
    6523             :             /* len_stream <= 8 */
    6524             :             /* write GR order */
    6525         250 :             push_next_indice( hMetaData, GR1, 1 );
    6526         250 :             nb_bits = add( nb_bits, 1 );
    6527        1226 :             FOR( i = 1; i < len_stream; i++ )
    6528             :             {
    6529         976 :                 ivas_qmetadata_encode_extended_gr_fx( hMetaData, q_idx[i], 100, GR1 );
    6530             :             }
    6531             :         }
    6532             : 
    6533        1862 :         nb_bits = add( nb_bits, nb_GR_min );
    6534             : 
    6535        1862 :         assert( nb_bits == ( hMetaData->nb_bits_tot - bits_pos ) );
    6536             :     }
    6537             : 
    6538        1862 :     return nb_bits;
    6539             : }
    6540             : 
    6541             : 
    6542             : /*-------------------------------------------------------------------------
    6543             :  * ivas_omasa_encode_masa_to_total()
    6544             :  *
    6545             :  *------------------------------------------------------------------------*/
    6546        1862 : void ivas_omasa_encode_masa_to_total_fx(
    6547             :     Word32 masa_to_total_energy_ratio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q30 */
    6548             :     BSTR_ENC_HANDLE hMetaData,
    6549             :     const Word16 low_bitrate_mode,
    6550             :     const Word16 nbands,
    6551             :     const Word16 nblocks )
    6552             : {
    6553             :     Word16 i, j, k;
    6554             :     Word32 data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS]; // Q30
    6555             :     Word32 q_dct_data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS];
    6556        1862 :     Word32 step = STEP_M2T_FX;
    6557             :     Word16 q_idx[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS];
    6558             :     Word32 dct_data_tmp[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS];
    6559             :     Word32 dct_data[MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS];
    6560             :     Word16 bits_pos, nb_bits;
    6561             :     Word16 n_streams, len_stream, tmp_e;
    6562             :     Word32 L_tmp;
    6563        1862 :     move32();
    6564        1862 :     move16();
    6565             : 
    6566        1862 :     set32_fx( q_dct_data, 0, MAX_PARAM_SPATIAL_SUBFRAMES * MASA_FREQUENCY_BANDS );
    6567        1862 :     bits_pos = hMetaData->nb_bits_tot;
    6568        1862 :     k = 0;
    6569        1862 :     move16();
    6570        1862 :     move16();
    6571       13722 :     FOR( i = 0; i < nbands; i++ )
    6572             :     {
    6573       42302 :         FOR( j = 0; j < nblocks; j++ )
    6574             :         {
    6575       30442 :             data[k] = L_shr( masa_to_total_energy_ratio[j][i], Q5 );
    6576       30442 :             move32();
    6577       30442 :             k = add( k, 1 );
    6578             :         }
    6579             :     }
    6580             : 
    6581             :     /* DCT2 transform */
    6582        1862 :     n_streams = 1;
    6583        1862 :     move16();
    6584        1862 :     len_stream = imult1616( nbands, nblocks );
    6585        1862 :     SWITCH( len_stream )
    6586             :     {
    6587          24 :         case 4:
    6588          24 :             matrix_product_fx( dct4_fx, nblocks, nblocks, 0, data, 1, nblocks, 1, dct_data );
    6589          24 :             n_streams = 1;
    6590          24 :             len_stream = 4;
    6591          24 :             move16();
    6592          24 :             BREAK;
    6593         226 :         case 5:
    6594         226 :             matrix_product_fx( dct5_fx, nbands, nbands, 0, data, 1, nbands, 1, dct_data );
    6595         226 :             n_streams = 1;
    6596         226 :             len_stream = nbands;
    6597         226 :             move16();
    6598         226 :             move16();
    6599         226 :             BREAK;
    6600           0 :         case 8:
    6601           0 :             matrix_product_fx( dct8_fx, nbands, nbands, 0, data, 1, nbands, 1, dct_data );
    6602           0 :             n_streams = 1;
    6603           0 :             len_stream = nbands;
    6604           0 :             move16();
    6605           0 :             BREAK;
    6606         378 :         case 12:
    6607         378 :             matrix_product_fx( dct12_fx, nbands, nbands, 0, data, 1, nbands, 1, dct_data );
    6608         378 :             n_streams = 1;
    6609         378 :             len_stream = nbands;
    6610         378 :             move16();
    6611         378 :             move16();
    6612         378 :             BREAK;
    6613        1234 :         case 20:
    6614        1234 :             matrix_product_fx( dct5_fx, nbands, nbands, 0, data, nblocks, nbands, 1, dct_data_tmp );
    6615        1234 :             matrix_product_fx( dct_data_tmp, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 1, dct_data );
    6616        1234 :             n_streams = 1;
    6617        1234 :             len_stream = imult1616( nbands, nblocks );
    6618        1234 :             move16();
    6619        1234 :             move16();
    6620        1234 :             BREAK;
    6621           0 :         case 32:
    6622           0 :             matrix_product_fx( dct8_fx, nbands, nbands, 0, data, nblocks, nbands, 1, dct_data_tmp );
    6623           0 :             matrix_product_fx( dct_data_tmp, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 1, dct_data );
    6624           0 :             n_streams = nblocks;
    6625           0 :             len_stream = nbands;
    6626           0 :             move16();
    6627           0 :             move16();
    6628           0 :             BREAK;
    6629           0 :         default:
    6630           0 :             printf( "Incorrect number of coefficients for OMASA.\n" );
    6631           0 :             BREAK;
    6632             :     }
    6633             : 
    6634        3724 :     FOR( k = 0; k < n_streams; k++ )
    6635             :     {
    6636        1862 :         j = imult1616( k, len_stream );
    6637             :         /* quantize with fixed common step */
    6638        1862 :         L_tmp = BASOP_Util_Divide3232_Scale_newton( dct_data[j], step, &tmp_e );
    6639        1862 :         tmp_e = add( tmp_e, Q6 );
    6640        1862 :         q_idx[j] = rint_new_fx( L_shr( L_tmp, sub( 15, tmp_e ) ) /* Q16 */ ); // Q0
    6641        1862 :         move16();
    6642             : 
    6643        1862 :         IF( GT_16( q_idx[j], ( ( 1 << BITS_MASA2TOTTAL_DCT0 ) - 1 ) ) ) /* limit DCT0 to BITS_MASA2TOTTAL_DCT0 bit representation */
    6644             :         {
    6645           0 :             q_idx[j] = ( ( 1 << BITS_MASA2TOTTAL_DCT0 ) - 1 );
    6646           0 :             move16();
    6647             :         }
    6648             : 
    6649        1862 :         q_dct_data[j] = Mpy_32_16_1( step, shl( q_idx[j], 9 ) /* Q9 */ ); // Q25
    6650        1862 :         move16();
    6651             : 
    6652        1862 :         IF( q_idx[j] == 0 )
    6653             :         {
    6654           0 :             set16_fx( &q_idx[j], 0, len_stream );
    6655           0 :             set32_fx( &q_dct_data[j], 0, len_stream );
    6656             :         }
    6657             :         ELSE
    6658             :         {
    6659       30442 :             FOR( i = 1; i < len_stream; i++ )
    6660             :             {
    6661       28580 :                 L_tmp = BASOP_Util_Divide3232_Scale_newton( dct_data[j + i], step, &tmp_e );
    6662       28580 :                 tmp_e = add( tmp_e, Q6 );
    6663       28580 :                 q_idx[j + i] = rint_new_fx( L_shr( L_tmp, sub( 15, tmp_e ) ) );
    6664       28580 :                 move16();
    6665       28580 :                 q_dct_data[j + i] = Mpy_32_16_1( step, shl( q_idx[j + i], 9 ) /* Q9 */ ); // Q25
    6666       28580 :                 move32();
    6667       28580 :                 IF( q_idx[j + i] <= 0 )
    6668             :                 {
    6669       19960 :                     q_idx[j + i] = imult1616( -2, q_idx[j + i] );
    6670       19960 :                     move16();
    6671             :                 }
    6672             :                 ELSE
    6673             :                 {
    6674        8620 :                     q_idx[j + i] = sub( imult1616( 2, q_idx[j + i] ), 1 );
    6675        8620 :                     move16();
    6676             :                 }
    6677             :             }
    6678             :         }
    6679             :     }
    6680             : 
    6681             :     /* write data */
    6682        1862 :     nb_bits = 0;
    6683        1862 :     move16();
    6684        3724 :     FOR( i = 0; i < n_streams; i++ )
    6685             :     {
    6686        1862 :         nb_bits = add( nb_bits, write_stream_dct_coeffs_omasa_fx( &q_idx[i * len_stream], len_stream, hMetaData, ( i == 0 ), low_bitrate_mode ) );
    6687             :     }
    6688             : 
    6689             :     /* reconstruct masa2total */
    6690        1862 :     q_dct_data[0] = Mpy_32_16_1( step, shl( q_idx[0], 9 ) /* Q9 */ ); // Q25
    6691        1862 :     move32();
    6692       30442 :     FOR( i = 1; i < len_stream; i++ )
    6693             :     {
    6694       28580 :         IF( ( q_idx[i] % 2 ) == 0 )
    6695             :         {
    6696       19960 :             q_dct_data[i] = L_negate( Mpy_32_16_1( step, shl( q_idx[i], 8 ) /* Q9 */ ) ); // Q25
    6697       19960 :             move32();
    6698             :         }
    6699             :         ELSE
    6700             :         {
    6701        8620 :             q_dct_data[i] = Mpy_32_16_1( step, shl( add( q_idx[i], 1 ), 8 ) /* Q9 */ ); // Q25
    6702        8620 :             move32();
    6703             :         }
    6704             :     }
    6705             : 
    6706             :     /* inverse DCT2 transform */
    6707        1862 :     SWITCH( len_stream )
    6708             :     {
    6709          24 :         case 4:
    6710          24 :             matrix_product_q30_fx( dct4_fx, nblocks, nblocks, 1, q_dct_data, nblocks, 1, 0, dct_data_tmp );
    6711          24 :             Copy32( dct_data_tmp, q_dct_data, nblocks );
    6712          24 :             BREAK;
    6713         226 :         case 5:
    6714         226 :             matrix_product_q30_fx( dct5_fx, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp );
    6715         226 :             Copy32( dct_data_tmp, q_dct_data, nbands );
    6716         226 :             BREAK;
    6717           0 :         case 8:
    6718           0 :             matrix_product_q30_fx( dct8_fx, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp );
    6719           0 :             Copy32( dct_data_tmp, q_dct_data, nbands );
    6720           0 :             BREAK;
    6721         378 :         case 12:
    6722         378 :             matrix_product_q30_fx( dct12_fx, nbands, nbands, 1, q_dct_data, nbands, 1, 0, dct_data_tmp );
    6723         378 :             Copy32( dct_data_tmp, q_dct_data, nbands );
    6724         378 :             BREAK;
    6725        1234 :         case 20:
    6726        1234 :             matrix_product_fx( dct5_fx, nbands, nbands, 1, q_dct_data, nbands, nblocks, 0, dct_data_tmp );
    6727        1234 :             matrix_product_q30_fx( dct_data_tmp, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data ); /* reuse of variable*/
    6728        1234 :             BREAK;
    6729           0 :         case 32:
    6730           0 :             matrix_product_fx( dct8_fx, nbands, nbands, 1, q_dct_data, nbands, nblocks, 0, dct_data_tmp );
    6731           0 :             matrix_product_q30_fx( dct_data_tmp, nbands, nblocks, 0, dct4_fx, nblocks, nblocks, 0, q_dct_data );
    6732           0 :             BREAK;
    6733           0 :         default:
    6734           0 :             printf( "Incorrect number of coefficients for OMASA.\n" );
    6735           0 :             BREAK;
    6736             :     }
    6737             : 
    6738        1862 :     k = 0;
    6739        1862 :     move16();
    6740        7498 :     FOR( i = 0; i < nblocks; i++ )
    6741             :     {
    6742       36078 :         FOR( j = 0; j < nbands; j++ )
    6743             :         {
    6744       30442 :             masa_to_total_energy_ratio[i][j] = L_max( 0, q_dct_data[k] );
    6745       30442 :             masa_to_total_energy_ratio[i][j] = L_min( ONE_IN_Q30, masa_to_total_energy_ratio[i][j] ); // Q30
    6746       30442 :             move32();
    6747       30442 :             move32();
    6748       30442 :             k = add( k, 1 );
    6749             :         }
    6750             :     }
    6751        1862 :     assert( nb_bits == ( hMetaData->nb_bits_tot - bits_pos ) );
    6752             : 
    6753             : 
    6754        1862 :     return;
    6755             : }

Generated by: LCOV version 1.14