LCOV - code coverage report
Current view: top level - lib_com - basop_lsf_tools.c (source / functions) Hit Total Coverage
Test: Coverage on main @ 6baab0c613aa6c7100498ed7b93676aa8198a493 Lines: 76 88 86.4 %
Date: 2025-05-29 08:28:55 Functions: 3 3 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             : /*====================================================================================
      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      635091 : void basop_E_LPC_f_lsp_a_conversion(
      65             :     const Word16 *lsp,
      66             :     Word16 *a,
      67             :     const Word16 m )
      68             : {
      69             :     Word16 i, j, k;
      70             :     Word32 f1[NC_MAX + 1], f2[NC_MAX + 1];
      71             :     Word16 nc;
      72             :     Word32 t0;
      73             :     Word16 Ovf, Ovf2;
      74             : 
      75             : 
      76             :     /*-----------------------------------------------------*
      77             :      *  Find the polynomials F1(z) and F2(z)               *
      78             :      *-----------------------------------------------------*/
      79             : 
      80      635091 :     nc = shr( m, 1 );
      81             : 
      82      635091 :     assert( m == 16 || m == 10 );
      83             : 
      84      635091 :     Ovf = 0;
      85      635091 :     move16();
      86      635091 :     Ovf = E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, Ovf, 1 );
      87      635091 :     Ovf2 = E_LPC_f_lsp_pol_get( &lsp[1], f2, nc, Ovf, 1 );
      88      635091 :     IF( sub( Ovf2, Ovf ) != 0 )
      89             :     {
      90             :         /* to ensure similar scaling for f1 and f2 in case
      91             :           an overflow would be detected only in f2,
      92             :           but this case never happen on my dtb */
      93           0 :         E_LPC_f_lsp_pol_get( &lsp[0], f1, nc, s_max( Ovf2, Ovf ), 1 );
      94             :     }
      95             :     /*-----------------------------------------------------*
      96             :      *  Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1)   *
      97             :      *-----------------------------------------------------*/
      98             :     /*modification*/
      99      635091 :     k = sub( nc, 1 );
     100     5715819 :     FOR( i = 0; i <= k; i++ )
     101             :     {
     102     5080728 :         f1[nc - i] = L_add( f1[nc - i], f1[nc - i - 1] );
     103     5080728 :         move32();
     104     5080728 :         f2[nc - i] = L_sub( f2[nc - i], f2[nc - i - 1] );
     105     5080728 :         move32();
     106             :     }
     107             : 
     108             :     /*-----------------------------------------------------*
     109             :      *  A(z) = (F1(z)+F2(z))/2                             *
     110             :      *  F1(z) is symmetric and F2(z) is antisymmetric      *
     111             :      *-----------------------------------------------------*/
     112             : 
     113      635091 :     t0 = L_deposit_l( 0 );
     114     5715819 :     FOR( i = 1; i <= nc; i++ )
     115             :     {
     116     5080728 :         t0 = L_max( t0, L_abs( L_add( f1[i], f2[i] ) ) );
     117     5080728 :         t0 = L_max( t0, L_abs( L_sub( f1[i], f2[i] ) ) );
     118             :     }
     119      635091 :     k = s_min( norm_l( t0 ), 6 );
     120      635091 :     a[0] = shl( 256, k );
     121      635091 :     move16();
     122      635091 :     test();
     123      635091 :     IF( Ovf || Ovf2 )
     124             :     {
     125           0 :         a[0] = shl( 256, sub( k, Ovf ) );
     126           0 :         move16();
     127             :     }
     128      635091 :     j = m;
     129     5715819 :     FOR( i = 1; i <= nc; i++ )
     130             :     {
     131             :         /* a[i] = 0.5*(f1[i] + f2[i]) */
     132     5080728 :         t0 = L_add( f1[i], f2[i] );
     133     5080728 :         t0 = L_shl( t0, k );
     134     5080728 :         a[i] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
     135             : 
     136             :         /* a[j] = 0.5*(f1[i] - f2[i]) */
     137     5080728 :         t0 = L_sub( f1[i], f2[i] );
     138     5080728 :         t0 = L_shl( t0, k );
     139     5080728 :         a[j] = round_fx( t0 ); /* from Q23 to Qx and * 0.5 */
     140     5080728 :         j--;
     141             :     }
     142             : 
     143      635091 :     return;
     144             : }
     145             : 
     146             : 
     147             : /*---------------------------------------------------------------------------
     148             :  * procedure  reorder_lsf()
     149             :  *
     150             :  * To make sure that the  lsfs are properly ordered and to keep a certain
     151             :  * minimum distance between consecutive lsfs.
     152             :  *--------------------------------------------------------------------------*/
     153      635283 : void basop_reorder_lsf(
     154             :     Word16 *lsf,           /* i/o: LSFs in the frequency domain (0..0.5)   Q(x2.56)*/
     155             :     const Word16 min_dist, /* i  : minimum required distance               x2.56*/
     156             :     const Word16 n,        /* i  : LPC order                               */
     157             :     const Word32 Fs        /* i  : sampling frequency                      */
     158             : )
     159             : {
     160             :     Word16 i, lsf_min, n_m_1;
     161             :     Word16 lsf_max;
     162             : 
     163      635283 :     lsf_min = min_dist;
     164      635283 :     move16();
     165             : 
     166             :     /*-----------------------------------------------------------------------*
     167             :      * Verify the LSF ordering and minimum GAP
     168             :      *-----------------------------------------------------------------------*/
     169             : 
     170    10799811 :     FOR( i = 0; i < n; i++ )
     171             :     {
     172    10164528 :         if ( sub( lsf[i], lsf_min ) < 0 )
     173             :         {
     174           0 :             lsf[i] = lsf_min;
     175           0 :             move16();
     176             :         }
     177    10164528 :         lsf_min = add( lsf[i], min_dist );
     178             :     }
     179             : 
     180             :     /*-----------------------------------------------------------------------*
     181             :      * Reverify the LSF ordering and minimum GAP in the reverse order (security)
     182             :      *-----------------------------------------------------------------------*/
     183             : 
     184      635283 :     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 */
     185             : 
     186      635283 :     n_m_1 = sub( n, 1 );
     187      635283 :     IF( sub( lsf[n_m_1], lsf_max ) > 0 ) /* If danger of unstable filter in case of resonance in HF */
     188             :     {
     189           0 :         FOR( i = n_m_1; i >= 0; i-- ) /* Reverify the minimum LSF gap in the reverse direction */
     190             :         {
     191           0 :             if ( sub( lsf[i], lsf_max ) > 0 )
     192             :             {
     193           0 :                 lsf[i] = lsf_max;
     194           0 :                 move16();
     195             :             }
     196           0 :             lsf_max = sub( lsf[i], min_dist );
     197             :         }
     198             :     }
     199             : 
     200      635283 :     return;
     201             : }
     202             : 
     203             : 
     204             : /*
     205             :  * E_LPC_f_lsp_pol_get
     206             :  *
     207             :  * Parameters:
     208             :  *    lsp/isp        I: Line spectral pairs (cosine domaine)      Q15
     209             :  *    f              O: the coefficients of F1 or F2        Q23
     210             :  *    n              I: no of coefficients (m/2)
     211             :  *                      == NC for F1(z); == NC-1 for F2(z)
     212             :  *    fact           I: scaling factor
     213             :  *
     214             :  *-----------------------------------------------------------*
     215             :  * procedure E_LPC_f_lsp_pol_get:                            *
     216             :  *           ~~~~~~~~~~~                                     *
     217             :  *   Find the polynomial F1(z) or F2(z) from the LSPs.       *
     218             :  * This is performed by expanding the product polynomials:   *
     219             :  *                                                           *
     220             :  * F1(z) =   product   ( 1 - 2 LSF_i z^-1 + z^-2 )           *
     221             :  *         i=0,2,4,6,8                                       *
     222             :  * F2(z) =   product   ( 1 - 2 LSF_i z^-1 + z^-2 )           *
     223             :  *         i=1,3,5,7,9                                       *
     224             :  *                                                           *
     225             :  * where LSP_i are the LSPs in the cosine domain.            *
     226             :  *                                                           *
     227             :  *-----------------------------------------------------------*
     228             :  *   R.A.Salami    October 1990                              *
     229             :  *-----------------------------------------------------------*
     230             :  */
     231     1270182 : static Word16 E_LPC_f_lsp_pol_get(
     232             :     const Word16 lsp[],
     233             :     Word32 f[],
     234             :     const Word16 n,
     235             :     const Word16 past_Ovf,
     236             :     const Word16 isMODE1 )
     237             : {
     238             :     /* All computation in Q23 */
     239             :     const Word16 *plsp;
     240             :     Word16 i, j;
     241             :     Word16 b;
     242             :     Word32 b32;
     243     1270182 :     Word16 Ovf = 0;
     244             :     Word16 Q_out;
     245             :     Word16 m2;
     246             : #ifdef BASOP_NOGLOB
     247             :     Flag Overflow;
     248             : #endif /* BASOP_NOGLOB */
     249             : 
     250             : 
     251     1270182 :     Q_out = 31 - 23;
     252     1270182 :     move16();
     253     1270182 :     Ovf = past_Ovf;
     254     1270182 :     move16();
     255             : 
     256     1270182 :     test();
     257     1270182 :     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     1270182 :     Overflow = 0;
     266     1270182 :     move16();
     267     1270182 :     plsp = lsp;
     268     1270182 :     f[0] = L_shl( 1, sub( 31, Q_out ) );
     269     1270182 :     move32();
     270             :     /*b = -2.0f * *plsp;*/
     271     1270182 :     b = *plsp;
     272     1270182 :     move16();
     273     1270182 :     m2 = shl( -2, sub( 15, Q_out ) );
     274     1270182 :     f[1] = L_mult( b, m2 );
     275     1270182 :     move32();
     276             : 
     277    10161456 :     FOR( i = 2; i <= n; i++ )
     278             :     {
     279     8891274 :         plsp += 2;
     280             :         /*b = 2.0f * *plsp;*/
     281     8891274 :         move16();
     282     8891274 :         b = *plsp;
     283     8891274 :         b32 = L_mult( b, m2 );
     284             : 
     285             :         /*f[i] = -b*f[i-1] + 2.0f*f[i-2];*/
     286     8891274 :         move32();
     287     8891274 :         f[i] = L_shl( L_sub( f[i - 2], Mpy_32_16( f[i - 1], b ) ), 1 );
     288             : 
     289    35565096 :         FOR( j = i - 1; j > 1; j-- )
     290             :         {
     291             :             /*f[j] += b*f[j-1] + f[j-2];*/
     292    26673822 :             move32();
     293    26673822 :             f[j] = L_add( f[j], L_sub( f[j - 2], L_shl( Mpy_32_16( f[j - 1], b ), 1 ) ) );
     294             :         }
     295     8891274 :         move32();
     296     8891274 :         f[1] = L_add( f[1], b32 );
     297             :     }
     298             : 
     299             : 
     300     1270182 :     test();
     301     1270182 :     IF( Overflow > 0 && isMODE1 )
     302             :     {
     303             : #ifdef BASOP_NOGLOB
     304           0 :         assert( 0 );
     305             : #endif /* BASOP_NOGLOB */
     306             :         /* If an overflow is detected, redo the computation with 1 bit less */
     307             :         Ovf = add( Ovf, 1 );
     308             :         Ovf = E_LPC_f_lsp_pol_get( lsp, f, n, Ovf, isMODE1 );
     309             :     }
     310     1270182 :     return Ovf;
     311             : }
     312             : 
     313             : #undef WMC_TOOL_SKIP

Generated by: LCOV version 1.14