LCOV - code coverage report
Current view: top level - lib_com - ivas_qmetadata_com_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 263 270 97.4 %
Date: 2025-05-03 01:55:50 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        1217 : ivas_error ivas_qmetadata_open_fx(
      67             :     IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle         */
      68             : )
      69             : {
      70             :     /* allocate  MetaData handle */
      71        1217 :     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        1217 :     ( *hQMetaData )->q_direction = NULL;
      77        1217 :     ( *hQMetaData )->surcoh_band_data = NULL;
      78        1217 :     ( *hQMetaData )->bandMap = NULL;
      79             : 
      80        1217 :     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       91324 : 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       91324 :     IF( hQMetaData->q_direction != NULL )
     109             :     {
     110       90107 :         do_realloc = (UWord8) NE_16( nbands, hQMetaData->q_direction->cfg.nbands );
     111       90107 :         do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( ndirs, hQMetaData->no_directions ) );
     112       90107 :         do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( coherence_flag, hQMetaData->coherence_flag ) );
     113             :     }
     114             :     ELSE
     115             :     {
     116        1217 :         do_realloc = TRUE;
     117        1217 :         move16();
     118             :     }
     119             : 
     120       91324 :     IF( do_realloc )
     121             :     {
     122        8993 :         ivas_qmetadata_free_memory_fx( hQMetaData );
     123             : 
     124        8993 :         hQMetaData->numCodingBands = (UWord8) nbands;
     125        8993 :         move16();
     126        8993 :         hQMetaData->no_directions = ndirs;
     127        8993 :         move16();
     128        8993 :         hQMetaData->coherence_flag = coherence_flag;
     129        8993 :         move16();
     130             : 
     131        8993 :         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       18868 :         FOR( dir = 0; dir < hQMetaData->no_directions; dir++ )
     137             :         {
     138        9875 :             hQMetaData->q_direction[dir].cfg.nbands = nbands;
     139        9875 :             move16();
     140        9875 :             IF( nbands == 0 )
     141             :             {
     142           0 :                 hQMetaData->q_direction[dir].band_data = NULL;
     143             :             }
     144             :             ELSE
     145             :             {
     146        9875 :                 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       75636 :                 FOR( j = 0; j < nbands; j++ )
     152             :                 {
     153       65761 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     154       65761 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     155       65761 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].q_elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     156       65761 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].q_azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     157       65761 :                     set32_fx( hQMetaData->q_direction[dir].band_data[j].energy_ratio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES );
     158             :                 }
     159             :             }
     160             : 
     161        9875 :             IF( coherence_flag )
     162             :             {
     163        3357 :                 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        6518 :                 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        9875 :             hQMetaData->q_direction[dir].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES;
     172        9875 :             move16();
     173        9875 :             hQMetaData->q_direction[dir].cfg.search_effort = 3;
     174        9875 :             move16();
     175        9875 :             hQMetaData->q_direction[dir].cfg.start_band = 0;
     176        9875 :             move16();
     177        9875 :             hQMetaData->q_direction[dir].cfg.mc_ls_setup = MC_LS_SETUP_INVALID;
     178        9875 :             move32();
     179             :         }
     180             : 
     181        8993 :         IF( coherence_flag )
     182             :         {
     183        2787 :             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        6206 :             hQMetaData->surcoh_band_data = NULL;
     191             :         }
     192             :     }
     193             : 
     194             : 
     195       91324 :     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       10210 : static void ivas_qmetadata_free_memory_fx(
     206             :     IVAS_QMETADATA_HANDLE hQMetaData /* i/o: q_metadata handle         */
     207             : )
     208             : {
     209             :     Word16 dir;
     210             : 
     211       10210 :     IF( hQMetaData == NULL )
     212             :     {
     213           0 :         return;
     214             :     }
     215             : 
     216       10210 :     IF( hQMetaData->q_direction != NULL )
     217             :     {
     218       18868 :         FOR( dir = 0; dir < hQMetaData->no_directions; dir++ )
     219             :         {
     220        9875 :             IF( hQMetaData->q_direction[dir].band_data != NULL )
     221             :             {
     222        9875 :                 free( hQMetaData->q_direction[dir].band_data );
     223        9875 :                 hQMetaData->q_direction[dir].band_data = NULL;
     224             :             }
     225        9875 :             IF( hQMetaData->q_direction[dir].coherence_band_data != NULL )
     226             :             {
     227        3357 :                 free( hQMetaData->q_direction[dir].coherence_band_data );
     228        3357 :                 hQMetaData->q_direction[dir].coherence_band_data = NULL;
     229             :             }
     230             :         }
     231             : 
     232        8993 :         free( hQMetaData->q_direction );
     233        8993 :         hQMetaData->q_direction = NULL;
     234             :     }
     235             : 
     236       10210 :     IF( hQMetaData->surcoh_band_data != NULL )
     237             :     {
     238        2787 :         free( hQMetaData->surcoh_band_data );
     239        2787 :         hQMetaData->surcoh_band_data = NULL;
     240             :     }
     241             : 
     242       10210 :     return;
     243             : }
     244             : 
     245             : 
     246             : /*-----------------------------------------------------------------------*
     247             :  * ivas_qmetadata_close()
     248             :  *
     249             :  * close Q Metadata
     250             :  *-----------------------------------------------------------------------*/
     251             : 
     252        2384 : void ivas_qmetadata_close_fx(
     253             :     IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle         */
     254             : )
     255             : {
     256        2384 :     test();
     257        2384 :     IF( hQMetaData == NULL || *hQMetaData == NULL )
     258             :     {
     259        1167 :         return;
     260             :     }
     261             : 
     262        1217 :     ivas_qmetadata_free_memory_fx( *hQMetaData );
     263             : 
     264        1217 :     free( *hQMetaData );
     265        1217 :     *hQMetaData = NULL;
     266             : 
     267        1217 :     return;
     268             : }
     269             : 
     270             : 
     271             : /*-------------------------------------------------------------------------
     272             :  * masa_sq()
     273             :  *
     274             :  * scalar quantization using partition
     275             :  *------------------------------------------------------------------------*/
     276             : 
     277             : /*! r: codeword index */
     278     3044891 : 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    19345977 :     FOR( i = 0; i < cb_sz; i++ )
     287             :     {
     288    19345977 :         IF( LT_32( in, threshold[i + 1] ) )
     289             :         {
     290     3044891 :             return i;
     291             :         }
     292             :     }
     293             : 
     294           0 :     return -1;
     295             : }
     296             : 
     297             : /*-------------------------------------------------------------------------
     298             :  * only_reduce_bits_direction()
     299             :  *
     300             :  *
     301             :  *------------------------------------------------------------------------*/
     302             : 
     303       17494 : 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       99883 :     FOR( j = 0; j < coding_subbands; j++ )
     319             :     {
     320      301494 :         FOR( k = 0; k < no_subframes; k++ )
     321             :         {
     322      219105 :             bits_sph_idx_orig[j][k] = q_direction->band_data[j].bits_sph_idx[k];
     323      219105 :             move16();
     324             :         }
     325             :     }
     326       17494 :     n = 0;
     327       17494 :     move16();
     328       17494 :     delta = 1;
     329       17494 :     move16();
     330             : 
     331       17494 :     IF( reduce_bits > 0 )
     332             :     {
     333       16821 :         red_times = idiv1616( reduce_bits, imult1616( coding_subbands, no_subframes ) ); /* number of complete reductions by 1 bit */
     334       16821 :         IF( red_times > 0 )
     335             :         {
     336       77615 :             FOR( j = 0; j < coding_subbands; j++ )
     337             :             {
     338       64010 :                 bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
     339      257452 :                 FOR( k = 0; k < no_subframes; k++ )
     340             :                 {
     341      193442 :                     bits_dir0[k] = sub( bits_dir0[k], red_times );
     342      193442 :                     move16();
     343      193442 :                     reduce_bits = sub( reduce_bits, red_times );
     344             : 
     345      193442 :                     IF( LT_16( bits_dir0[k], MASA_MIN_BITS_TF ) )
     346             :                     {
     347       29087 :                         reduce_bits = add( reduce_bits, sub( MASA_MIN_BITS_TF, bits_dir0[k] ) );
     348       29087 :                         bits_dir0[k] = MASA_MIN_BITS_TF;
     349       29087 :                         move16();
     350             :                     }
     351             :                 }
     352             :             }
     353             :         }
     354             : 
     355       16821 :         rem = reduce_bits; /* -coding_subbands*no_subframes*red_times; */
     356       16821 :         move16();
     357       37179 :         WHILE( LT_16( n, rem ) )
     358             :         {
     359       20358 :             max_nb = 0;
     360       20358 :             move16();
     361      110142 :             FOR( j = 0; j < coding_subbands; j++ )
     362             :             {
     363       89784 :                 bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx;
     364      358368 :                 FOR( k = 0; k < no_subframes; k++ )
     365             :                 {
     366      268584 :                     test();
     367      268584 :                     IF( LT_16( n, rem ) && GT_16( bits_dir0[k], sub( MASA_MIN_BITS_TF, delta ) ) )
     368             :                     {
     369      144922 :                         bits_dir0[k] = sub( bits_dir0[k], 1 );
     370      144922 :                         move16();
     371      144922 :                         n = add( n, 1 );
     372             :                     }
     373             : 
     374      268584 :                     if ( LT_16( max_nb, bits_dir0[k] ) )
     375             :                     {
     376       45071 :                         max_nb = bits_dir0[k];
     377       45071 :                         move16();
     378             :                     }
     379             :                 }
     380             :             }
     381             : 
     382       20358 :             IF( LE_16( max_nb, MASA_MIN_BITS_TF ) )
     383             :             {
     384        1638 :                 delta = add( delta, 1 );
     385             :             }
     386             :         }
     387             : 
     388       16821 :         reduce_bits = 0;
     389       16821 :         move16();
     390             :     }
     391             : 
     392       17494 :     IF( EQ_16( ind_order[0], -1 ) )
     393             :     {
     394       24158 :         FOR( j = 0; j < coding_subbands; j++ )
     395             :         {
     396       18046 :             ind_order[j] = j;
     397       18046 :             move16();
     398             :         }
     399             :     }
     400             :     ELSE
     401             :     {
     402             : 
     403             :         Word16 m, sorted, index1, index2;
     404             : 
     405       75725 :         FOR( j = 0; j < coding_subbands; j++ )
     406             :         {
     407       64343 :             ind_order[j] = j;
     408       64343 :             move16();
     409             :         }
     410       11382 :         sorted = 0;
     411       11382 :         move16();
     412       41542 :         FOR( m = coding_subbands - 1; m && !sorted; m-- )
     413             :         {
     414       30160 :             sorted = 1;
     415       30160 :             move16();
     416      166701 :             FOR( j = 0; j < m; j++ )
     417             :             {
     418      136541 :                 index1 = ind_order[j];
     419      136541 :                 move16();
     420      136541 :                 index2 = ind_order[j + 1];
     421      136541 :                 move16();
     422      136541 :                 tmp = 0;
     423      136541 :                 move16();
     424      493336 :                 FOR( k = 0; k < no_subframes; k++ )
     425             :                 {
     426      356795 :                     tmp = add( tmp, sub( bits_sph_idx_orig[index1][k], q_direction->band_data[index1].bits_sph_idx[k] ) );
     427             :                 }
     428      136541 :                 penalty[0] = L_shr( W_extract_l( W_mult_32_16( tmp, bits_sph_idx_orig[index2][0] ) ), 1 );
     429      136541 :                 move32();
     430      136541 :                 tmp = 0;
     431      136541 :                 move16();
     432      493336 :                 FOR( k = 0; k < no_subframes; k++ )
     433             :                 {
     434      356795 :                     tmp = add( tmp, sub( bits_sph_idx_orig[index2][k], q_direction->band_data[index2].bits_sph_idx[k] ) );
     435             :                 }
     436      136541 :                 penalty[1] = L_shr( W_extract_l( W_mult_32_16( tmp, bits_sph_idx_orig[index1][0] ) ), 1 );
     437      136541 :                 move32();
     438      136541 :                 IF( LT_32( penalty[0], penalty[1] ) )
     439             :                 {
     440       40929 :                     sorted = 0;
     441       40929 :                     move16();
     442       40929 :                     ind_order[j] = index2;
     443       40929 :                     move16();
     444       40929 :                     ind_order[j + 1] = index1;
     445       40929 :                     move16();
     446             :                 }
     447             :             }
     448             :         }
     449             :     }
     450             : 
     451       17494 :     *reduce_bits_out = negate( reduce_bits );
     452       17494 :     move16();
     453             : 
     454       17494 :     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       52695 : 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       52695 :     diff = *p_diff;
     475       52695 :     move16();
     476       52695 :     IF( diff < 0 )
     477             :     {
     478             :         /* increase bits for next subbands */
     479       16887 :         k = 0;
     480       16887 :         move16();
     481       69369 :         WHILE( diff < 0 && LT_16( j, max_i ) && LT_16( k, max_k ) )
     482             :         {
     483       52482 :             test();
     484       52482 :             test();
     485       52482 :             IF( LT_32( q_direction->band_data[j].bits_sph_idx[k], MASA_DIRECTION_MAX_BITS ) )
     486             :             {
     487       52482 :                 q_direction->band_data[j].bits_sph_idx[k] = (UWord16) L_add( q_direction->band_data[j].bits_sph_idx[k], 1 );
     488       52482 :                 move16();
     489       52482 :                 diff = add( diff, 1 );
     490             :             }
     491       52482 :             k = add( k, 1 );
     492             :         }
     493             :     }
     494             :     ELSE
     495             :     {
     496       35808 :         k = 0;
     497       35808 :         move16();
     498       55769 :         WHILE( diff > 0 && LT_16( k, max_k ) )
     499             :         {
     500       19961 :             test();
     501       19961 :             IF( q_direction->band_data[j].bits_sph_idx[k] > 0 )
     502             :             {
     503       19961 :                 q_direction->band_data[j].bits_sph_idx[k] = (UWord16) L_sub( q_direction->band_data[j].bits_sph_idx[k], 1 );
     504       19961 :                 move16();
     505       19961 :                 diff = sub( diff, 1 );
     506             :             }
     507             :         }
     508             :     }
     509       52695 :     *p_diff = diff;
     510       52695 :     move16();
     511             : 
     512       52695 :     return;
     513             : }
     514             : 
     515             : 
     516             : /*---------------------------------------------------------------
     517             :  * invdct4_transform()
     518             :  *
     519             :  * Inverse DCT transform for 4D vector
     520             :  *---------------------------------------------------------------*/
     521             : 
     522      276943 : 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      276943 :     a_fx = L_add( v_fx[0], v_fx[2] ); // q
     532      276943 :     b_fx = L_sub( v_fx[0], v_fx[2] ); // q
     533             :     // 1.306562964876376f * 2 ^ 30 -> 1402911360, 0.541196100146198f * 2 ^ 30 -> 581104896
     534      276943 :     c_fx = L_shl( L_add( Mpy_32_32( 1402911360, v_fx[1] ), Mpy_32_32( 581104896, v_fx[3] ) ), Q31 - Q30 ); // q
     535      276943 :     d_fx = L_shl( L_sub( Mpy_32_32( 581104896, v_fx[1] ), Mpy_32_32( 1402911360, v_fx[3] ) ), Q31 - Q30 ); // q
     536      276943 :     f_invdct_v_fx[0] = L_shl( L_add( a_fx, c_fx ), 7 );                                                    // q
     537      276943 :     move32();
     538      276943 :     f_invdct_v_fx[1] = L_shl( L_add( b_fx, d_fx ), 7 ); // q
     539      276943 :     move32();
     540      276943 :     f_invdct_v_fx[2] = L_shl( L_sub( b_fx, d_fx ), 7 ); // q
     541      276943 :     move32();
     542      276943 :     f_invdct_v_fx[3] = L_shl( L_sub( a_fx, c_fx ), 7 ); // q
     543      276943 :     move32();
     544             : 
     545     1384715 :     FOR( i = 0; i < 4; i++ )
     546             :     {
     547     1107772 :         IF( f_invdct_v_fx[i] < 0 )
     548             :         {
     549      123183 :             invdct_v[i] = 0;
     550      123183 :             move16();
     551             :         }
     552             :         ELSE
     553             :         {
     554      984589 :             IF( GT_32( f_invdct_v_fx[i], L_shl( 255, q ) ) )
     555             :             {
     556          12 :                 f_invdct_v_fx[i] = L_shl( 255, q ); // q
     557          12 :                 move32();
     558             :             }
     559      984589 :             invdct_v[i] = (UWord8) L_shr( f_invdct_v_fx[i], q ); // Q0
     560      984589 :             move16();
     561             :         }
     562             :     }
     563             : 
     564      276943 :     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      412896 : 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      412896 :     IF( hodirac_flag )
     585             :     {
     586      387576 :         *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hordiac_ratio1;
     587      387576 :         move16();
     588      387576 :         *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hoardia_ratio2;
     589      387576 :         move16();
     590             :     }
     591             :     ELSE
     592             :     {
     593       25320 :         *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio1;
     594       25320 :         move16();
     595       25320 :         *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio2;
     596       25320 :         move16();
     597             :     }
     598             : 
     599      412896 :     return;
     600             : }
     601             : 
     602             : /*---------------------------------------------------------------
     603             :  * set_qmetadata_maxbit_req()
     604             :  *
     605             :  * Sets proper value for qmetadata_max_bit_req limit
     606             :  *--------------------------------------------------------------*/
     607             : 
     608       91324 : 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       91324 :     IF( EQ_32( ivas_format, SBA_FORMAT ) )
     614             :     {
     615        4765 :         hQMetaData->qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_SBA;
     616        4765 :         move16();
     617             :     }
     618             :     ELSE /* MASA_FORMAT */
     619             :     {
     620       86559 :         hQMetaData->qmetadata_max_bit_req = QMETADATA_MAXBIT_REQ_MASA;
     621       86559 :         move16();
     622             :     }
     623             : 
     624       91324 :     return;
     625             : }
     626             : 
     627             : 
     628             : /*-------------------------------------------------------------------------
     629             :  * ivas_qmetadata_azimuth_elevation_to_direction_vector()
     630             :  *
     631             :  *
     632             :  *------------------------------------------------------------------------*/
     633             : 
     634     3204501 : 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     3204501 :     elevation_fx = extract_l( L_shr( Mpy_32_32( el, ONE_BY_360_Q31 ), 7 ) ); // ( ( Q22 + Q31 - Q31 ) - Q7 ) -> Q15
     645     3204501 :     azimuth_fx = extract_l( L_shr( Mpy_32_32( az, ONE_BY_360_Q31 ), 7 ) );   // ( ( Q22 + Q31 - Q31 ) - Q7 ) -> Q15
     646             : 
     647     3204501 :     dv[2] = L_shl( getSineWord16R2( elevation_fx ), Q15 ); /* Q30 */
     648     3204501 :     move32();
     649     3204501 :     radius_length = getCosWord16R2( elevation_fx );
     650     3204501 :     dv[0] = L_mult0( radius_length, getCosWord16R2( azimuth_fx ) ); /* Q30 */
     651     3204501 :     move32();
     652     3204501 :     dv[1] = L_mult0( radius_length, getSineWord16R2( azimuth_fx ) ); /* Q30 */
     653     3204501 :     move32();
     654             : 
     655     3204501 :     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     2611491 : 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     2611491 :     L_tmp = L_add( Mpy_32_32( dv[0], dv[0] ), Mpy_32_32( dv[1], dv[1] ) ); /* 2 * dv_q - 31 */
     676     2611491 :     e_tmp = shl( sub( 31, dv_q ), 1 );
     677     2611491 :     L_tmp = Sqrt32( L_tmp, &e_tmp ); // e_tmp
     678             :     // 29335 -> 180 / PI in Q9
     679     2611491 :     *el = L_mult0( BASOP_util_atan2( dv[2], L_tmp, sub( sub( 31, dv_q ), e_tmp ) ), 29335 ); /* Q22 */
     680     2611491 :     move32();
     681             :     // 29335 -> 180 / PI in Q9
     682     2611491 :     *az = L_mult0( BASOP_util_atan2( dv[1], dv[0], 0 ), 29335 ); /* Q22 */
     683     2611491 :     move32();
     684     2611491 :     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      387576 : 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      387576 :     IF( GE_16( index_diff, DIFF_DFRATIO_1BIT_LIMIT_IDX ) )
     702             :     {
     703      168801 :         dfRatio_bits = 1;
     704      168801 :         move16();
     705             :     }
     706      218775 :     ELSE IF( GE_16( index_diff, DIFF_DFRATIO_2BIT_LIMIT_IDX_HODIRAC ) )
     707             :     {
     708       97003 :         dfRatio_bits = 2;
     709       97003 :         move16();
     710             :     }
     711             :     ELSE
     712             :     {
     713      121772 :         dfRatio_bits = 3;
     714      121772 :         move16();
     715             :     }
     716             : 
     717      387576 :     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       25320 : 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       25320 :     IF( GE_16( index_diff, DIFF_DFRATIO_1BIT_LIMIT_IDX ) )
     736             :     {
     737         523 :         dfRatio_bits = 1;
     738         523 :         move16();
     739             :     }
     740       24797 :     ELSE IF( GE_16( index_diff, DIFF_DFRATIO_2BIT_LIMIT_IDX ) )
     741             :     {
     742       21219 :         dfRatio_bits = 2;
     743       21219 :         move16();
     744             :     }
     745             :     ELSE
     746             :     {
     747        3578 :         dfRatio_bits = 3;
     748        3578 :         move16();
     749             :     }
     750             : 
     751       25320 :     return dfRatio_bits;
     752             : }

Generated by: LCOV version 1.14