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

Generated by: LCOV version 1.14