LCOV - code coverage report
Current view: top level - lib_com - ivas_qmetadata_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 4c82f1d24d39d0296b18d775f18a006f4c7d024b Lines: 263 270 97.4 %
Date: 2025-05-17 01:59:02 Functions: 14 14 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 <math.h>
      36             : #include "options.h"
      37             : #include "ivas_cnst.h"
      38             : #include "ivas_rom_com.h"
      39             : #include "prot_fx.h"
      40             : #include "cnst.h"
      41             : #include "wmc_auto.h"
      42             : #include "ivas_prot_fx.h"
      43             : #include "ivas_rom_com_fx.h"
      44             : 
      45             : // #include "debug.h"
      46             : 
      47             : /*-----------------------------------------------------------------------*
      48             :  * Local constants
      49             :  *-----------------------------------------------------------------------*/
      50             : 
      51             : #define MASA_DIR_RATIO_COMP_MAX_IDX_STEPS 2
      52             : 
      53             : /*-----------------------------------------------------------------------*
      54             :  * Local function prototypes
      55             :  *-----------------------------------------------------------------------*/
      56             : 
      57             : static void ivas_qmetadata_free_memory_fx( IVAS_QMETADATA_HANDLE hQMetaData );
      58             : 
      59             : 
      60             : /*-----------------------------------------------------------------------*
      61             :  * ivas_qmetadata_open()
      62             :  *
      63             :  * Allocate Q Metadata handle
      64             :  *-----------------------------------------------------------------------*/
      65             : 
      66         588 : ivas_error ivas_qmetadata_open_fx(
      67             :     IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle         */
      68             : )
      69             : {
      70             :     /* allocate  MetaData handle */
      71         588 :     IF( ( *hQMetaData = (IVAS_QMETADATA_HANDLE) malloc( sizeof( IVAS_QMETADATA ) ) ) == NULL )
      72             :     {
      73           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
      74             :     }
      75             : 
      76         588 :     ( *hQMetaData )->q_direction = NULL;
      77         588 :     ( *hQMetaData )->surcoh_band_data = NULL;
      78         588 :     ( *hQMetaData )->bandMap = NULL;
      79             : 
      80         588 :     return IVAS_ERR_OK;
      81             : }
      82             : 
      83             : /*-----------------------------------------------------------------------*
      84             :  * ivas_qmetadata_allocate_memory()
      85             :  *
      86             :  * Allocates dynamic memory for qmetadata. Also reallocates automatically
      87             :  * if relevant parameters have changed. To function properly, this function
      88             :  * assumes that qmetadata contains parameter values for nbands, ndirs and
      89             :  * coherence_flag corresponding to the currently reserved memory. This function
      90             :  * then compares them to provided new values given in call and allocates or
      91             :  * reallocates as necessary. The parameter values in qmetadata are updated
      92             :  * accordingly. In addition, parameters inside qdirection config are
      93             :  * set here to their default values out of practicality.
      94             :  *-----------------------------------------------------------------------*/
      95             : 
      96       49560 : ivas_error ivas_qmetadata_allocate_memory_fx(
      97             :     IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle             */
      98             :     const Word16 nbands,              /* i  : new number of frequency bands */
      99             :     const Word16 ndirs,               /* i  : new number of directions      */
     100             :     const Word16 coherence_flag       /* i  : new coherence coding status   */
     101             : )
     102             : {
     103             :     Word16 j, dir;
     104             :     UWord8 do_realloc;
     105             : 
     106             : 
     107             :     /* Check if we need to reallocate memory or do we need to do the first time allocation. */
     108       49560 :     IF( hQMetaData->q_direction != NULL )
     109             :     {
     110       48972 :         do_realloc = (UWord8) NE_16( nbands, hQMetaData->q_direction->cfg.nbands );
     111       48972 :         do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( ndirs, hQMetaData->no_directions ) );
     112       48972 :         do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( coherence_flag, hQMetaData->coherence_flag ) );
     113             :     }
     114             :     ELSE
     115             :     {
     116         588 :         do_realloc = TRUE;
     117         588 :         move16();
     118             :     }
     119             : 
     120       49560 :     IF( do_realloc )
     121             :     {
     122        3311 :         ivas_qmetadata_free_memory_fx( hQMetaData );
     123             : 
     124        3311 :         hQMetaData->numCodingBands = (UWord8) nbands;
     125        3311 :         move16();
     126        3311 :         hQMetaData->no_directions = ndirs;
     127        3311 :         move16();
     128        3311 :         hQMetaData->coherence_flag = coherence_flag;
     129        3311 :         move16();
     130             : 
     131        3311 :         IF( ( hQMetaData->q_direction = (IVAS_QDIRECTION *) malloc( sizeof( IVAS_QDIRECTION ) * ndirs ) ) == NULL )
     132             :         {
     133           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
     134             :         }
     135             : 
     136        7035 :         FOR( dir = 0; dir < hQMetaData->no_directions; dir++ )
     137             :         {
     138        3724 :             hQMetaData->q_direction[dir].cfg.nbands = nbands;
     139        3724 :             move16();
     140        3724 :             IF( nbands == 0 )
     141             :             {
     142           0 :                 hQMetaData->q_direction[dir].band_data = NULL;
     143             :             }
     144             :             ELSE
     145             :             {
     146        3724 :                 IF( ( hQMetaData->q_direction[dir].band_data = (IVAS_QDIRECTION_BAND_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ) ) == NULL )
     147             :                 {
     148           0 :                     return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
     149             :                 }
     150             : 
     151       30300 :                 FOR( j = 0; j < nbands; j++ )
     152             :                 {
     153       26576 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     154       26576 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     155       26576 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].q_elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     156       26576 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].q_azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     157       26576 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].energy_ratio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     158             :                 }
     159             :             }
     160             : 
     161        3724 :             IF( coherence_flag )
     162             :             {
     163        1609 :                 hQMetaData->q_direction[dir].coherence_band_data = (IVAS_QDIRECTION_BAND_COHERENCE_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_COHERENCE_DATA ) * hQMetaData->q_direction[dir].cfg.nbands );
     164             :             }
     165             :             ELSE
     166             :             {
     167        2115 :                 hQMetaData->q_direction[dir].coherence_band_data = NULL;
     168             :             }
     169             : 
     170             :             /* These default values are set here to get them conveniently in one place */
     171        3724 :             hQMetaData->q_direction[dir].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES;
     172        3724 :             move16();
     173        3724 :             hQMetaData->q_direction[dir].cfg.search_effort = 3;
     174        3724 :             move16();
     175        3724 :             hQMetaData->q_direction[dir].cfg.start_band = 0;
     176        3724 :             move16();
     177        3724 :             hQMetaData->q_direction[dir].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
     178        3724 :             move32();
     179             :         }
     180             : 
     181        3311 :         IF( coherence_flag )
     182             :         {
     183        1346 :             IF( ( hQMetaData->surcoh_band_data = (IVAS_SURROUND_COHERENCE_BAND_DATA *) malloc( sizeof( IVAS_SURROUND_COHERENCE_BAND_DATA ) * hQMetaData->q_direction[0].cfg.nbands ) ) == NULL )
     184             :             {
     185           0 :                 return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" );
     186             :             }
     187             :         }
     188             :         ELSE
     189             :         {
     190        1965 :             hQMetaData->surcoh_band_data = NULL;
     191             :         }
     192             :     }
     193             : 
     194             : 
     195       49560 :     return IVAS_ERR_OK;
     196             : }
     197             : 
     198             : 
     199             : /*-----------------------------------------------------------------------*
     200             :  * ivas_qmetadata_free_memory()
     201             :  *
     202             :  * free dynamic part of Q Metadata memory
     203             :  *-----------------------------------------------------------------------*/
     204             : 
     205        3899 : static void ivas_qmetadata_free_memory_fx(
     206             :     IVAS_QMETADATA_HANDLE hQMetaData /* i/o: q_metadata handle         */
     207             : )
     208             : {
     209             :     Word16 dir;
     210             : 
     211        3899 :     IF( hQMetaData == NULL )
     212             :     {
     213           0 :         return;
     214             :     }
     215             : 
     216        3899 :     IF( hQMetaData->q_direction != NULL )
     217             :     {
     218        7035 :         FOR( dir = 0; dir < hQMetaData->no_directions; dir++ )
     219             :         {
     220        3724 :             IF( hQMetaData->q_direction[dir].band_data != NULL )
     221             :             {
     222        3724 :                 free( hQMetaData->q_direction[dir].band_data );
     223        3724 :                 hQMetaData->q_direction[dir].band_data = NULL;
     224             :             }
     225        3724 :             IF( hQMetaData->q_direction[dir].coherence_band_data != NULL )
     226             :             {
     227        1609 :                 free( hQMetaData->q_direction[dir].coherence_band_data );
     228        1609 :                 hQMetaData->q_direction[dir].coherence_band_data = NULL;
     229             :             }
     230             :         }
     231             : 
     232        3311 :         free( hQMetaData->q_direction );
     233        3311 :         hQMetaData->q_direction = NULL;
     234             :     }
     235             : 
     236        3899 :     IF( hQMetaData->surcoh_band_data != NULL )
     237             :     {
     238        1346 :         free( hQMetaData->surcoh_band_data );
     239        1346 :         hQMetaData->surcoh_band_data = NULL;
     240             :     }
     241             : 
     242        3899 :     return;
     243             : }
     244             : 
     245             : 
     246             : /*-----------------------------------------------------------------------*
     247             :  * ivas_qmetadata_close()
     248             :  *
     249             :  * close Q Metadata
     250             :  *-----------------------------------------------------------------------*/
     251             : 
     252        1159 : void ivas_qmetadata_close_fx(
     253             :     IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle         */
     254             : )
     255             : {
     256        1159 :     test();
     257        1159 :     IF( hQMetaData == NULL || *hQMetaData == NULL )
     258             :     {
     259         571 :         return;
     260             :     }
     261             : 
     262         588 :     ivas_qmetadata_free_memory_fx( *hQMetaData );
     263             : 
     264         588 :     free( *hQMetaData );
     265         588 :     *hQMetaData = NULL;
     266             : 
     267         588 :     return;
     268             : }
     269             : 
     270             : 
     271             : /*-------------------------------------------------------------------------
     272             :  * masa_sq()
     273             :  *
     274             :  * scalar quantization using partition
     275             :  *------------------------------------------------------------------------*/
     276             : 
     277             : /*! r: codeword index */
     278     1028328 : Word16 masa_sq_fx(
     279             :     const Word32 in,         /* i  : input value     Q30*/
     280             :     const Word32 *threshold, /* i  : partition       Q30*/
     281             :     const Word16 cb_sz       /* i  : codebook size   */
     282             : )
     283             : {
     284             :     Word16 i;
     285             : 
     286     5824595 :     FOR( i = 0; i < cb_sz; i++ )
     287             :     {
     288     5824595 :         IF( LT_32( in, threshold[i + 1] ) )
     289             :         {
     290     1028328 :             return i;
     291             :         }
     292             :     }
     293             : 
     294           0 :     return -1;
     295             : }
     296             : 
     297             : /*-------------------------------------------------------------------------
     298             :  * only_reduce_bits_direction()
     299             :  *
     300             :  *
     301             :  *------------------------------------------------------------------------*/
     302             : 
     303        8156 : ivas_error only_reduce_bits_direction_fx(
     304             :     Word16 *reduce_bits_out,
     305             :     IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure   */
     306             :     Word16 reduce_bits,
     307             :     const Word16 coding_subbands,
     308             :     const Word16 no_subframes,
     309             :     Word16 *ind_order )
     310             : {
     311             :     Word16 j, k, red_times, rem, n;
     312             :     Word16 max_nb, delta;
     313             :     Word16 *bits_dir0;
     314             : 
     315             :     Word16 bits_sph_idx_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES];
     316             :     Word32 penalty[MASA_MAXIMUM_CODING_SUBBANDS];
     317             :     Word16 tmp;
     318       46840 :     FOR( j = 0; j < coding_subbands; j++ )
     319             :     {
     320      141727 :         FOR( k = 0; k < no_subframes; k++ )
     321             :         {
     322      103043 :             bits_sph_idx_orig[j][k] = q_direction->band_data[j].bits_sph_idx[k];
     323      103043 :             move16();
     324             :         }
     325             :     }
     326        8156 :     n = 0;
     327        8156 :     move16();
     328        8156 :     delta = 1;
     329        8156 :     move16();
     330             : 
     331        8156 :     IF( reduce_bits > 0 )
     332             :     {
     333        7855 :         red_times = idiv1616( reduce_bits, imult1616( coding_subbands, no_subframes ) ); /* number of complete reductions by 1 bit */
     334        7855 :         IF( red_times > 0 )
     335             :         {
     336       36477 :             FOR( j = 0; j < coding_subbands; j++ )
     337             :             {
     338       30136 :                 bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
     339      121082 :                 FOR( k = 0; k < no_subframes; k++ )
     340             :                 {
     341       90946 :                     bits_dir0[k] = sub( bits_dir0[k], red_times );
     342       90946 :                     move16();
     343       90946 :                     reduce_bits = sub( reduce_bits, red_times );
     344             : 
     345       90946 :                     IF( LT_16( bits_dir0[k], MASA_MIN_BITS_TF ) )
     346             :                     {
     347       13840 :                         reduce_bits = add( reduce_bits, sub( MASA_MIN_BITS_TF, bits_dir0[k] ) );
     348       13840 :                         bits_dir0[k] = MASA_MIN_BITS_TF;
     349       13840 :                         move16();
     350             :                     }
     351             :                 }
     352             :             }
     353             :         }
     354             : 
     355        7855 :         rem = reduce_bits; /* -coding_subbands*no_subframes*red_times; */
     356        7855 :         move16();
     357       17310 :         WHILE( LT_16( n, rem ) )
     358             :         {
     359        9455 :             max_nb = 0;
     360        9455 :             move16();
     361       51665 :             FOR( j = 0; j < coding_subbands; j++ )
     362             :             {
     363       42210 :                 bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
     364      168561 :                 FOR( k = 0; k < no_subframes; k++ )
     365             :                 {
     366      126351 :                     test();
     367      126351 :                     IF( LT_16( n, rem ) && GT_16( bits_dir0[k], sub( MASA_MIN_BITS_TF, delta ) ) )
     368             :                     {
     369       68009 :                         bits_dir0[k] = sub( bits_dir0[k], 1 );
     370       68009 :                         move16();
     371       68009 :                         n = add( n, 1 );
     372             :                     }
     373             : 
     374      126351 :                     if ( LT_16( max_nb, bits_dir0[k] ) )
     375             :                     {
     376       21051 :                         max_nb = bits_dir0[k];
     377       21051 :                         move16();
     378             :                     }
     379             :                 }
     380             :             }
     381             : 
     382        9455 :             IF( LE_16( max_nb, MASA_MIN_BITS_TF ) )
     383             :             {
     384         635 :                 delta = add( delta, 1 );
     385             :             }
     386             :         }
     387             : 
     388        7855 :         reduce_bits = 0;
     389        7855 :         move16();
     390             :     }
     391             : 
     392        8156 :     IF( EQ_16( ind_order[0], -1 ) )
     393             :     {
     394       11768 :         FOR( j = 0; j < coding_subbands; j++ )
     395             :         {
     396        8792 :             ind_order[j] = j;
     397        8792 :             move16();
     398             :         }
     399             :     }
     400             :     ELSE
     401             :     {
     402             : 
     403             :         Word16 m, sorted, index1, index2;
     404             : 
     405       35072 :         FOR( j = 0; j < coding_subbands; j++ )
     406             :         {
     407       29892 :             ind_order[j] = j;
     408       29892 :             move16();
     409             :         }
     410        5180 :         sorted = 0;
     411        5180 :         move16();
     412       19243 :         FOR( m = coding_subbands - 1; m && !sorted; m-- )
     413             :         {
     414       14063 :             sorted = 1;
     415       14063 :             move16();
     416       78854 :             FOR( j = 0; j < m; j++ )
     417             :             {
     418       64791 :                 index1 = ind_order[j];
     419       64791 :                 move16();
     420       64791 :                 index2 = ind_order[j + 1];
     421       64791 :                 move16();
     422       64791 :                 tmp = 0;
     423       64791 :                 move16();
     424      234495 :                 FOR( k = 0; k < no_subframes; k++ )
     425             :                 {
     426      169704 :                     tmp = add( tmp, sub( bits_sph_idx_orig[index1][k], q_direction->band_data[index1].bits_sph_idx[k] ) );
     427             :                 }
     428       64791 :                 penalty[0] = L_shr( W_extract_l( W_mult_32_16( tmp, bits_sph_idx_orig[index2][0] ) ), 1 );
     429       64791 :                 move32();
     430       64791 :                 tmp = 0;
     431       64791 :                 move16();
     432      234495 :                 FOR( k = 0; k < no_subframes; k++ )
     433             :                 {
     434      169704 :                     tmp = add( tmp, sub( bits_sph_idx_orig[index2][k], q_direction->band_data[index2].bits_sph_idx[k] ) );
     435             :                 }
     436       64791 :                 penalty[1] = L_shr( W_extract_l( W_mult_32_16( tmp, bits_sph_idx_orig[index1][0] ) ), 1 );
     437       64791 :                 move32();
     438       64791 :                 IF( LT_32( penalty[0], penalty[1] ) )
     439             :                 {
     440       19373 :                     sorted = 0;
     441       19373 :                     move16();
     442       19373 :                     ind_order[j] = index2;
     443       19373 :                     move16();
     444       19373 :                     ind_order[j + 1] = index1;
     445       19373 :                     move16();
     446             :                 }
     447             :             }
     448             :         }
     449             :     }
     450             : 
     451        8156 :     *reduce_bits_out = negate( reduce_bits );
     452        8156 :     move16();
     453             : 
     454        8156 :     return IVAS_ERR_OK;
     455             : }
     456             : 
     457             : 
     458             : /*---------------------------------------------------------------
     459             :  * update_bits_next_block()
     460             :  *
     461             :  * Transfer the saved bits to the next subbands
     462             :  *---------------------------------------------------------------*/
     463             : 
     464       24897 : void update_bits_next_block_fx(
     465             :     IVAS_QDIRECTION *q_direction, /* i/o: qdirection                    */
     466             :     Word16 *p_diff,               /* i/o: bits to be transferred        */
     467             :     const Word16 j,               /* i  : subband to update bit alloc to*/
     468             :     const Word16 max_i,           /* i  : number of subbands            */
     469             :     const Word16 max_k            /* i  : n umber of subframes          */
     470             : )
     471             : {
     472             :     Word16 diff;
     473             :     Word16 k;
     474       24897 :     diff = *p_diff;
     475       24897 :     move16();
     476       24897 :     IF( diff < 0 )
     477             :     {
     478             :         /* increase bits for next subbands */
     479        8026 :         k = 0;
     480        8026 :         move16();
     481       33084 :         WHILE( diff < 0 && LT_16( j, max_i ) && LT_16( k, max_k ) )
     482             :         {
     483       25058 :             test();
     484       25058 :             test();
     485       25058 :             IF( LT_32( q_direction->band_data[j].bits_sph_idx[k], MASA_DIRECTION_MAX_BITS ) )
     486             :             {
     487       25058 :                 q_direction->band_data[j].bits_sph_idx[k] = (UWord16) L_add( q_direction->band_data[j].bits_sph_idx[k], 1 );
     488       25058 :                 move16();
     489       25058 :                 diff = add( diff, 1 );
     490             :             }
     491       25058 :             k = add( k, 1 );
     492             :         }
     493             :     }
     494             :     ELSE
     495             :     {
     496       16871 :         k = 0;
     497       16871 :         move16();
     498       26299 :         WHILE( diff > 0 && LT_16( k, max_k ) )
     499             :         {
     500        9428 :             test();
     501        9428 :             IF( q_direction->band_data[j].bits_sph_idx[k] > 0 )
     502             :             {
     503        9428 :                 q_direction->band_data[j].bits_sph_idx[k] = (UWord16) L_sub( q_direction->band_data[j].bits_sph_idx[k], 1 );
     504        9428 :                 move16();
     505        9428 :                 diff = sub( diff, 1 );
     506             :             }
     507             :         }
     508             :     }
     509       24897 :     *p_diff = diff;
     510       24897 :     move16();
     511             : 
     512       24897 :     return;
     513             : }
     514             : 
     515             : 
     516             : /*---------------------------------------------------------------
     517             :  * invdct4_transform()
     518             :  *
     519             :  * Inverse DCT transform for 4D vector
     520             :  *---------------------------------------------------------------*/
     521             : 
     522      129221 : void invdct4_transform_fx(
     523             :     Word32 *v_fx,     /* i  : input vector                    q   */
     524             :     UWord8 *invdct_v, /* o  : inverse transformed vector          */
     525             :     Word16 q )
     526             : {
     527             :     Word32 a_fx, b_fx, c_fx, d_fx;
     528             :     Word16 i;
     529             :     Word32 f_invdct_v_fx[4];
     530             : 
     531      129221 :     a_fx = L_add( v_fx[0], v_fx[2] ); // q
     532      129221 :     b_fx = L_sub( v_fx[0], v_fx[2] ); // q
     533             :     // 1.306562964876376f * 2 ^ 30 -> 1402911360, 0.541196100146198f * 2 ^ 30 -> 581104896
     534      129221 :     c_fx = L_shl( L_add( Mpy_32_32( 1402911360, v_fx[1] ), Mpy_32_32( 581104896, v_fx[3] ) ), Q31 - Q30 ); // q
     535      129221 :     d_fx = L_shl( L_sub( Mpy_32_32( 581104896, v_fx[1] ), Mpy_32_32( 1402911360, v_fx[3] ) ), Q31 - Q30 ); // q
     536      129221 :     f_invdct_v_fx[0] = L_shl( L_add( a_fx, c_fx ), 7 );                                                    // q
     537      129221 :     move32();
     538      129221 :     f_invdct_v_fx[1] = L_shl( L_add( b_fx, d_fx ), 7 ); // q
     539      129221 :     move32();
     540      129221 :     f_invdct_v_fx[2] = L_shl( L_sub( b_fx, d_fx ), 7 ); // q
     541      129221 :     move32();
     542      129221 :     f_invdct_v_fx[3] = L_shl( L_sub( a_fx, c_fx ), 7 ); // q
     543      129221 :     move32();
     544             : 
     545      646105 :     FOR( i = 0; i < 4; i++ )
     546             :     {
     547      516884 :         IF( f_invdct_v_fx[i] < 0 )
     548             :         {
     549       59250 :             invdct_v[i] = 0;
     550       59250 :             move16();
     551             :         }
     552             :         ELSE
     553             :         {
     554      457634 :             IF( GT_32( f_invdct_v_fx[i], L_shl( 255, q ) ) )
     555             :             {
     556           2 :                 f_invdct_v_fx[i] = L_shl( 255, q ); // q
     557           2 :                 move32();
     558             :             }
     559      457634 :             invdct_v[i] = (UWord8) L_shr( f_invdct_v_fx[i], q ); // Q0
     560      457634 :             move16();
     561             :         }
     562             :     }
     563             : 
     564      129221 :     return;
     565             : }
     566             : 
     567             : /*---------------------------------------------------------------
     568             :  * masa_compensate_two_dir_energy_ratio_index()
     569             :  *
     570             :  * Calculated compensated direct-to-total ratios for direction
     571             :  * quantization with two directions. This allows maintaining
     572             :  * direction accuracy while reusing one direction quantizers
     573             :  * separately for both directions.
     574             :  *--------------------------------------------------------------*/
     575             : 
     576      204816 : void masa_compensate_two_dir_energy_ratio_index_fx(
     577             :     const Word16 ratio_index_1, /* i  : Input ratio for direction 1           */
     578             :     const Word16 ratio_index_2, /* i  : Input ratio for direction 2           */
     579             :     Word16 *ratio_index_mod1,   /* o  : Output modified ratio for direction 1 */
     580             :     Word16 *ratio_index_mod2,   /* o  : Output modified ratio for direction 2 */
     581             :     const Word16 hodirac_flag   /* i  : flag to indicate HO-DirAC mode        */
     582             : )
     583             : {
     584      204816 :     IF( hodirac_flag )
     585             :     {
     586      192696 :         *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hordiac_ratio1;
     587      192696 :         move16();
     588      192696 :         *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hoardia_ratio2;
     589      192696 :         move16();
     590             :     }
     591             :     ELSE
     592             :     {
     593       12120 :         *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio1;
     594       12120 :         move16();
     595       12120 :         *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio2;
     596       12120 :         move16();
     597             :     }
     598             : 
     599      204816 :     return;
     600             : }
     601             : 
     602             : /*---------------------------------------------------------------
     603             :  * set_qmetadata_maxbit_req()
     604             :  *
     605             :  * Sets proper value for qmetadata_max_bit_req limit
     606             :  *--------------------------------------------------------------*/
     607             : 
     608       49560 : void ivas_set_qmetadata_maxbit_req_fx(
     609             :     IVAS_QMETADATA_HANDLE hQMetaData, /* o  : qmetadata structure where the requirement value is set */
     610             :     const IVAS_FORMAT ivas_format     /* i  : IVAS format                                            */
     611             : )
     612             : {
     613       49560 :     IF( EQ_32( ivas_format, SBA_FORMAT ) )
     614             :     {
     615        2904 :         hQMetaData->qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_SBA;
     616        2904 :         move16();
     617             :     }
     618             :     ELSE /* MASA_FORMAT */
     619             :     {
     620       46656 :         hQMetaData->qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_MASA;
     621       46656 :         move16();
     622             :     }
     623             : 
     624       49560 :     return;
     625             : }
     626             : 
     627             : 
     628             : /*-------------------------------------------------------------------------
     629             :  * ivas_qmetadata_azimuth_elevation_to_direction_vector()
     630             :  *
     631             :  *
     632             :  *------------------------------------------------------------------------*/
     633             : 
     634       20154 : void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx(
     635             :     const Word32 az, /* i  : azimuth                Q22 */
     636             :     const Word32 el, /* i  : elevation              Q22 */
     637             :     Word32 *dv       /* o  : direction vector       Q30 */
     638             : )
     639             : {
     640             :     Word16 radius_length;
     641             :     Word16 elevation_fx, azimuth_fx;
     642             : 
     643             :     // (2 ^ 31 - 1) / 360 -> 5965232
     644       20154 :     elevation_fx = extract_l( L_shr( Mpy_32_32( el, ONE_BY_360_Q31 ), 7 ) ); // ( ( Q22 + Q31 - Q31 ) - Q7 ) -> Q15
     645       20154 :     azimuth_fx = extract_l( L_shr( Mpy_32_32( az, ONE_BY_360_Q31 ), 7 ) );   // ( ( Q22 + Q31 - Q31 ) - Q7 ) -> Q15
     646             : 
     647       20154 :     dv[2] = L_shl( getSineWord16R2( elevation_fx ), Q15 ); /* Q30 */
     648       20154 :     move32();
     649       20154 :     radius_length = getCosWord16R2( elevation_fx );
     650       20154 :     dv[0] = L_mult0( radius_length, getCosWord16R2( azimuth_fx ) ); /* Q30 */
     651       20154 :     move32();
     652       20154 :     dv[1] = L_mult0( radius_length, getSineWord16R2( azimuth_fx ) ); /* Q30 */
     653       20154 :     move32();
     654             : 
     655       20154 :     return;
     656             : }
     657             : 
     658             : /*-------------------------------------------------------------------------
     659             :  * ivas_qmetadata_direction_vector_to_azimuth_elevation()
     660             :  *
     661             :  * azimuth between [-180, 180]
     662             :  * elevation between [-90 and 90]
     663             :  *------------------------------------------------------------------------*/
     664             : 
     665       60000 : void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx(
     666             :     const Word32 *dv, /* i  : direction vector  dv_q     */
     667             :     const Word16 dv_q,
     668             :     Word32 *az, /* o  : azimuth           Q22            */
     669             :     Word32 *el  /* o  : elevation         Q22            */
     670             : )
     671             : {
     672             :     /* note: dv does not need to have unit L_2 norm, because the conversion is scale invariant */
     673             :     Word32 L_tmp;
     674             :     Word16 e_tmp;
     675       60000 :     L_tmp = L_add( Mpy_32_32( dv[0], dv[0] ), Mpy_32_32( dv[1], dv[1] ) ); /* 2 * dv_q - 31 */
     676       60000 :     e_tmp = shl( sub( 31, dv_q ), 1 );
     677       60000 :     L_tmp = Sqrt32( L_tmp, &e_tmp ); // e_tmp
     678             :     // 29335 -> 180 / PI in Q9
     679       60000 :     *el = L_mult0( BASOP_util_atan2( dv[2], L_tmp, sub( sub( 31, dv_q ), e_tmp ) ), 29335 ); /* Q22 */
     680       60000 :     move32();
     681             :     // 29335 -> 180 / PI in Q9
     682       60000 :     *az = L_mult0( BASOP_util_atan2( dv[1], dv[0], 0 ), 29335 ); /* Q22 */
     683       60000 :     move32();
     684       60000 :     return;
     685             : }
     686             : 
     687             : 
     688             : /*-------------------------------------------------------------------------
     689             :  * ivas_get_df_ratio_bits_hodirac()
     690             :  *
     691             :  *
     692             :  *------------------------------------------------------------------------*/
     693             : 
     694             : /*! r: bits to be used for quantizing ratio of ratios */
     695      192696 : Word16 ivas_get_df_ratio_bits_hodirac_fx(
     696             :     const Word16 index_diff /* i  : index of quantized diffuse-to-total ratio */
     697             : )
     698             : {
     699             :     Word16 dfRatio_bits;
     700             : 
     701      192696 :     IF( GE_16( index_diff, DIFF_DFRATIO_1BIT_LIMIT_IDX ) )
     702             :     {
     703       91724 :         dfRatio_bits = 1;
     704       91724 :         move16();
     705             :     }
     706      100972 :     ELSE IF( GE_16( index_diff, DIFF_DFRATIO_2BIT_LIMIT_IDX_HODIRAC ) )
     707             :     {
     708       49201 :         dfRatio_bits = 2;
     709       49201 :         move16();
     710             :     }
     711             :     ELSE
     712             :     {
     713       51771 :         dfRatio_bits = 3;
     714       51771 :         move16();
     715             :     }
     716             : 
     717      192696 :     return dfRatio_bits;
     718             : }
     719             : 
     720             : /*---------------------------------------------------------------
     721             :  * ivas_get_df_ratio_bits()
     722             :  *
     723             :  * Gives quantization accuracy for distribution factor of
     724             :  * direct-to-total ratios based on the diffuse-to-total ratio
     725             :  * index
     726             :  *--------------------------------------------------------------*/
     727             : 
     728             : /*! r: bits to be used for quantizing ratio of ratios */
     729       12120 : Word16 ivas_get_df_ratio_bits_fx(
     730             :     const Word16 index_diff /* i  : index of quantized diffuse-to-total ratio */
     731             : )
     732             : {
     733             :     Word16 dfRatio_bits;
     734             : 
     735       12120 :     IF( GE_16( index_diff, DIFF_DFRATIO_1BIT_LIMIT_IDX ) )
     736             :     {
     737         252 :         dfRatio_bits = 1;
     738         252 :         move16();
     739             :     }
     740       11868 :     ELSE IF( GE_16( index_diff, DIFF_DFRATIO_2BIT_LIMIT_IDX ) )
     741             :     {
     742       10149 :         dfRatio_bits = 2;
     743       10149 :         move16();
     744             :     }
     745             :     ELSE
     746             :     {
     747        1719 :         dfRatio_bits = 3;
     748        1719 :         move16();
     749             :     }
     750             : 
     751       12120 :     return dfRatio_bits;
     752             : }

Generated by: LCOV version 1.14