LCOV - code coverage report
Current view: top level - lib_com - ari_hm_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 132 133 99.2 %
Date: 2025-05-03 01:55:50 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : 
       6             : #include <stdint.h>
       7             : #include <assert.h>
       8             : #include "options.h"
       9             : #include "cnst.h"
      10             : #include "basop_util.h"
      11             : #include "rom_com.h"
      12             : #include "prot_fx.h"
      13             : 
      14             : #define GET_ADJ2( T, L, F ) ( ( ( L ) << ( F ) ) - ( T ) )
      15      212169 : void UnmapIndex(
      16             :     const Word16 PeriodicityIndex, /* Q0 */
      17             :     const Word16 Bandwidth,        /* Q0 */
      18             :     const Word16 LtpPitchLag,      /* Q0 */
      19             :     const Word16 SmallerLags,      /* Q0 */
      20             :     Word16 *FractionalResolution,  /* Q0 */
      21             :     Word32 *Lag                    /* Q0 */
      22             : )
      23             : {
      24             :     Word16 LtpPitchIndex, Multiplier;
      25             :     Word16 Lag16;
      26             : 
      27      212169 :     test();
      28      212169 :     IF( ( LtpPitchLag > 0 ) && ( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 ) )
      29             :     {
      30       55533 :         LtpPitchIndex = shr( PeriodicityIndex, 9 );   /* Q0 */
      31       55533 :         Multiplier = s_and( PeriodicityIndex, 0xff ); /* Q0 */
      32             : 
      33       55533 :         assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
      34       55533 :         assert( 1 <= Multiplier && Multiplier <= ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
      35             : 
      36       55533 :         *FractionalResolution = kLtpHmFractionalResolution; /* Q0 */
      37       55533 :         move16();
      38       55533 :         *Lag = L_shr( L_mult0( LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier - 1] ), 8 ); /* Q0 */
      39       55533 :         move32();
      40             :     }
      41             :     ELSE
      42             :     {
      43      156636 :         IF( LT_16( PeriodicityIndex, 16 ) )
      44             :         {
      45      100561 :             *FractionalResolution = 3; /* Q0 */
      46      100561 :             move16();
      47      100561 :             Lag16 = add( PeriodicityIndex, GET_ADJ2( 0, 6, 3 ) ); /* Q0 */
      48             :         }
      49       56075 :         ELSE IF( LT_16( PeriodicityIndex, 80 ) )
      50             :         {
      51       30394 :             *FractionalResolution = 4; /* Q0 */
      52       30394 :             move16();
      53       30394 :             Lag16 = add( PeriodicityIndex, GET_ADJ2( 16, 8, 4 ) ); /* Q0 */
      54             :         }
      55       25681 :         ELSE IF( LT_16( PeriodicityIndex, 208 ) )
      56             :         {
      57       22060 :             *FractionalResolution = 3; /* Q0 */
      58       22060 :             move16();
      59       22060 :             Lag16 = add( PeriodicityIndex, GET_ADJ2( 80, 12, 3 ) ); /* Q0 */
      60             :         }
      61             :         ELSE
      62             :         {
      63        3621 :             test();
      64        3621 :             IF( LT_16( PeriodicityIndex, 224 ) || SmallerLags != 0 )
      65             :             {
      66        2788 :                 *FractionalResolution = 1; /* Q0 */
      67        2788 :                 move16();
      68        2788 :                 Lag16 = add( PeriodicityIndex, GET_ADJ2( 208, 28, 1 ) ); /* Q0 */
      69             :             }
      70             :             ELSE
      71             :             {
      72         833 :                 *FractionalResolution = 0;
      73         833 :                 move16();
      74         833 :                 Lag16 = add( PeriodicityIndex, GET_ADJ2( 224, 188, 0 ) ); /* Q0 */
      75             :             }
      76             :         }
      77      156636 :         *Lag = L_deposit_l( Lag16 ); /* Q0 */
      78      156636 :         move32();
      79             :     }
      80      212169 : }
      81             : 
      82             : 
      83      193230 : void ConfigureContextHm(
      84             :     const Word16 NumCoeffs,        /* (I) Number of coefficients                         Q0*/
      85             :     const Word16 TargetBits,       /* (I) Target bit budget (excl. Done flag)            Q0*/
      86             :     const Word16 PeriodicityIndex, /* (I) Pitch related index                            Q0*/
      87             :     const Word16 LtpPitchLag,      /* (I) TCX-LTP pitch in F.D.                          Q0*/
      88             :     CONTEXT_HM_CONFIG *hm_cfg      /* (O) Context-based harmonic model configuration       */
      89             : )
      90             : {
      91             :     Word8 Bandwidth, SmallerLags;
      92             :     Word32 i, Limit, Lag;
      93             :     Word16 j, Index, FractionalResolution;
      94             :     Word16 *tmp;
      95             : 
      96             : 
      97      193230 :     Bandwidth = 0;
      98      193230 :     move16();
      99      193230 :     if ( GE_16( NumCoeffs, 256 ) )
     100             :     {
     101      193230 :         Bandwidth = 1; /* Q0 */
     102      193230 :         move16();
     103             :     }
     104             : 
     105      193230 :     SmallerLags = 0;
     106      193230 :     move16();
     107      193230 :     test();
     108      193230 :     if ( ( LE_16( TargetBits, kSmallerLagsTargetBitsThreshold ) ) || ( Bandwidth == 0 ) )
     109             :     {
     110        7567 :         SmallerLags = 1; /* Q0 */
     111        7567 :         move16();
     112             :     }
     113             : 
     114      193230 :     UnmapIndex( PeriodicityIndex,
     115             :                 Bandwidth,
     116             :                 LtpPitchLag,
     117             :                 SmallerLags,
     118             :                 &FractionalResolution, &Lag );
     119             : 
     120             :     /* Set up and fill peakIndices */
     121      193230 :     hm_cfg->peakIndices = hm_cfg->indexBuffer;                                 /* Q0 */
     122      193230 :     tmp = hm_cfg->peakIndices;                                                 /* Q0 */
     123      193230 :     Limit = L_shl( L_deposit_l( sub( NumCoeffs, 1 ) ), FractionalResolution ); /* Q0 */
     124      193230 :     IF( LT_32( Lag, Limit ) )
     125             :     {
     126    20493348 :         FOR( i = Lag; i < Limit; i += Lag )
     127             :         {
     128    20300118 :             Index = extract_l( L_shr( i, FractionalResolution ) ); /* Q0 */
     129    20300118 :             *tmp++ = sub( Index, 1 );                              /* Q0 */
     130    20300118 :             move16();
     131    20300118 :             *tmp++ = Index; /* Q0 */
     132    20300118 :             move16();
     133    20300118 :             *tmp++ = add( Index, 1 ); /* Q0 */
     134    20300118 :             move16();
     135             :         }
     136             :     }
     137      193230 :     hm_cfg->numPeakIndices = (Word16) ( tmp - hm_cfg->indexBuffer ); /* Q0 */
     138      193230 :     move16();
     139             : 
     140             :     /* Set up and fill holeIndices */
     141      193230 :     hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices; /* Q0 */
     142      193230 :     tmp = hm_cfg->holeIndices;                                          /* Q0 */
     143      193230 :     Index = 0;
     144      193230 :     move16();
     145      193230 :     IF( hm_cfg->numPeakIndices > 0 )
     146             :     {
     147    20493348 :         FOR( j = 0; j < hm_cfg->numPeakIndices; j += 3 )
     148             :         {
     149   120315782 :             FOR( ; Index < hm_cfg->peakIndices[j]; ++Index )
     150             :             {
     151   100015664 :                 *tmp++ = Index; /* Q0 */
     152   100015664 :                 move16();
     153             :             }
     154    20300118 :             Index = add( Index, 3 ); /* Skip the peak */
     155             :         }
     156             :     }
     157      193230 :     IF( LT_16( Index, NumCoeffs ) )
     158             :     {
     159     1223170 :         FOR( ; Index < NumCoeffs; ++Index )
     160             :         {
     161     1043662 :             *tmp++ = Index;
     162     1043662 :             move16();
     163             :         }
     164             :     }
     165      193230 :     hm_cfg->numHoleIndices = (Word16) ( tmp - hm_cfg->holeIndices );
     166      193230 :     move16();
     167      193230 :     *tmp++ = NumCoeffs;
     168      193230 :     move16(); /* Add extremal element signaling the end of the buffer */
     169      193230 : }
     170             : 
     171      193465 : Word16 CountIndexBits(
     172             :     Word16 Bandwidth,       /* Q0 */
     173             :     Word16 PeriodicityIndex /* Q0 */
     174             : )
     175             : {
     176             :     Word16 result;
     177             :     Word16 PeriodicityIndexS;
     178             : 
     179      193465 :     result = 8;
     180      193465 :     move16();
     181      193465 :     PeriodicityIndexS = shr( PeriodicityIndex, 9 ); /* Q0 */
     182             : 
     183      193465 :     if ( s_and( PeriodicityIndex, kLtpHmFlag ) != 0 )
     184             :     {
     185       47335 :         result = NumRatioBits[Bandwidth][PeriodicityIndexS]; /* Q0 */
     186       47335 :         move16();
     187             :     }
     188             : 
     189      193465 :     return result;
     190             : }
     191             : 
     192             : #define WMC_TOOL_SKIP
     193             : 
     194       18939 : Word32 tcx_hm_render(
     195             :     Word32 lag,       /* i: pitch lag                         Q0  */
     196             :     Word16 fract_res, /* i: fractional resolution of the lag  Q0  */
     197             :     Word16 p[]        /* o: harmonic model                    Q13 */
     198             : )
     199             : {
     200             :     Word16 k, tmp, height;
     201             :     Word16 PeakDeviation;
     202             :     Word32 f0, tmp32;
     203             : 
     204             :     /* Set up overall shape */
     205       18939 :     f0 = L_shl( lag, sub( 15, fract_res ) ); /* Q31 */
     206             : 
     207       18939 :     tmp32 = Mpy_32_16_1( f0, -26474 );
     208       18939 :     tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 );       /* Q29 */
     209       18939 :     tmp32 = L_sub( 603979776L /* 1.125 in Q29 */, tmp32 );               /* Q29 */
     210       18939 :     tmp32 = L_add( L_add( tmp32, tmp32 ), Mpy_32_16_1( tmp32, 26214 ) ); /* Q29 */
     211       18939 :     height = round_fx( tmp32 );                                          /* Q13 */
     212             : 
     213       18939 :     tmp32 = Mpy_32_16_1( f0, -18910 );
     214       18939 :     tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 ); /* Q30 */
     215       18939 :     tmp32 = L_sub( 1395864371L /* 1.3 in Q30 */, tmp32 );          /* Q30 */
     216       18939 :     PeakDeviation = round_fx( tmp32 );                             /* Q14 */
     217             : 
     218       18939 :     IF( GT_16( 13915, PeakDeviation ) )
     219             :     {
     220             :         /* A bit error was encountered */
     221           0 :         return 1;
     222             :     }
     223             :     ELSE
     224             :     {
     225       18939 :         tmp = div_s( 13915, PeakDeviation ); /* Q15 */
     226       18939 :         tmp = mult_r( tmp, tmp );            /* Q15 */
     227             :     }
     228             : 
     229       18939 :     tmp = div_s( 13915, PeakDeviation ); /* Q15 */
     230       18939 :     tmp = mult_r( tmp, tmp );            /* Q15 */
     231             : 
     232             :     /* Render the prototype peak */
     233       18939 :     p[kTcxHmParabolaHalfWidth] = height; /* Q13 */
     234       18939 :     move16();
     235             : 
     236       94695 :     FOR( k = 1; k <= kTcxHmParabolaHalfWidth; ++k )
     237             :     {
     238       75756 :         p[kTcxHmParabolaHalfWidth + k] = round_fx( Mpy_32_16_1( BASOP_Util_InvLog2( L_shl( L_mult0( i_mult2( negate( k ), k ), tmp ), 10 ) ), height ) ); /* Q13 */
     239       75756 :         move16();
     240             :     }
     241             :     /* Mirror */
     242       94695 :     FOR( k = -kTcxHmParabolaHalfWidth; k < 0; ++k )
     243             :     {
     244       75756 :         p[kTcxHmParabolaHalfWidth + k] = p[kTcxHmParabolaHalfWidth - k]; /* Q13 */
     245       75756 :         move16();
     246             :     }
     247             : 
     248       18939 :     return 0;
     249             : }
     250             : 
     251             : 
     252       43176 : void tcx_hm_modify_envelope(
     253             :     Word16 gain,      /* i:   HM gain                           Q11 */
     254             :     Word32 lag,       /* i:   pitch lag                         Q0  */
     255             :     Word16 fract_res, /* i:   fractional resolution of the lag  Q0  */
     256             :     Word16 p[],       /* i:   harmonic model                    Q13 */
     257             :     Word32 env[],     /* i/o: envelope                          Q16 */
     258             :     Word16 L_frame    /* i:   number of spectral lines          Q0  */
     259             : )
     260             : {
     261             :     Word16 k, h, x, l1, l2, L_frame_m1, L_frame_for_loop;
     262             :     Word16 inv_shape[2 * kTcxHmParabolaHalfWidth + 1];
     263             : 
     264       43176 :     IF( gain == 0 )
     265             :     {
     266       11325 :         return;
     267             :     }
     268             : 
     269      318510 :     FOR( k = 0; k < 2 * kTcxHmParabolaHalfWidth + 1; ++k )
     270             :     {
     271             :         /* Q24 = Q11 * Q13; 512 = 1.0 in Q24 format */
     272      286659 :         inv_shape[k] = div_s( 512, add( 512, mult_r( gain, p[k] ) ) ); /* Q15 */
     273      286659 :         move16();
     274             :     }
     275             : 
     276       31851 :     h = 1;
     277       31851 :     move16();
     278       31851 :     k = extract_l( L_shr( lag, fract_res ) ); /* Q0 */
     279             : 
     280       31851 :     L_frame_m1 = sub( L_frame, 1 );                                 /* Q0 */
     281       31851 :     L_frame_for_loop = add( L_frame, kTcxHmParabolaHalfWidth - 1 ); /* Q0 */
     282             : 
     283     1623112 :     WHILE( LE_16( k, L_frame_for_loop ) )
     284             :     {
     285     1591261 :         l1 = s_max( 0, sub( k, kTcxHmParabolaHalfWidth ) );
     286     1591261 :         l2 = s_min( add( k, kTcxHmParabolaHalfWidth ), L_frame_m1 );
     287    15820906 :         FOR( x = l1; x <= l2; ++x )
     288             :         {
     289    14229645 :             env[x] = Mpy_32_16_1( env[x], inv_shape[( x - k ) + kTcxHmParabolaHalfWidth] ); /* Q16 */
     290    14229645 :             move32();
     291             :         }
     292             : 
     293     1591261 :         h = add( h, 1 );                                          /* Q0 */
     294     1591261 :         k = extract_l( L_shr( imult3216( lag, h ), fract_res ) ); /* Q0 */
     295             :     }
     296             : }
     297             : 
     298             : #undef WMC_TOOL_SKIP

Generated by: LCOV version 1.14