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

Generated by: LCOV version 1.14