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

Generated by: LCOV version 1.14