LCOV - code coverage report
Current view: top level - lib_enc - ivas_qspherical_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 316 360 87.8 %
Date: 2025-10-13 22:24:20 Functions: 6 6 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 "ivas_rom_com.h"
      39             : #include "ivas_stat_enc.h"
      40             : #include "wmc_auto.h"
      41             : #include "prot_fx.h"
      42             : #include "ivas_prot_fx.h"
      43             : 
      44             : 
      45             : /*-----------------------------------------------------------------------*
      46             :  * Local function prototypes
      47             :  *-----------------------------------------------------------------------*/
      48             : static Word32 quantize_theta_phi_fx( Word32 *theta_cb, const Word16 no_th, const Word16 *no_phi_loc, const Word32 abs_theta, Word16 *id_phi, Word16 *id_phi_remap, Word32 *phi_hat, const Word32 phi, const Word16 no_bits, Word16 *id_theta, Word32 *phi_q, const Word16 remap, const MC_LS_SETUP mc_format );
      49             : 
      50             : static Word16 direction_distance_cp_fx( Word32 theta, Word32 theta_hat, Word32 theta_hat1, const Word32 phi, const Word32 phi_hat, const Word32 phi_hat1, Word16 *d1 );
      51             : 
      52             : /*-------------------------------------------------------------------*
      53             :  * quantize_direction_frame()
      54             :  *
      55             :  *
      56             :  *----------------------------------------------------------------------*/
      57      220947 : void quantize_direction_frame_fx(
      58             :     IVAS_QDIRECTION *q_direction,                                                     /* i/o: quantized direction structure            */
      59             :     Word32 azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],   /* o  : Q22                                      */
      60             :     Word32 elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], /* o  : Q22                                      */
      61             :     const Word16 hrmasa_flag                                                          /* i  : flag indicating high-rate MASA MD coding */
      62             : )
      63             : {
      64             :     Word16 i, j;
      65             :     UWord16 idx;
      66             : 
      67             :     /* Quantize directions */
      68      220947 :     q_direction->not_in_2D = 0;
      69      220947 :     move16();
      70     1313371 :     FOR( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
      71             :     {
      72     1092424 :         idx = q_direction->band_data[i].energy_ratio_index_mod[0];
      73     1092424 :         move16();
      74     4957019 :         FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
      75             :         {
      76     3864595 :             if ( azimuth_orig != NULL )
      77             :             {
      78     3864595 :                 azimuth_orig[i][j] = q_direction->band_data[i].azimuth_fx[j];
      79     3864595 :                 move32();
      80             :             }
      81             : 
      82     3864595 :             if ( elevation_orig != NULL )
      83             :             {
      84     3864595 :                 elevation_orig[i][j] = q_direction->band_data[i].elevation_fx[j];
      85     3864595 :                 move32();
      86             :             }
      87             : 
      88             :             /* requantize the direction */
      89     7729190 :             q_direction->band_data[i].spherical_index[j] = quantize_direction_fx( q_direction->band_data[i].elevation_fx[j],
      90     3864595 :                                                                                   q_direction->band_data[i].azimuth_fx[j],
      91     3864595 :                                                                                   q_direction->band_data[i].bits_sph_idx[j],
      92     3864595 :                                                                                   &q_direction->band_data[i].elevation_fx[j],
      93     3864595 :                                                                                   &q_direction->band_data[i].azimuth_fx[j], &q_direction->band_data[i].elevation_index[j],
      94     3864595 :                                                                                   &q_direction->band_data[i].azimuth_index[j],
      95             :                                                                                   q_direction->cfg.mc_ls_setup );
      96     3864595 :             move16();
      97             : 
      98     3864595 :             q_direction->not_in_2D = add( q_direction->not_in_2D, q_direction->band_data[i].elevation_index[j] );
      99     3864595 :             move16();
     100             : 
     101     3864595 :             IF( hrmasa_flag )
     102             :             {
     103      158082 :                 IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
     104             :                 {
     105           0 :                     q_direction->band_data[i].elevation_m_alphabet[j] = no_theta_masa[bits_direction_masa[0] - 3];
     106           0 :                     q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[0] - 1][q_direction->band_data[i].elevation_index[j]];
     107           0 :                     move16();
     108           0 :                     move16();
     109             :                 }
     110             :                 ELSE
     111             :                 {
     112      158082 :                     q_direction->band_data[i].elevation_m_alphabet[j] = sub( imult1616( no_theta_masa[bits_direction_masa[0] - 3], 2 ), 1 );
     113      158082 :                     q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[0] - 1][( q_direction->band_data[i].elevation_index[j] + 1 ) >> 1];
     114      158082 :                     move16();
     115      158082 :                     move16();
     116             :                 }
     117             :             }
     118             :             ELSE
     119             :             {
     120     3706513 :                 IF( NE_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
     121             :                 {
     122       25889 :                     q_direction->band_data[i].elevation_m_alphabet[j] = no_theta_masa[bits_direction_masa[idx] - 3];
     123       25889 :                     q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[idx] - 1][q_direction->band_data[i].elevation_index[j]];
     124       25889 :                     move16();
     125       25889 :                     move16();
     126             :                 }
     127             :                 ELSE
     128             :                 {
     129     3680624 :                     q_direction->band_data[i].elevation_m_alphabet[j] = sub( imult1616( no_theta_masa[bits_direction_masa[idx] - 3], 2 ), 1 );
     130     3680624 :                     q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[idx] - 1][( q_direction->band_data[i].elevation_index[j] + 1 ) >> 1];
     131     3680624 :                     move16();
     132     3680624 :                     move16();
     133             :                 }
     134             :             }
     135             : 
     136     3864595 :             if ( EQ_16( q_direction->band_data[i].azimuth_index[j], MASA_NO_INDEX ) )
     137             :             {
     138        3080 :                 q_direction->band_data[i].azimuth_index[j] = 0;
     139        3080 :                 move16();
     140             :             }
     141             : 
     142     3864595 :             IF( LE_16( q_direction->band_data[i].bits_sph_idx[j], 2 ) )
     143             :             {
     144           0 :                 q_direction->band_data[i].elevation_index[j] = 0;
     145           0 :                 move16();
     146             :             }
     147             :             ELSE
     148             :             {
     149     3864595 :                 IF( EQ_32( q_direction->cfg.mc_ls_setup, MC_LS_SETUP_INVALID ) )
     150             :                 {
     151             :                     /*deorder elevation indexing*/
     152     3838706 :                     IF( s_and( q_direction->band_data[i].elevation_index[j], 1 ) != 0 )
     153             :                     {
     154      738136 :                         q_direction->band_data[i].elevation_index[j] = add( shr( add( q_direction->band_data[i].elevation_index[j], 1 ), 1 ), shr( q_direction->band_data[i].elevation_m_alphabet[j], 1 ) );
     155      738136 :                         move16();
     156             :                     }
     157             :                     ELSE
     158             :                     {
     159             :                         // q_direction->band_data[i].elevation_index[j] = -( ( q_direction->band_data[i].elevation_index[j] ) >> 1 ) + ( q_direction->band_data[i].elevation_m_alphabet[j] >> 1 );
     160     3100570 :                         q_direction->band_data[i].elevation_index[j] = sub( shr( q_direction->band_data[i].elevation_m_alphabet[j], 1 ), shr( ( q_direction->band_data[i].elevation_index[j] ), 1 ) );
     161     3100570 :                         move16();
     162             :                     }
     163             :                 }
     164             :             }
     165             :         }
     166             :     }
     167             : 
     168      220947 :     if ( q_direction->not_in_2D > 0 )
     169             :     {
     170      194415 :         q_direction->not_in_2D = 1 + MASA_LIMIT_2D;
     171      194415 :         move16();
     172             :     }
     173             : 
     174      220947 :     return;
     175             : }
     176             : 
     177             : 
     178             : /*-------------------------------------------------------------------*
     179             :  * quantize_direction_frame2D()
     180             :  *
     181             :  *
     182             :  *----------------------------------------------------------------------*/
     183       10150 : void quantize_direction_frame2D_fx(
     184             :     IVAS_QDIRECTION *q_direction,                                                      /* i/o: quantized direction structure   */
     185             :     Word32 azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],    // Q22
     186             :     Word32 elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES] ) // Q22
     187             : {
     188             :     Word16 i, j;
     189             :     UWord16 idx;
     190             :     /* Quantize directions */
     191       10150 :     q_direction->not_in_2D = 0;
     192       10150 :     move16();
     193       54544 :     FOR( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
     194             :     {
     195       44394 :         idx = q_direction->band_data[i].energy_ratio_index[0];
     196       44394 :         move16();
     197      128055 :         FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
     198             :         {
     199       83661 :             if ( azimuth_orig != NULL )
     200             :             {
     201       83661 :                 azimuth_orig[i][j] = q_direction->band_data[i].azimuth_fx[j];
     202       83661 :                 move32();
     203             :             }
     204       83661 :             if ( elevation_orig != NULL )
     205             :             {
     206       83661 :                 elevation_orig[i][j] = q_direction->band_data[i].elevation_fx[j];
     207       83661 :                 move32();
     208             :             }
     209       83661 :             q_direction->band_data[i].azimuth_m_alphabet[j] = no_phi_masa[bits_direction_masa[idx] - 1][0];
     210       83661 :             move16();
     211             : 
     212             :             /* requantize the direction */
     213      167322 :             q_direction->band_data[i].spherical_index[j] = quantize_direction2D_fx( q_direction->band_data[i].azimuth_fx[j],
     214       83661 :                                                                                     q_direction->band_data[i].azimuth_m_alphabet[j],
     215       83661 :                                                                                     &q_direction->band_data[i].azimuth_fx[j],
     216       83661 :                                                                                     &q_direction->band_data[i].azimuth_index[j],
     217             :                                                                                     q_direction->cfg.mc_ls_setup );
     218       83661 :             move16();
     219             : 
     220       83661 :             q_direction->band_data[i].elevation_m_alphabet[j] = 1;
     221       83661 :             move16();
     222             :         }
     223             :     }
     224             : 
     225       10150 :     return;
     226             : }
     227             : 
     228             : /*-------------------------------------------------------------------*
     229             :  * small_requantize_direction_frame()
     230             :  *
     231             :  *
     232             :  *----------------------------------------------------------------------*/
     233        8070 : void small_requantize_direction_frame_fx(
     234             :     IVAS_QDIRECTION *q_direction,                                                     /* i/o: quantized direction structure   */
     235             :     Word32 azimuth_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES],   // Q22
     236             :     Word32 elevation_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], // Q22
     237             :     const Word16 raw_flag[MASA_MAXIMUM_CODING_SUBBANDS],
     238             :     Word16 bits_dir_bands[MASA_MAXIMUM_CODING_SUBBANDS],
     239             :     Word16 *diff )
     240             : {
     241             :     Word16 i, j;
     242             :     UWord16 bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES];
     243             : 
     244        8070 :     test();
     245        8070 :     IF( ( *diff > 0 ) && ( q_direction->not_in_2D > 0 ) )
     246             :     {
     247       35082 :         FOR( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
     248             :         {
     249      142225 :             FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
     250             :             {
     251      113780 :                 bits_dir[i][j] = q_direction->band_data[i].bits_sph_idx[j];
     252      113780 :                 move16();
     253             :             }
     254             :         }
     255             : 
     256        6637 :         small_reduction_direction_fx( q_direction, bits_dir, raw_flag, diff );
     257             : 
     258        6637 :         IF( *diff <= 0 )
     259             :         {
     260        6474 :             FOR( i = q_direction->cfg.start_band; i < q_direction->cfg.nbands; i++ )
     261             :             {
     262        5163 :                 IF( EQ_16( raw_flag[i], 1 ) )
     263             :                 {
     264        4456 :                     bits_dir_bands[i] = 0;
     265        4456 :                     move16();
     266       22280 :                     FOR( j = 0; j < q_direction->cfg.nblocks; j++ )
     267             :                     {
     268       17824 :                         bits_dir_bands[i] = add( bits_dir_bands[i], bits_dir[i][j] );
     269       17824 :                         move16();
     270       17824 :                         q_direction->band_data[i].bits_sph_idx[j] = bits_dir[i][j];
     271       17824 :                         move16();
     272             : 
     273             :                         /* requantize the direction */
     274       35648 :                         q_direction->band_data[i].spherical_index[j] = quantize_direction_fx(
     275       17824 :                             elevation_orig[i][j], azimuth_orig[i][j],
     276       17824 :                             q_direction->band_data[i].bits_sph_idx[j],
     277       17824 :                             &q_direction->band_data[i].elevation_fx[j], &q_direction->band_data[i].azimuth_fx[j],
     278       17824 :                             &q_direction->band_data[i].elevation_index[j], &q_direction->band_data[i].azimuth_index[j],
     279             :                             q_direction->cfg.mc_ls_setup );
     280       17824 :                         move16();
     281             : 
     282       17824 :                         if ( EQ_32( q_direction->band_data[i].azimuth_index[j], MASA_NO_INDEX ) )
     283             :                         {
     284          20 :                             q_direction->band_data[i].azimuth_index[j] = 0;
     285          20 :                             move16();
     286             :                         }
     287             :                     }
     288             :                 }
     289             :             }
     290             :         }
     291             :     }
     292             : 
     293        8070 :     return;
     294             : }
     295             : 
     296             : /*-------------------------------------------------------------------*
     297             :  * quantize_direction()
     298             :  *
     299             :  *
     300             :  *----------------------------------------------------------------------*/
     301             : /*! r: quantized spherical index */
     302     4023044 : UWord16 quantize_direction_fx(
     303             :     const Word32 theta,         /* i  : input elevation value, Q22        */
     304             :     Word32 phi,                 /* i  : input azimuth value, Q22          */
     305             :     const Word16 no_bits,       /* i  : number of bits                    */
     306             :     Word32 *theta_q,            /* o  : quantized elevation, Q22          */
     307             :     Word32 *phi_q,              /* o  : quantized azimuth, Q22            */
     308             :     UWord16 *index_theta,       /* o  : quantized elevation index         */
     309             :     UWord16 *index_phi,         /* o  : quantized azimuth index           */
     310             :     const MC_LS_SETUP mc_format /* i  : channel format if in MC-mode      */
     311             : )
     312             : {
     313             :     Word32 abs_theta, theta_hat, phi_hat;
     314             :     Word16 i, sign_th;
     315             :     Word16 cum_n[500];
     316             :     Word16 id_th, id_phi;
     317             :     Word32 theta_cb[MAX_NO_THETA];
     318             :     Word16 no_th;
     319             :     UWord16 idx_sph;
     320             :     Word16 id_phi_remap;
     321             : 
     322     4023044 :     set32_fx( theta_cb, 0, MAX_NO_THETA );
     323             : 
     324     4023044 :     IF( no_bits == 0 )
     325             :     {
     326           0 :         *theta_q = 0;
     327           0 :         *phi_q = 0;
     328           0 :         *index_theta = MASA_NO_INDEX;
     329           0 :         *index_phi = MASA_NO_INDEX;
     330           0 :         move32();
     331           0 :         move32();
     332           0 :         move16();
     333           0 :         move16();
     334             : 
     335           0 :         return 0;
     336             :     }
     337             : 
     338     4023044 :     IF( EQ_16( no_bits, 1 ) )
     339             :     {
     340           0 :         *theta_q = 0;
     341           0 :         *index_theta = MASA_NO_INDEX;
     342           0 :         move32();
     343           0 :         move16();
     344             : 
     345           0 :         test();
     346           0 :         IF( LT_32( phi, ( -DEGREE_90_Q_22 ) ) || GT_32( phi, DEGREE_90_Q_22 ) )
     347             :         {
     348           0 :             *phi_q = -DEGREE_180_Q_22;
     349           0 :             *index_phi = 1;
     350           0 :             move32();
     351           0 :             move16();
     352             : 
     353           0 :             return 1;
     354             :         }
     355             :         ELSE
     356             :         {
     357           0 :             *phi_q = 0;
     358           0 :             *index_phi = 0;
     359           0 :             move32();
     360           0 :             move16();
     361             : 
     362           0 :             return 0;
     363             :         }
     364             :     }
     365             : 
     366     4023044 :     IF( EQ_16( no_bits, 2 ) )
     367             :     {
     368         691 :         *theta_q = 0;
     369         691 :         *index_theta = MASA_NO_INDEX;
     370         691 :         move32();
     371         691 :         move16();
     372         691 :         IF( NE_32( mc_format, MC_LS_SETUP_INVALID ) )
     373             :         {
     374          15 :             id_phi = quantize_phi_chan_lbr_fx( phi, &phi_hat, no_phi_masa[no_bits - 1][0] );
     375          15 :             phi_hat = L_add( phi_hat, DEGREE_180_Q_22 );
     376          15 :             idx_sph = id_phi;
     377          15 :             *phi_q = L_sub( phi_hat, DEGREE_180_Q_22 );
     378          15 :             id_phi_remap = id_phi;
     379          15 :             *index_phi = id_phi_remap;
     380          15 :             move16();
     381          15 :             move32();
     382          15 :             move16();
     383          15 :             move16();
     384             :         }
     385             :         ELSE
     386             :         {
     387         676 :             id_phi = quantize_phi_enc_fx( L_add( phi, DEGREE_180_Q_22 ), 0, &phi_hat, no_phi_masa[no_bits - 1][0] );
     388         676 :             idx_sph = id_phi;
     389         676 :             *phi_q = L_sub( phi_hat, DEGREE_180_Q_22 );
     390         676 :             id_phi_remap = ivas_qmetadata_reorder_generic_fx( sub( id_phi, shr( no_phi_masa[no_bits - 1][0], 1 ) ) );
     391         676 :             *index_phi = id_phi_remap;
     392         676 :             move16();
     393         676 :             move32();
     394         676 :             move16();
     395             :         }
     396             : 
     397         691 :         return idx_sph;
     398             :     }
     399             : 
     400     4022353 :     no_th = no_theta_masa[no_bits - 3];
     401     4022353 :     move16();
     402             : 
     403    32387524 :     FOR( i = 0; i < no_th; i++ )
     404             :     {
     405    28365171 :         theta_cb[i] = imult3216( delta_theta_masa_fx[no_bits - 3], i );
     406    28365171 :         move32();
     407             :     }
     408             : 
     409     4022353 :     if ( GT_32( theta_cb[i - 1], DEGREE_90_Q_22 ) )
     410             :     {
     411     1739177 :         theta_cb[i - 1] = DEGREE_90_Q_22;
     412     1739177 :         move32();
     413             :     }
     414             : 
     415     4022353 :     phi = L_add( phi, DEGREE_180_Q_22 );
     416             : 
     417     4022353 :     IF( theta < 0 )
     418             :     {
     419     2032520 :         abs_theta = L_negate( theta );
     420     2032520 :         sign_th = -1;
     421     2032520 :         move16();
     422             :     }
     423             :     ELSE
     424             :     {
     425     1989833 :         abs_theta = theta;
     426     1989833 :         sign_th = 1;
     427     1989833 :         move32();
     428     1989833 :         move16();
     429             :     }
     430             : 
     431     4022353 :     theta_hat = quantize_theta_phi_fx( theta_cb, no_th, no_phi_masa[no_bits - 1], abs_theta, &id_phi,
     432             :                                        &id_phi_remap, &phi_hat, phi, no_bits, &id_th, phi_q, 1, mc_format );
     433             : 
     434     4022353 :     IF( NE_32( mc_format, MC_LS_SETUP_INVALID ) )
     435             :     {
     436             :         /* indexing only for upper hemisphere */
     437       33268 :         cum_n[0] = no_phi_masa[no_bits - 1][0];
     438       33268 :         move16();
     439      166595 :         FOR( i = 1; i < no_th; i++ )
     440             :         {
     441      133327 :             cum_n[i] = add( cum_n[i - 1], no_phi_masa[no_bits - 1][i] );
     442      133327 :             move16();
     443             :         }
     444             : 
     445       33268 :         IF( LT_16( id_phi, MASA_NO_INDEX ) )
     446             :         {
     447       33150 :             IF( id_th == 0 )
     448             :             {
     449        4245 :                 idx_sph = id_phi;
     450        4245 :                 move16();
     451             :             }
     452             :             ELSE
     453             :             {
     454       28905 :                 idx_sph = add( cum_n[id_th - 1], id_phi );
     455             :             }
     456             :         }
     457             :         ELSE{
     458         118 :             IF( id_th == 0 ){
     459           0 :                 idx_sph = 0;
     460           0 :         move16();
     461             :     }
     462             :     ELSE
     463             :     {
     464         118 :         idx_sph = cum_n[id_th - 1];
     465         118 :         move16();
     466             :     }
     467             : }
     468       33268 : *theta_q = theta_hat;
     469       33268 : move32();
     470       33268 : IF( EQ_32( theta_hat, DEGREE_90_Q_22 ) )
     471             : {
     472         118 :     *phi_q = 0;
     473         118 :     id_phi = MASA_NO_INDEX;
     474         118 :     move32();
     475         118 :     move16();
     476             : }
     477             : ELSE
     478             : {
     479       33150 :     *phi_q = L_sub( phi_hat, DEGREE_180_Q_22 );
     480       33150 :     move32();
     481             : }
     482       33268 : *index_theta = id_th;
     483       33268 : *index_phi = id_phi_remap;
     484       33268 : move16();
     485       33268 : move16();
     486             : }
     487             : ELSE
     488             : {
     489             :     /* Starting from Equator, alternating positive and negative */
     490     3989085 :     cum_n[0] = no_phi_masa[no_bits - 1][0];
     491     3989085 :     move16();
     492    28198576 :     FOR( i = 1; i < no_th; i++ )
     493             :     {
     494    24209491 :         cum_n[2 * i - 1] = add( cum_n[2 * i - 2], no_phi_masa[no_bits - 1][i] );
     495    24209491 :         cum_n[2 * i] = add( cum_n[2 * i - 1], no_phi_masa[no_bits - 1][i] );
     496    24209491 :         move16();
     497    24209491 :         move16();
     498             :     }
     499             : 
     500     3989085 :     if ( no_th > 0 )
     501             :     {
     502     3989085 :         assert( abs( cum_n[2 * ( no_th - 1 )] ) < 32768 );
     503             :     }
     504             : 
     505     3989085 :     IF( id_th == 0 )
     506             :     {
     507     2098548 :         IF( LT_16( id_phi, MASA_NO_INDEX ) )
     508             :         {
     509     2098548 :             idx_sph = id_phi;
     510     2098548 :             move16();
     511             :         }
     512             :         ELSE
     513             :         {
     514           0 :             idx_sph = 0;
     515           0 :             move16();
     516             :         }
     517             :     }
     518             :     ELSE{
     519     1890537 :         IF( sign_th > 0 ){
     520      754843 :             IF( LT_16( id_phi, MASA_NO_INDEX ) ){
     521      753710 :                 idx_sph = add( cum_n[2 * id_th - 2], id_phi );
     522             : }
     523             : ELSE
     524             : {
     525        1133 :     idx_sph = cum_n[2 * id_th - 2];
     526        1133 :     move16();
     527             : }
     528             : 
     529      754843 : id_th = sub( shl( id_th, 1 ), 1 );
     530             : }
     531             : ELSE
     532             : {
     533     1135694 :     IF( LT_16( id_phi, MASA_NO_INDEX ) )
     534             :     {
     535     1133586 :         idx_sph = add( cum_n[2 * id_th - 1], id_phi );
     536             :     }
     537             :     ELSE
     538             :     {
     539        2108 :         idx_sph = cum_n[2 * id_th - 1];
     540        2108 :         move16();
     541             :     }
     542     1135694 :     id_th = shl( id_th, 1 );
     543             : }
     544             : }
     545             : 
     546     3989085 : *theta_q = imult3216( theta_hat, sign_th );
     547     3989085 : move32();
     548     3989085 : IF( EQ_32( theta_hat, DEGREE_90_Q_22 ) )
     549             : {
     550        3174 :     *phi_q = 0;
     551        3174 :     id_phi = MASA_NO_INDEX;
     552        3174 :     move32();
     553        3174 :     move16();
     554             : }
     555             : ELSE
     556             : {
     557     3985911 :     *phi_q = L_sub( phi_hat, DEGREE_180_Q_22 );
     558     3985911 :     move32();
     559             : }
     560             : 
     561     3989085 : *index_theta = id_th;
     562     3989085 : *index_phi = id_phi_remap;
     563     3989085 : move16();
     564     3989085 : move16();
     565             : }
     566             : 
     567     4022353 : return idx_sph;
     568             : }
     569             : 
     570             : /*-------------------------------------------------------------------*
     571             :  * direction_distance_cp()
     572             :  *
     573             :  * quantization distortion calculated on the sphere
     574             :  *----------------------------------------------------------------------*/
     575             : /*! r: distortion value */
     576     2307619 : static Word16 direction_distance_cp_fx( // Q14
     577             :     Word32 theta,                       /* i  : elevation absolute value, Q22                      */
     578             :     Word32 theta_hat,                   /* i  : quantized elevation value in absolute value, Q22   */
     579             :     Word32 theta_hat1,                  /* i  : quantized elevation value in absolute value, Q22   */
     580             :     const Word32 phi,                   /* i  : azimuth value, Q22                                 */
     581             :     const Word32 phi_hat,               /* i  : quantized azimuth value, Q22                       */
     582             :     const Word32 phi_hat1,              /* i  : quantized azimuth value, Q22                       */
     583             :     Word16 *d1                          /* o  : Q14                                                */
     584             : )
     585             : {
     586             :     Word16 d, ct, st, st1, st2;
     587             :     Word16 theta16, theta_hat16, theta_hat1_16;
     588             :     Word16 tmp, tmp_e, tmp_phi;
     589             : 
     590     2307619 :     theta16 = extract_l( Mpy_32_32( theta, PI_OVER_180_Q22 ) );            // (Q22 + Q22 - 31) = Q13
     591     2307619 :     theta_hat16 = extract_l( Mpy_32_32( theta_hat, PI_OVER_180_Q22 ) );    // (Q22 + Q22 - 31) = Q13
     592     2307619 :     theta_hat1_16 = extract_l( Mpy_32_32( theta_hat1, PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     593             : 
     594     2307619 :     st = getSinWord16( theta16 );        // Q15
     595     2307619 :     ct = getCosWord16( theta16 );        // Q14
     596     2307619 :     st1 = getSinWord16( theta_hat16 );   // Q15
     597     2307619 :     st2 = getSinWord16( theta_hat1_16 ); // Q15
     598             : 
     599             :     // d = st * st1 + ct * ( sqrtf( 1 - st1 * st1 ) ) * cosf( ( phi - phi_hat ) * PI_OVER_180 );
     600             : 
     601             :     /*( phi - phi_hat ) * PI_OVER_180 */
     602     2307619 :     IF( GT_32( L_sub( phi, phi_hat ), _180_IN_Q22 ) )
     603             :     {
     604             :         // cos(360 - theta) = cos(theta)
     605      202912 :         tmp_phi = extract_l( Mpy_32_32( L_sub( _360_IN_Q22, L_sub( phi, phi_hat ) ), PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     606             :     }
     607     2104707 :     ELSE IF( LT_32( L_sub( phi, phi_hat ), -_180_IN_Q22 ) )
     608             :     {
     609             :         // cos(360 + theta) = cos(theta)
     610           0 :         tmp_phi = extract_l( Mpy_32_32( L_add( _360_IN_Q22, L_sub( phi, phi_hat ) ), PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     611             :     }
     612             :     ELSE
     613             :     {
     614     2104707 :         tmp_phi = extract_l( Mpy_32_32( L_sub( phi, phi_hat ), PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     615             :     }
     616             : 
     617     2307619 :     tmp_e = 0;
     618     2307619 :     move16();
     619     2307619 :     tmp = Sqrt16( sub( MAX16B, mult( st1, st1 ) ), &tmp_e );
     620     2307619 :     tmp = shl_sat( tmp, tmp_e ); // Q15
     621             : 
     622     2307619 :     tmp = mult( tmp, shl_sat( getCosWord16( tmp_phi ), 1 ) /* Q15 */ ); // Q15
     623     2307619 :     tmp = mult( tmp, ct /* Q14 */ );                                    // Q14
     624             : 
     625     2307619 :     tmp = add_sat( tmp, shr( mult( st, st1 ), 1 ) /* Q14 */ ); // Q14
     626             : 
     627     2307619 :     d = tmp; // Q14
     628     2307619 :     move16();
     629             : 
     630             :     // *d1 = st * st2 + ct * ( sqrtf( 1 - st2 * st2 ) ) * cosf( ( phi - phi_hat1 ) * PI_OVER_180 );
     631             : 
     632             :     /*( phi - phi_hat1 ) * PI_OVER_180 */
     633     2307619 :     IF( GT_32( L_sub( phi, phi_hat1 ), _180_IN_Q22 ) )
     634             :     {
     635             :         // cos(360 - theta) = cos(theta)
     636      272948 :         tmp_phi = extract_l( Mpy_32_32( L_sub( _360_IN_Q22, L_sub( phi, phi_hat1 ) ), PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     637             :     }
     638     2034671 :     ELSE IF( LT_32( L_sub( phi, phi_hat1 ), -_180_IN_Q22 ) )
     639             :     {
     640             :         // cos(360 + theta) = cos(theta)
     641           0 :         tmp_phi = extract_l( Mpy_32_32( L_add( _360_IN_Q22, L_sub( phi, phi_hat1 ) ), PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     642             :     }
     643             :     ELSE
     644             :     {
     645     2034671 :         tmp_phi = extract_l( Mpy_32_32( L_sub( phi, phi_hat1 ), PI_OVER_180_Q22 ) ); // (Q22 + Q22 - 31) = Q13
     646             :     }
     647             : 
     648     2307619 :     tmp_e = 0;
     649     2307619 :     move16();
     650     2307619 :     tmp = Sqrt16( sub( MAX16B, mult( st2, st2 ) ), &tmp_e );
     651     2307619 :     tmp = shl_sat( tmp, tmp_e ); // Q15
     652             : 
     653     2307619 :     tmp = mult( tmp, shl_sat( getCosWord16( tmp_phi ), 1 ) /* Q15 */ ); // Q15
     654     2307619 :     tmp = mult( tmp, ct /* Q14 */ );                                    // Q14
     655             : 
     656     2307619 :     tmp = add_sat( tmp, shr( mult( st, st2 ), 1 ) /* Q14 */ ); // Q14
     657             : 
     658     2307619 :     *d1 = tmp;
     659     2307619 :     move16();
     660             : 
     661     2307619 :     return d;
     662             : }
     663             : 
     664             : /*-------------------------------------------------------------------*
     665             :  * quantize_theta_phi()
     666             :  *
     667             :  * joint quantization of elevation and azimuth
     668             :  *----------------------------------------------------------------------*/
     669             : /*! r: quantized elevation value */
     670     4022353 : static Word32 quantize_theta_phi_fx( // Q22
     671             :     Word32 *theta_cb,                /* i  : elevation codebook, Q22                                  */
     672             :     const Word16 no_th,              /* i  : elevation codebook size                                  */
     673             :     const Word16 *no_phi_loc,        /* i  : number of azimuth values for each elevation codeword     */
     674             :     const Word32 abs_theta,          /* i  : absolute value of elevation to be quantized, Q22         */
     675             :     Word16 *id_phi,                  /* o  : azimuth index                                            */
     676             :     Word16 *id_phi_remap,            /* o  : remapped azimuth index                                   */
     677             :     Word32 *phi_hat,                 /* o  : quantized azimuth value, Q22                             */
     678             :     const Word32 phi,                /* i  : input azimuth value; to be quantized, Q22                */
     679             :     const Word16 no_bits,            /* i  : number of bits used for quantization                     */
     680             :     Word16 *id_theta,                /* o  : elevation index                                          */
     681             :     Word32 *phi_q,                   /* o  : rotated quantized azimuth, Q22                           */
     682             :     const Word16 remap,              /* i  : flag for remapping                                       */
     683             :     const MC_LS_SETUP mc_format      /* i  : channel format if in MC-mode                             */
     684             : )
     685             : {
     686             :     Word32 theta_hat, theta_hat1, phi_hat1;
     687             :     Word16 theta_hat16, theta_cb16[MAX_NO_THETA];
     688             :     Word16 id_th, id_th1, id_th2, id_ph, id_ph1, s;
     689             :     Word16 d_fx, d1_fx;
     690             : 
     691     4022353 :     set16_fx( theta_cb16, 0, MAX_NO_THETA );
     692             : 
     693     4022353 :     id_th = BASOP_Util_Divide3232_Scale( abs_theta, delta_theta_masa_fx[no_bits - 3], &s );
     694     4022353 :     id_th = shr( id_th, sub( 15, s ) ); // Q0
     695             : 
     696     4022353 :     IF( GE_16( id_th, no_th ) )
     697             :     {
     698          21 :         id_th = sub( no_th, 1 );
     699             :     }
     700     4022353 :     theta_hat = theta_cb[id_th];
     701     4022353 :     move32();
     702             : 
     703     4022353 :     IF( LT_16( id_th, sub( no_th, 1 ) ) )
     704             :     {
     705     3790164 :         Copy_Scale_sig32_16( theta_cb, theta_cb16, MAX_NO_THETA, 0 ); // Q6
     706             : 
     707     3790164 :         id_th = add( id_th, squant_fx( round_fx( abs_theta ), &theta_hat16, &theta_cb16[id_th], 2 ) );
     708             : 
     709     3790164 :         theta_hat = L_deposit_h( theta_hat16 ); // Q6 -> Q22
     710             :     }
     711             : 
     712     4022353 :     IF( GT_16( no_th, 1 ) )
     713             :     {
     714     4022353 :         test();
     715     4022353 :         IF( LT_16( no_th, 6 ) && EQ_32( mc_format, MC_LS_SETUP_INVALID ) )
     716             :         {
     717     2337678 :             IF( id_th == 0 )
     718             :             {
     719     1289674 :                 id_th1 = 1;
     720     1289674 :                 move16();
     721             :             }
     722     1048004 :             ELSE IF( EQ_16( id_th, sub( no_th, 1 ) ) )
     723             :             {
     724      574603 :                 id_th1 = sub( no_th, 2 );
     725             :             }
     726             :             ELSE
     727             :             {
     728      473401 :                 id_th1 = sub( id_th, 1 );
     729      473401 :                 id_th2 = add( id_th, 1 );
     730             : 
     731      473401 :                 if ( GT_32( L_abs( L_sub( abs_theta, theta_cb[id_th1] ) ), L_abs( L_sub( abs_theta, theta_cb[id_th2] ) ) ) )
     732             :                 {
     733      167904 :                     id_th1 = id_th2;
     734      167904 :                     move16();
     735             :                 }
     736             :             }
     737             :         }
     738             :         ELSE
     739             :         {
     740     1684675 :             id_th1 = id_th;
     741     1684675 :             move16();
     742             :         }
     743             : 
     744     4022353 :         IF( GT_16( no_phi_loc[id_th], 1 ) )
     745             :         {
     746             :             /* Note: (id_th % 2 == 1) must be equal to id_th % 2 */
     747     4018994 :             IF( NE_32( mc_format, MC_LS_SETUP_INVALID ) )
     748             :             {
     749       33150 :                 id_ph = quantize_phi_chan_compand_fx( phi, phi_hat, no_phi_loc[id_th], (Word16) GT_32( L_shr( theta_cb[id_th], Q22 ), MC_MASA_THR_ELEVATION ), mc_format );
     750       33150 :                 *id_phi_remap = id_ph;
     751       33150 :                 move16();
     752             :             }
     753             :             ELSE
     754             :             {
     755     3985844 :                 id_ph = quantize_phi_enc_fx( phi, s_and( id_th, 1 ), phi_hat, no_phi_loc[id_th] );
     756             :             }
     757             :         }
     758             :         ELSE
     759             :         {
     760        3359 :             id_ph = MASA_NO_INDEX;
     761        3359 :             *id_phi_remap = MASA_NO_INDEX;
     762        3359 :             *phi_hat = DEGREE_180_Q_22;
     763        3359 :             *phi_q = 0;
     764        3359 :             move16();
     765        3359 :             move16();
     766        3359 :             move32();
     767        3359 :             move32();
     768             :         }
     769             : 
     770     4022353 :         test();
     771     4022353 :         test();
     772     4022353 :         test();
     773     4022353 :         IF( GT_16( no_phi_loc[id_th1], 1 ) && LT_16( id_ph, MASA_NO_INDEX ) && LT_16( no_th, 6 ) && EQ_32( mc_format, MC_LS_SETUP_INVALID ) )
     774             :         {
     775     2307619 :             theta_hat1 = theta_cb[id_th1];
     776     2307619 :             move32();
     777             : 
     778     2307619 :             id_ph1 = quantize_phi_enc_fx( phi, s_and( id_th1, 1 ), &phi_hat1, no_phi_loc[id_th1] );
     779             : 
     780     2307619 :             d_fx = direction_distance_cp_fx( abs_theta, theta_hat, theta_hat1, phi, *phi_hat, phi_hat1, &d1_fx );
     781             : 
     782     2307619 :             IF( GT_16( d1_fx, d_fx ) )
     783             :             {
     784      238739 :                 *phi_hat = phi_hat1;
     785      238739 :                 id_ph = id_ph1;
     786      238739 :                 theta_hat = theta_cb[id_th1];
     787      238739 :                 id_th = id_th1;
     788      238739 :                 move16();
     789      238739 :                 move16();
     790      238739 :                 move32();
     791      238739 :                 move32();
     792             :             }
     793             :         }
     794             :     }
     795             :     ELSE
     796             :     {
     797           0 :         IF( NE_32( mc_format, MC_LS_SETUP_INVALID ) )
     798             :         {
     799           0 :             id_ph = quantize_phi_chan_compand_fx( phi, phi_hat, no_phi_loc[id_th], 0, mc_format );
     800           0 :             *id_phi_remap = id_ph;
     801           0 :             move16();
     802             :         }
     803             :         ELSE
     804             :         {
     805           0 :             id_ph = quantize_phi_enc_fx( phi, s_and( id_th, 1 ), phi_hat, no_phi_loc[id_th] );
     806             :         }
     807             :     }
     808             : 
     809     4022353 :     IF( remap )
     810             :     {
     811     4022353 :         IF( LT_16( id_ph, MASA_NO_INDEX ) )
     812             :         {
     813     4018994 :             *id_phi_remap = ivas_qmetadata_reorder_generic_fx( sub( id_ph, shr( no_phi_loc[id_th], 1 ) ) );
     814     4018994 :             move16();
     815             :         }
     816             :     }
     817             :     ELSE
     818             :     {
     819           0 :         *id_phi_remap = id_ph;
     820           0 :         move16();
     821             :     }
     822             : 
     823     4022353 :     *id_phi = id_ph;
     824     4022353 :     *id_theta = id_th;
     825     4022353 :     move16();
     826     4022353 :     move16();
     827             : 
     828     4022353 :     return theta_hat;
     829             : }

Generated by: LCOV version 1.14