LCOV - code coverage report
Current view: top level - lib_dec - ivas_pca_dec_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 89 102 87.3 %
Date: 2025-05-03 01:55:50 Functions: 9 9 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 <stdint.h>
      34             : #include "options.h"
      35             : #include "prot_fx.h"
      36             : #include <assert.h>
      37             : #include "ivas_cnst.h"
      38             : #include "wmc_auto.h"
      39             : #include "math.h"
      40             : #include "ivas_prot_fx.h"
      41             : 
      42             : /*-----------------------------------------------------------------------*
      43             :  * Local function definitions
      44             :  *-----------------------------------------------------------------------*/
      45             : 
      46          12 : static Word32 ivas_bitstream_read_int32_fx(
      47             :     Decoder_State *st0,
      48             :     const Word16 bits /*Q0*/
      49             : )
      50             : {
      51             :     Word32 val;
      52             : 
      53             :     /* MSB */
      54          12 :     val = L_shl( get_next_indice_fx( st0, sub( bits, 16 ) ), 16 ); /*Q0*/
      55             : 
      56             :     /* + LSB */
      57          12 :     val = L_add( val, get_next_indice_fx( st0, 16 ) ); /*Q0*/
      58             : 
      59          12 :     return val;
      60             : }
      61             : 
      62        9965 : static void pca_dec_reset_dquat_fx(
      63             :     Word16 *ql_fx, /*Q15*/
      64             :     Word16 *qr_fx  /*Q15*/
      65             : )
      66             : {
      67        9965 :     set16_fx( ql_fx, 0, IVAS_PCA_INTERP );
      68        9965 :     ql_fx[0] = MAX_16;
      69        9965 :     move16();
      70        9965 :     set16_fx( qr_fx, 0, IVAS_PCA_INTERP );
      71        9965 :     qr_fx[0] = MAX_16;
      72        9965 :     move16();
      73        9965 :     return;
      74             : }
      75             : 
      76             : 
      77        9440 : static void pca_dec_reset_mem_eigvec_fx(
      78             :     PCA_DEC_STATE *hPCA )
      79             : {
      80             :     Word16 i;
      81             : 
      82      613600 :     FOR( i = 0; i < ( IVAS_PCA_LEN_INTERP_EIG_DEC >> 4 ); i++ )
      83             :     {
      84      604160 :         eye_matrix_fx( &hPCA->mem_eigVec_interp_fx[( 16 * i )], FOA_CHANNELS, MAX_16 );
      85             :     }
      86             : 
      87        9440 :     return;
      88             : }
      89             : 
      90             : 
      91       46880 : static void pca_inv_transform_sub_fx(
      92             :     Word16 *eigVec,             /*Q15*/
      93             :     Word32 *transformed_data[], /* i  : input/transformed audio channels    Q11*/
      94             :     const Word16 start,         /*Q0*/
      95             :     const Word16 len,           /*Q0*/
      96             :     const Word16 n_channels     /*Q0*/
      97             : )
      98             : {
      99             :     Word16 i, j, k;
     100             :     Word32 temp, temp2;
     101             :     Word32 buffer_data[FOA_CHANNELS];
     102             : 
     103      829280 :     FOR( j = 0; j < len; j++ )
     104             :     {
     105     3912000 :         FOR( k = 0; k < n_channels; k++ )
     106             :         {
     107     3129600 :             buffer_data[k] = transformed_data[k][( j + start )]; /*Q11*/
     108     3129600 :             move32();
     109             :         }
     110             : 
     111     3912000 :         FOR( k = 0; k < n_channels; k++ )
     112             :         {
     113     3129600 :             temp = 0;
     114     3129600 :             move32();
     115    15648000 :             FOR( i = 0; i < n_channels; i++ )
     116             :             {
     117    12518400 :                 temp2 = Mpy_32_16_1( buffer_data[i], eigVec[( k * IVAS_PCA_INTERP + i )] ); /*Q11*/
     118    12518400 :                 temp = L_add( temp, temp2 );
     119             :             }
     120     3129600 :             transformed_data[k][( j + start )] = temp; /*Q11*/
     121     3129600 :             move32();
     122             :         }
     123             :     }
     124             : 
     125       46880 :     return;
     126             : }
     127             : 
     128             : 
     129        1172 : static void pca_dec_inv_transform_fx(
     130             :     PCA_DEC_STATE *hPCA,
     131             :     Word16 *ql_fx,           /*Q15*/
     132             :     Word16 *qr_fx,           /*Q15*/
     133             :     const Word16 n_samples,  /*Q0*/
     134             :     const Word16 n_channels, /*Q0*/
     135             :     Word32 *decoded_data[]   /*Q11*/
     136             : )
     137             : {
     138             :     Word16 j;
     139             :     Word16 slot_len;
     140             :     Word16 ql_interp_fx[IVAS_PCA_LEN_INTERP_Q], qr_interp_fx[IVAS_PCA_LEN_INTERP_Q];
     141             :     // todo : updtate prev buffer, find Q
     142        1172 :     quat_shortestpath_fx( hPCA->prev_ql_fx, ql_fx, hPCA->prev_qr_fx, qr_fx );
     143             : 
     144        1172 :     pca_interp_preproc_fx( hPCA->prev_ql_fx, hPCA->prev_qr_fx, ql_fx, qr_fx, IVAS_PCA_N_SLOTS, ql_interp_fx, qr_interp_fx );
     145             : 
     146        1172 :     slot_len = idiv1616( n_samples, IVAS_PCA_N_SLOTS ); /*Q0*/
     147             : 
     148       48052 :     FOR( j = 0; j < IVAS_PCA_N_SLOTS; j++ )
     149             :     {
     150             :         /* convert from double quaternion to 4D matrix */
     151       46880 :         dquat2mat_fx( &ql_interp_fx[4 * j], &qr_interp_fx[4 * j], &hPCA->mem_eigVec_interp_fx[( 16 * j + IVAS_PCA_DELAY_CMP * 16 )] );
     152             : 
     153       46880 :         pca_inv_transform_sub_fx( &hPCA->mem_eigVec_interp_fx[16 * j], decoded_data, slot_len * j, slot_len, n_channels );
     154             :     }
     155             : 
     156        1172 :     return;
     157             : }
     158             : 
     159       10580 : static void pca_dec_update_dquat_fx(
     160             :     PCA_DEC_STATE *hPCA,
     161             :     const Word16 *ql_fx, /*Q15*/
     162             :     const Word16 *qr_fx  /*Q15*/
     163             : )
     164             : {
     165             :     /* update state for next frame */
     166       10580 :     Copy( qr_fx, hPCA->prev_qr_fx, IVAS_PCA_INTERP ); /*Q15*/
     167       10580 :     Copy( ql_fx, hPCA->prev_ql_fx, IVAS_PCA_INTERP ); /*Q15*/
     168             : 
     169       10580 :     return;
     170             : }
     171             : 
     172             : 
     173             : /*-------------------------------------------------------------------------
     174             :  * ivas_pca_dec_init_fx()
     175             :  *
     176             :  * Initialize PCA decoder
     177             :  *------------------------------------------------------------------------*/
     178             : 
     179             : 
     180          32 : void ivas_pca_dec_init_fx(
     181             :     PCA_DEC_STATE *hPCA /* i/o: PCA decoder structure  */
     182             : )
     183             : {
     184          32 :     pca_dec_reset_dquat_fx( hPCA->prev_ql_fx, hPCA->prev_qr_fx );
     185          32 :     pca_dec_reset_mem_eigvec_fx( hPCA );
     186             : 
     187             :     /* set counter saturated to 2 frames */
     188          32 :     hPCA->prev_pca_bypass = 2;
     189          32 :     move16();
     190          32 :     return;
     191             : }
     192             : /*-------------------------------------------------------------------------
     193             :  * ivas_pca_read_bits_fx()
     194             :  *
     195             :  * Decode PCA indexes
     196             :  *------------------------------------------------------------------------*/
     197             : 
     198        9840 : void ivas_pca_read_bits_fx(
     199             :     Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/
     200             :     PCA_DEC_STATE *hPCA )
     201             : {
     202             :     /*first bit in the PCA payload (first bit after 3 header bits) signals bypass/active*/
     203        9840 :     hPCA->pca_bypass = get_next_indice_fx( st0, 1 ); /*Q0*/
     204        9840 :     move16();
     205        9840 :     IF( EQ_16( hPCA->pca_bypass, PCA_MODE_INACTIVE ) )
     206             :     {
     207        9834 :         return;
     208             :     }
     209             : 
     210           6 :     hPCA->index[0] = ivas_bitstream_read_int32_fx( st0, IVAS_PCA_QBITS - 1 ); /*Q0*/
     211           6 :     move32();
     212           6 :     hPCA->index[1] = ivas_bitstream_read_int32_fx( st0, IVAS_PCA_QBITS ); /*Q0*/
     213           6 :     move32();
     214             : 
     215           6 :     return;
     216             : }
     217             : 
     218             : /*-------------------------------------------------------------------------
     219             :  * ivas_pca_dec_fx()
     220             :  *
     221             :  * PCA decoder
     222             :  *------------------------------------------------------------------------*/
     223             : 
     224       10580 : void ivas_pca_dec_fx(
     225             :     PCA_DEC_STATE *hPCA,                /* i/o: PCA decoder structure      */
     226             :     const Word16 output_frame,          /* i  : output frame length        Q0*/
     227             :     const Word16 n_channels,            /* i  : number of channels         Q0*/
     228             :     const Word32 ivas_total_brate,      /* i  : IVAS total bitrate         Q0*/
     229             :     const Word32 last_ivas_total_brate, /* i  : last IVAS total bitrate    Q0*/
     230             :     const Word16 bfi,                   /* i  : bad frame indicator        Q0*/
     231             :     Word32 *pcm_out_fx[]                /* o  : output audio channels      Q11*/
     232             : )
     233             : {
     234             :     Word16 ql_fx[IVAS_PCA_INTERP], qr_fx[IVAS_PCA_INTERP]; /*Q15*/
     235             :     Word16 pca_bypass;
     236             :     // todo : check if mem_eigVec_interp_fx values are being updated / add loop to update
     237       10580 :     Copy( &hPCA->mem_eigVec_interp_fx[IVAS_PCA_N_SLOTS * 16], hPCA->mem_eigVec_interp_fx, IVAS_PCA_DELAY_CMP * 16 ); /*Q15*/
     238             : 
     239             :     /* @@@TODO: check how ivas_total_brate is set if bfi == 1 */ // ToDo: and what happens in DTX where "ivas_total_brate" can be close to zero?
     240             : 
     241             :     /* handle bit rate switching */
     242       10580 :     test();
     243       10580 :     test();
     244       10580 :     IF( NE_32( ivas_total_brate, PCA_BRATE ) || ( EQ_32( ivas_total_brate, PCA_BRATE ) && GT_16( n_channels, FOA_CHANNELS ) ) )
     245             :     {
     246             :         /* set PCA by-pass mode in current frame and interpolate transform as previous frame used PCA */
     247           0 :         pca_dec_reset_dquat_fx( ql_fx, qr_fx );
     248             : 
     249           0 :         test();
     250           0 :         test();
     251           0 :         IF( ( NE_32( last_ivas_total_brate, PCA_BRATE ) ) || ( EQ_32( last_ivas_total_brate, PCA_BRATE ) && GT_16( hPCA->prev_pca_bypass, 1 ) ) )
     252             :         {
     253           0 :             pca_dec_reset_mem_eigvec_fx( hPCA );
     254             :         }
     255             :         ELSE
     256             :         {
     257           0 :             pca_dec_inv_transform_fx( hPCA, ql_fx, qr_fx, output_frame, n_channels, pcm_out_fx );
     258             :         }
     259             : 
     260           0 :         pca_dec_update_dquat_fx( hPCA, ql_fx, qr_fx );
     261           0 :         hPCA->prev_pca_bypass = add( hPCA->prev_pca_bypass, 1 ); /*Q0*/
     262           0 :         move16();
     263             : 
     264           0 :         if ( GT_16( hPCA->prev_pca_bypass, 2 ) )
     265             :         {
     266           0 :             hPCA->prev_pca_bypass = 2; /*Q0*/
     267           0 :             move16();
     268             :         }
     269             : 
     270           0 :         return;
     271             :     }
     272             : 
     273       10580 :     IF( bfi == 0 )
     274             :     {
     275             :         /* set PCA by-pass mode indicator */
     276        9840 :         pca_bypass = hPCA->pca_bypass; /*Q0*/
     277        9840 :         move16();
     278             :     }
     279             :     ELSE
     280             :     {
     281         740 :         pca_bypass = hPCA->prev_pca_bypass; /*Q0*/
     282         740 :         move16();
     283             :     }
     284             : 
     285       10580 :     IF( EQ_16( pca_bypass, PCA_MODE_INACTIVE ) )
     286             :     {
     287        9933 :         pca_dec_reset_dquat_fx( ql_fx, qr_fx );
     288             : 
     289        9933 :         IF( GT_16( hPCA->prev_pca_bypass, 1 ) ) //&& (hPCA->pca_off_hangover == 0))
     290             :         {
     291             :             /* copy input data into output directly as previous frame was already in by-pass mode */
     292        9408 :             pca_dec_reset_mem_eigvec_fx( hPCA );
     293             :         }
     294             :         ELSE
     295             :         {
     296         525 :             pca_dec_inv_transform_fx( hPCA, ql_fx, qr_fx, output_frame, n_channels, pcm_out_fx );
     297             :         }
     298             : 
     299        9933 :         pca_dec_update_dquat_fx( hPCA, ql_fx, qr_fx );
     300             : 
     301        9933 :         hPCA->prev_pca_bypass = add( hPCA->prev_pca_bypass, 1 ); /*Q0*/
     302        9933 :         move16();
     303        9933 :         hPCA->prev_pca_bypass = s_min( hPCA->prev_pca_bypass, 2 ); /*Q0*/
     304        9933 :         move16();
     305        9933 :         return; // exit happens here
     306             :     }
     307             : 
     308         647 :     IF( bfi == 0 )
     309             :     {
     310           6 :         pca_dec_s3_fx( hPCA->index[0], ql_fx );
     311           6 :         pca_dec_s3_fx( hPCA->index[1], qr_fx );
     312             :     }
     313             :     ELSE
     314             :     {
     315             :         /* freeze */
     316             :         // todo : check if update of prev_ql_fx is required
     317         641 :         Copy( hPCA->prev_ql_fx, ql_fx, IVAS_PCA_INTERP ); /*Q15*/
     318         641 :         Copy( hPCA->prev_qr_fx, qr_fx, IVAS_PCA_INTERP ); /*Q15*/
     319             :     }
     320         647 :     pca_dec_inv_transform_fx( hPCA, ql_fx, qr_fx, output_frame, n_channels, pcm_out_fx );
     321             : 
     322             :     /* update for next frame */
     323         647 :     pca_dec_update_dquat_fx( hPCA, ql_fx, qr_fx );
     324             : 
     325         647 :     hPCA->prev_pca_bypass = 0;
     326         647 :     move16();
     327         647 :     return;
     328             : }

Generated by: LCOV version 1.14