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

Generated by: LCOV version 1.14