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

Generated by: LCOV version 1.14