LCOV - code coverage report
Current view: top level - lib_lc3plus - plc_phecu_tools_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 78 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.5.1                               *
       3             : *              Low Complexity Communication Codec Plus (LC3plus)              *
       4             : *                                                                             *
       5             : * Copyright licence is solely granted through ETSI Intellectual Property      *
       6             : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
       7             : * estoppel or otherwise.                                                      *
       8             : ******************************************************************************/
       9             : 
      10             : #include "defines.h"
      11             : #include "functions.h"
      12             : 
      13             : /* initilize a short vector */
      14           0 : void plc_phEcu_initWord16(Word16 *     vec,   /*i/o : short vector pointer       */
      15             :                           const Word16 value, /*i   : short initialization value */
      16             :                           const Word16 len)   /*i   : number of elements         */
      17             : {
      18             :     Counter n;
      19             : 
      20           0 :     FOR (n = 0; n < len; n++)
      21             :     {
      22           0 :         vec[n] = value; move16();
      23             :     }
      24           0 : }
      25             : 
      26             : /* scale inplace with allowed saturation in upscaling ,  function not available in basop_util */
      27           0 : void Scale_sig_sat(Word16       x[], /* i/o: signal to scale                 Qx        */
      28             :                   const Word16 lg,   /* i  : size of x[]                     Q0        */
      29             :                   const Word16 exp0  /* i  : exponent: x = round(x << exp)   Qx ?exp  */
      30             : )
      31             : {
      32             :     Counter i;
      33             :     Word16  tmp;
      34           0 :     IF (exp0 > 0)
      35             :     {
      36           0 :         FOR (i = 0; i < lg; i++)
      37             :         {
      38           0 :             x[i] = shl_sat(x[i], exp0);  move16(); /* no saturation warnings triggered here */
      39             :         }
      40           0 :         return;
      41             :     }
      42           0 :     IF (exp0 < 0)
      43             :     {
      44           0 :         tmp = shl(-32768, s_max(exp0, -15)); /* we use negative to correctly represent 1.0 */
      45           0 :         FOR (i = 0; i < lg; i++)
      46             :         {
      47           0 :             x[i] = msu_r(0, x[i], tmp);  move16(); /* msu instead of mac because factor is negative */
      48             :         }
      49           0 :         return;
      50             :     }
      51             : }
      52             : 
      53           0 : void plc_phEcu_minval_fx(const Word16 *inp,      /* i  : vector       */
      54             :                          const Word16  len,      /* i  : length       */
      55             :                          Word16       *minvalPtr /* o  : min  value Ptr    */
      56             : )
      57             : {
      58             :     Word16  minTmp;
      59             :     Counter pos;
      60             : 
      61           0 :     minTmp = inp[0];  move16();
      62           0 :     assert(len>1);
      63           0 :     FOR (pos = 1; pos < len; pos++)
      64             :     {
      65           0 :         minTmp = s_min(inp[pos], minTmp);
      66             :     }
      67             : 
      68           0 :     *minvalPtr = minTmp;  move16();
      69           0 : }
      70             : 
      71           0 : void plc_phEcu_maxval_fx(const Word16 *inp,      /* i  : vector     */
      72             :                          const Word16  len,      /* i  : length     */
      73             :                          Word16       *maxvalPtr /* o  : *maxvalPtr */
      74             : )
      75             : {
      76             :     Word16  maxTmp;
      77             :     Counter pos;
      78             : 
      79           0 :     maxTmp = inp[0];  move16();
      80             : 
      81           0 :     assert(len>1);
      82           0 :     FOR (pos = 1; pos < len; pos++)
      83             :     {
      84           0 :         maxTmp = s_max(inp[pos], maxTmp);
      85             :     }
      86           0 :     *maxvalPtr = maxTmp;  move16();
      87           0 : }
      88             : 
      89             : /* in case a  value (e.g max or min)  is already known , find the first corresponding array  index */
      90           0 : Word16  plc_phEcu_find_ind_fx(                        /* o  : output maximum  indx 0.. len-1    */
      91             :                               const Word16 *inp,      /* i  : vector     */
      92             :                               const Word16  len,      /* i  : length     */
      93             :                               const Word16  val   /* i  : value to find     */
      94             : )       
      95             : {
      96             :    Word16  val_ind;
      97             :    Counter pos;
      98             : 
      99           0 :    val_ind = -1;  move16();
     100             : 
     101           0 :    FOR(pos = 0; pos < len; pos++)
     102             :    {
     103           0 :       if (sub(inp[pos], val) == 0)
     104             :       {
     105           0 :          val_ind = pos;  move16();
     106             :       }
     107             :    }
     108           0 :    return   val_ind;
     109             : }
     110             : 
     111             : /*-----------------------------------------------------------------------------
     112             :  * ratio_fx()
     113             :  *
     114             :  * Divide the numerator by the denominator.
     115             :  *----------------------------------------------------------------------------*/
     116           0 : Word16 plc_phEcu_ratio_fx(                     /* o : quotient   in Q14       */
     117             :                           const Word32 numer,  /* i : numerator               */
     118             :                           const Word32 denom,  /* i : denominator             */
     119             :                           Word16 *expo)        /* o : req shift of quotient   */
     120             : {
     121             :     Word16 expNumer, expDenom;
     122             :     Word16 manNumer, manDenom;
     123             :     Word16 quotient;
     124             : #ifdef DYNMEM_COUNT
     125             :     Dyn_Mem_In("plc_phEcu_ratio_fx", sizeof(struct {
     126             :                    Word16 expNumer, expDenom;
     127             :                    Word16 manNumer, manDenom;
     128             :                    Word16 quotient;
     129             :                }));
     130             : #endif
     131             : 
     132           0 :     expDenom = norm_l(denom);                     /* exponent */
     133           0 :     manDenom = extract_h(L_shl(denom, expDenom)); /* mantissa */
     134           0 :     expNumer = norm_l(numer);                     /* exponent */
     135           0 :     manNumer = extract_h(L_shl(numer, expNumer)); /* mantissa */
     136           0 :     manNumer = shr_pos(manNumer, 1);              /* Ensure the numerator < the denominator */
     137           0 :     quotient = div_s(manNumer, manDenom);         /* in Q14 */
     138             : 
     139           0 :     *expo = sub(expNumer, expDenom);
     140             : #ifdef DYNMEM_COUNT
     141             :     Dyn_Mem_Out();
     142             : #endif
     143           0 :     return quotient; /* Q14 */
     144             : }
     145             : 
     146           0 : Word32 winEnCalc(                          /* o:  output summed energy Ltot */
     147             :                  const Word16 *x,          /* i: Input signal */
     148             :                  const Word16 headroom_shift,    /* i: headroom_shift */
     149             :                  const Word16 *win,        /* i: left side Window coefficients */
     150             :                  const Word16  rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */
     151             :                  const Word16  halfLength,  /* i: Half of the total length of a complete Hamming window. */
     152             :                  Word16    *exp             /* i/o : i exp of Word16 variable x ,  o:Lexp of output Word32 sum */     
     153             :                  )
     154             : {
     155             :     Counter       i;
     156             :     Word32        L_tot; 
     157             :     const Word16 *pX, *pW;
     158             :     Word16        tmp, tmp_RL;
     159             : 
     160             : #ifdef DYNMEM_COUNT
     161             :     Dyn_Mem_In("PhEcu::GF::winEnCalc", sizeof(struct {
     162             :                    Counter       i;
     163             :                     Word32        L_tot;               
     164             :                    const Word16 *pX, *pW;
     165             :                    Word16 tmp, tmp_RL;
     166             :                }));
     167             : #endif
     168             : 
     169             : 
     170             : #ifdef WMOPS
     171             :     push_wmops("PhECU::winEnCalc");
     172             : #endif
     173             : 
     174           0 :     L_tot = INT32_MAX; move32(); /*acc is on negative side , but as all accumulation is positive, we make use of one extra bit   */
     175           0 :     pX   = x;
     176           0 :     pW   = win;
     177             :    
     178             : 
     179           0 :     assert( headroom_shift>=0 );
     180           0 :     FOR (i = 0; i < halfLength; i++) /* 1st symmetric half of the Hamming window */
     181             :     {
     182           0 :           tmp   = mult(*pX++, *pW++);   
     183           0 :           tmp   = shr_pos(tmp, headroom_shift);  /* shr  may/create  bias on the negative side , costly options are shr_r or use msu_r */
     184           0 :           L_tot = L_msu0(L_tot, tmp, tmp);       /* acc on negative energy side */
     185             :     }
     186             : 
     187             :     /* Periodic filter - one more rect sample before end tapering */
     188           0 :     tmp_RL = add(rectLength, 1);
     189           0 :     ASSERT(rectLength != 0);
     190             : 
     191           0 :     FOR (i = 0; i < tmp_RL; i++) /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */
     192             :     {    
     193           0 :           tmp   = shr_pos( *pX++, headroom_shift);
     194           0 :           L_tot = L_msu0(L_tot, tmp, tmp); /* acc on negative side */
     195             :     }
     196             : 
     197           0 :     tmp_RL = sub(halfLength, 1);
     198           0 :     ASSERT(rectLength != 0);
     199             : 
     200           0 :     FOR (i = 0; i < tmp_RL; i++) /* 2nd symmetric half of the Hamming window. */
     201             :     {
     202           0 :         tmp   = mult(*pX++, *(--pW));   
     203           0 :         tmp   = shr_pos(tmp, headroom_shift);
     204           0 :         L_tot = L_msu0(L_tot, tmp, tmp);
     205             :     }
     206             : 
     207             :   /*  Lexp = 2*(incoming_exp + dnshift) + 1  , 2x for square + 1(for msu0 DSP dn shift)*/
     208           0 :    *exp   =   add(shl_pos(add(*exp, headroom_shift),1),1);  
     209             : 
     210             :      /* handle wrap on zero point */
     211           0 :     IF( L_tot >= 0 )
     212             :     {  /* L_tot positive           --> less than 32 bits needed, */
     213           0 :        L_tot = L_add(L_tot,(INT32_MIN+1));
     214           0 :        if( L_tot == 0 )
     215             :        {      
     216           0 :           *exp =  LTOT_MIN_EXP; /* WC is actually (-(15+4)*2 + 1 +1  -31) */ ;  move16();
     217             :        }  
     218           0 :        L_tot =  L_min(L_tot, -1);     /* make sure there is energy for future ratio calculations */
     219             :     } 
     220             :     ELSE 
     221             :     {   /* L_tot negative --> more than 31 bits needed for sum , scale  32 bit sum within 31 bits  and  adjust exp */
     222             :  
     223           0 :          L_tot = L_shr_pos(L_add(L_tot,1),1);  /* rnd by adding 1,  then use 50% contribution from negative  side */
     224           0 :          L_tot = L_add(L_tot, INT32_MIN>>1);     /* add 50% contribution from positive side */      
     225             :     
     226           0 :         *exp =  add(*exp, 1);             move16(); 
     227             :     } 
     228             : 
     229           0 :     L_tot = L_max( -(INT32_MAX), L_tot);  /* guard against max accumulation on the  negative side , should only occur for rectangle windows */
     230           0 :     L_tot = L_negate(L_tot); /* no saturation here */
     231             : 
     232             :     /* activate when xfp_exp is not used any longer */  
     233             :     /*  pre-maximize the mantissa for  the following  steps  in burst_ana_dx  */
     234           0 :     tmp   = norm_l(L_tot);
     235           0 :     L_tot =  L_shl(L_tot,tmp);
     236           0 :     *exp  =  sub(*exp, tmp);  move16();
     237             : 
     238             : #ifdef WMOPS
     239             :  pop_wmops();
     240             : #endif
     241             : #ifdef DYNMEM_COUNT
     242             :     Dyn_Mem_Out();
     243             : #endif
     244             :    
     245           0 :     return L_tot;
     246             : }
     247             : 

Generated by: LCOV version 1.14