LCOV - code coverage report
Current view: top level - lib_com - basop_lsf_tools.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 67 89 75.3 %
Date: 2025-05-03 01:55:50 Functions: 2 3 66.7 %

          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             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <assert.h>
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #include "basop_proto_func.h"
      41             : #include "basop_util.h"
      42             : 
      43             : #define WMC_TOOL_SKIP
      44             : 
      45             : #define NC_MAX 8
      46             : 
      47             : static Word16 E_LPC_f_lsp_pol_get( const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1 );
      48             : 
      49             : 
      50             : /*
      51             :  * E_LPC_f_lsp_a_conversion
      52             :  *
      53             :  * Parameters:
      54             :  *    lsp            I: Line spectral pairs          Q15
      55             :  *    a              O: Predictor coefficients (order = m)  Qx (The Q factor of the output to be deduced from a(0))
      56             :  *    m              I: order of LP filter
      57             :  *
      58             :  * Function:
      59             :  *    Convert ISPs to predictor coefficients a[]
      60             :  *
      61             :  * Returns:
      62             :  *    void
      63             :  */
      64       31484 : void basop_E_LPC_f_lsp_a_conversion(
      65             :     const Word16 *lsp, /* Q15 */
      66             :     Word16 *a,         /* Qx */
      67             :     const Word16 m     /* Q0 */
      68             : )
      69             : {
      70             :     Word16 i, j, k;
      71             :     Word32 f1[NC_MAX + 1], f2[NC_MAX + 1];
      72             :     Word16 nc;
      73             :     Word32 t0;
      74             :     Word16 Ovf, Ovf2;
      75             : 
      76             : 
      77             :     /*-----------------------------------------------------*
      78             :      *  Find the polynomials F1(z) and F2(z)               *
      79             :      *-----------------------------------------------------*/
      80             : 
      81       31484 :     nc = shr( m, 1 );
      82             : 
      83       31484 :     assert( m == 16 || m == 10 );
      84             : 
      85       31484 :     Ovf = 0;
      86       31484 :     move16();
      87       31484 :     Ovf = E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, Ovf, 1 );  /* Q0 */
      88       31484 :     Ovf2 = E_LPC_f_lsp_pol_get( &lsp[1], f2, nc, Ovf, 1 ); /* Q0 */
      89       31484 :     IF( sub( Ovf2, Ovf ) != 0 )
      90             :     {
      91             :         /* to ensure similar scaling for f1 and f2 in case
      92             :           an overflow would be detected only in f2,
      93             :           but this case never happen on my dtb */
      94           0 :         E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, s_max( Ovf2, Ovf ), 1 );
      95             :     }
      96             :     /*-----------------------------------------------------*
      97             :      *  Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1)   *
      98             :      *-----------------------------------------------------*/
      99             :     /*modification*/
     100       31484 :     k = sub( nc, 1 );
     101      283356 :     FOR( i = 0; i <= k; i++ )
     102             :     {
     103      251872 :         f1[nc - i] = L_add( f1[nc - i], f1[nc - i - 1] ); /* Q23 */
     104      251872 :         move32();
     105      251872 :         f2[nc - i] = L_sub( f2[nc - i], f2[nc - i - 1] ); /* Q23 */
     106      251872 :         move32();
     107             :     }
     108             : 
     109             :     /*-----------------------------------------------------*
     110             :      *  A(z) = (F1(z)+F2(z))/2                             *
     111             :      *  F1(z) is symmetric and F2(z) is antisymmetric      *
     112             :      *-----------------------------------------------------*/
     113             : 
     114       31484 :     t0 = L_deposit_l( 0 );
     115      283356 :     FOR( i = 1; i <= nc; i++ )
     116             :     {
     117      251872 :         t0 = L_max( t0, L_abs( L_add( f1[i], f2[i] ) ) ); /* Q23 */
     118      251872 :         t0 = L_max( t0, L_abs( L_sub( f1[i], f2[i] ) ) ); /* Q23 */
     119             :     }
     120       31484 :     k = s_min( norm_l( t0 ), 6 );
     121       31484 :     a[0] = shl( 256, k );
     122       31484 :     move16();
     123       31484 :     test();
     124       31484 :     IF( Ovf || Ovf2 )
     125             :     {
     126           0 :         a[0] = shl( 256, sub( k, Ovf ) );
     127           0 :         move16();
     128             :     }
     129       31484 :     j = m;
     130      283356 :     FOR( i = 1; i <= nc; i++ )
     131             :     {
     132             :         /* a[i] = 0.5*(f1[i] + f2[i]) */
     133      251872 :         t0 = L_add( f1[i], f2[i] ); /* Q23 */
     134      251872 :         t0 = L_shl( t0, k );
     135      251872 :         a[i] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
     136             : 
     137             :         /* a[j] = 0.5*(f1[i] - f2[i]) */
     138      251872 :         t0 = L_sub( f1[i], f2[i] ); /* Q23 */
     139      251872 :         t0 = L_shl( t0, k );
     140      251872 :         a[j] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
     141      251872 :         j--;
     142             :     }
     143             : 
     144       31484 :     return;
     145             : }
     146             : 
     147             : 
     148             : /*---------------------------------------------------------------------------
     149             :  * procedure  reorder_lsf()
     150             :  *
     151             :  * To make sure that the  lsfs are properly ordered and to keep a certain
     152             :  * minimum distance between consecutive lsfs.
     153             :  *--------------------------------------------------------------------------*/
     154           0 : void basop_reorder_lsf(
     155             :     Word16 *lsf,           /* i/o: LSFs in the frequency domain (0..0.5)   Q(x2.56)*/
     156             :     const Word16 min_dist, /* i  : minimum required distance               x2.56*/
     157             :     const Word16 n,        /* i  : LPC order                               Q0*/
     158             :     const Word32 Fs        /* i  : sampling frequency                      Q0*/
     159             : )
     160             : {
     161             :     Word16 i, lsf_min, n_m_1;
     162             :     Word16 lsf_max;
     163             : 
     164           0 :     lsf_min = min_dist; /* Q2.56 */
     165           0 :     move16();
     166             : 
     167             :     /*-----------------------------------------------------------------------*
     168             :      * Verify the LSF ordering and minimum GAP
     169             :      *-----------------------------------------------------------------------*/
     170             : 
     171           0 :     FOR( i = 0; i < n; i++ )
     172             :     {
     173           0 :         if ( sub( lsf[i], lsf_min ) < 0 )
     174             :         {
     175           0 :             lsf[i] = lsf_min; /* Q2.56 */
     176           0 :             move16();
     177             :         }
     178           0 :         lsf_min = add( lsf[i], min_dist ); /* Q2.56 */
     179             :     }
     180             : 
     181             :     /*-----------------------------------------------------------------------*
     182             :      * Reverify the LSF ordering and minimum GAP in the reverse order (security)
     183             :      *-----------------------------------------------------------------------*/
     184             : 
     185           0 :     lsf_max = round_fx( L_sub( L_shr( L_mult0( extract_l( L_shr( Fs, 1 ) ), 1311 ), 9 - 16 ), L_deposit_h( min_dist ) ) ); /* Q0 + Q9 , 1311 is 2.56 in Q9 */
     186             : 
     187           0 :     n_m_1 = sub( n, 1 );                 /* Q0 */
     188           0 :     IF( sub( lsf[n_m_1], lsf_max ) > 0 ) /* If danger of unstable filter in case of resonance in HF */
     189             :     {
     190           0 :         FOR( i = n_m_1; i >= 0; i-- ) /* Reverify the minimum LSF gap in the reverse direction */
     191             :         {
     192           0 :             if ( sub( lsf[i], lsf_max ) > 0 )
     193             :             {
     194           0 :                 lsf[i] = lsf_max; /* Q2.56 */
     195           0 :                 move16();
     196             :             }
     197           0 :             lsf_max = sub( lsf[i], min_dist ); /* Q2.56 */
     198             :         }
     199             :     }
     200             : 
     201           0 :     return;
     202             : }
     203             : 
     204             : 
     205             : /*
     206             :  * E_LPC_f_lsp_pol_get
     207             :  *
     208             :  * Parameters:
     209             :  *    lsp/isp        I: Line spectral pairs (cosine domaine)      Q15
     210             :  *    f              O: the coefficients of F1 or F2        Q23
     211             :  *    n              I: no of coefficients (m/2)
     212             :  *                      == NC for F1(z); == NC-1 for F2(z)
     213             :  *    fact           I: scaling factor
     214             :  *
     215             :  *-----------------------------------------------------------*
     216             :  * procedure E_LPC_f_lsp_pol_get:                            *
     217             :  *           ~~~~~~~~~~~                                     *
     218             :  *   Find the polynomial F1(z) or F2(z) from the LSPs.       *
     219             :  * This is performed by expanding the product polynomials:   *
     220             :  *                                                           *
     221             :  * F1(z) =   product   ( 1 - 2 LSF_i z^-1 + z^-2 )           *
     222             :  *         i=0,2,4,6,8                                       *
     223             :  * F2(z) =   product   ( 1 - 2 LSF_i z^-1 + z^-2 )           *
     224             :  *         i=1,3,5,7,9                                       *
     225             :  *                                                           *
     226             :  * where LSP_i are the LSPs in the cosine domain.            *
     227             :  *                                                           *
     228             :  *-----------------------------------------------------------*
     229             :  *   R.A.Salami    October 1990                              *
     230             :  *-----------------------------------------------------------*
     231             :  */
     232       62968 : static Word16 E_LPC_f_lsp_pol_get(
     233             :     const Word16 lsp[],    /* Q15 */
     234             :     Word32 f[],            /* Q23 */
     235             :     const Word16 n,        /* Q0 */
     236             :     const Word16 past_Ovf, /* Q0 */
     237             :     const Word16 isMODE1   /* Q0 */
     238             : )
     239             : {
     240             :     /* All computation in Q23 */
     241             :     const Word16 *plsp;
     242             :     Word16 i, j;
     243             :     Word16 b;
     244             :     Word32 b32;
     245       62968 :     Word16 Ovf = 0;
     246             :     Word16 Q_out;
     247             :     Word16 m2;
     248             :     Flag Overflow;
     249       62968 :     move16(); // move for Ovf = 0
     250             : 
     251       62968 :     Q_out = 31 - 23;
     252       62968 :     move16();
     253       62968 :     Ovf = past_Ovf;
     254       62968 :     move16();
     255             : 
     256       62968 :     test();
     257       62968 :     if ( past_Ovf && isMODE1 ) /* Currently this feature is implemented only in MODE1 */
     258             :     {
     259             :         /* In some NB cases, overflow where detectected
     260             :             in f1 or f2 polynomial computation when it
     261             :             happen we reduce the precision of the computing
     262             :             to limit the risk of saturation*/
     263           0 :         Q_out = add( Q_out, past_Ovf );
     264             :     }
     265       62968 :     Overflow = 0;
     266       62968 :     move16();
     267       62968 :     plsp = lsp;
     268       62968 :     f[0] = L_shl( 1, sub( 31, Q_out ) );
     269       62968 :     move32();
     270             :     /*b = -2.0f * *plsp;*/
     271       62968 :     b = *plsp;
     272       62968 :     move16();
     273       62968 :     m2 = shl( -2, sub( 15, Q_out ) );
     274       62968 :     f[1] = L_mult( b, m2 ); /* Q23 */
     275       62968 :     move32();
     276             : 
     277      503744 :     FOR( i = 2; i <= n; i++ )
     278             :     {
     279      440776 :         plsp += 2;
     280             :         /*b = 2.0f * *plsp;*/
     281      440776 :         move16();
     282      440776 :         b = *plsp;
     283      440776 :         b32 = L_mult( b, m2 );
     284             : 
     285             :         /*f[i] = -b*f[i-1] + 2.0f*f[i-2];*/
     286      440776 :         move32();
     287      440776 :         f[i] = L_shl( L_sub( f[i - 2], Mpy_32_16_1( f[i - 1], b ) ), 1 ); /* Q23 */
     288             : 
     289     1763104 :         FOR( j = i - 1; j > 1; j-- )
     290             :         {
     291             :             /*f[j] += b*f[j-1] + f[j-2];*/
     292     1322328 :             move32();
     293     1322328 :             f[j] = L_add( f[j], L_sub( f[j - 2], L_shl( Mpy_32_16_1( f[j - 1], b ), 1 ) ) ); /* Q23 */
     294             :         }
     295      440776 :         move32();
     296      440776 :         f[1] = L_add( f[1], b32 ); /* Q23 */
     297             :     }
     298             : 
     299             : 
     300       62968 :     test();
     301       62968 :     IF( Overflow > 0 && isMODE1 )
     302             :     {
     303           0 :         assert( 0 );
     304             :         /* If an overflow is detected, redo the computation with 1 bit less */
     305             :         Ovf = add( Ovf, 1 );
     306             :         Ovf = E_LPC_f_lsp_pol_get( lsp, f, n, Ovf, isMODE1 ); /* Q0 */
     307             :     }
     308       62968 :     return Ovf;
     309             : }
     310             : 
     311             : #undef WMC_TOOL_SKIP

Generated by: LCOV version 1.14