LCOV - code coverage report
Current view: top level - lib_com - ari_hm.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 91 92 98.9 %
Date: 2025-05-23 08:37:30 Functions: 5 5 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 "cnst.h"
      41             : #include "stl.h"
      42             : #include "basop_util.h"
      43             : #include "prot.h"
      44             : #include "rom_com.h"
      45             : #include "wmc_auto.h"
      46             : 
      47             : /*-------------------------------------------------------------------*
      48             :  * UnmapIndex()
      49             :  *
      50             :  *
      51             :  *-------------------------------------------------------------------*/
      52             : 
      53      252597 : void UnmapIndex(
      54             :     const int16_t PeriodicityIndex,
      55             :     const int16_t Bandwidth,
      56             :     const int16_t LtpPitchLag,
      57             :     const int16_t SmallerLags,
      58             :     int16_t *FractionalResolution,
      59             :     int32_t *Lag )
      60             : {
      61      252597 :     if ( ( LtpPitchLag > 0 ) && ( PeriodicityIndex & kLtpHmFlag ) )
      62       78481 :     {
      63             :         int16_t LtpPitchIndex, Multiplier;
      64       78481 :         LtpPitchIndex = PeriodicityIndex >> 9;
      65       78481 :         Multiplier = PeriodicityIndex & 0xff;
      66       78481 :         assert( 0 <= LtpPitchIndex && LtpPitchIndex <= 16 );
      67       78481 :         assert( 1 <= Multiplier && Multiplier <= ( 1 << NumRatioBits[Bandwidth][LtpPitchIndex] ) );
      68       78481 :         *FractionalResolution = kLtpHmFractionalResolution;
      69       78481 :         *Lag = ( LtpPitchLag * (int32_t) ( 4 * Ratios[Bandwidth][LtpPitchIndex][Multiplier - 1] ) ) >> 2;
      70             :     }
      71             :     else
      72             :     {
      73      174116 :         if ( PeriodicityIndex < 16 )
      74             :         {
      75      100505 :             *FractionalResolution = 3;
      76      100505 :             *Lag = PeriodicityIndex + GET_ADJ( 0, 6 );
      77             :         }
      78       73611 :         else if ( PeriodicityIndex < 80 )
      79             :         {
      80       34043 :             *FractionalResolution = 4;
      81       34043 :             *Lag = PeriodicityIndex + GET_ADJ( 16, 8 );
      82             :         }
      83       39568 :         else if ( PeriodicityIndex < 208 )
      84             :         {
      85       33404 :             *FractionalResolution = 3;
      86       33404 :             *Lag = PeriodicityIndex + GET_ADJ( 80, 12 );
      87             :         }
      88        6164 :         else if ( PeriodicityIndex < 224 || SmallerLags )
      89             :         {
      90        4925 :             *FractionalResolution = 1;
      91        4925 :             *Lag = PeriodicityIndex + GET_ADJ( 208, 28 );
      92             :         }
      93             :         else
      94             :         {
      95        1239 :             *FractionalResolution = 0;
      96        1239 :             *Lag = PeriodicityIndex + GET_ADJ( 224, 188 );
      97             :         }
      98             :     }
      99             : 
     100      252597 :     return;
     101             : }
     102             : 
     103             : 
     104             : /*-------------------------------------------------------------------*
     105             :  * ConfigureContextHm()
     106             :  *
     107             :  *
     108             :  *-------------------------------------------------------------------*/
     109             : 
     110      218869 : void ConfigureContextHm(
     111             :     const int16_t NumCoeffs,        /* (I) Number of coefficients                         */
     112             :     const int16_t TargetBits,       /* (I) Target bit budget (excl. Done flag)            */
     113             :     const int16_t PeriodicityIndex, /* (I) Pitch related index                            */
     114             :     const int16_t LtpPitchLag,      /* (I) TCX-LTP pitch in F.D.                          */
     115             :     CONTEXT_HM_CONFIG *hm_cfg       /* (O) Context-based harmonic model configuration     */
     116             : )
     117             : {
     118             :     int16_t Bandwidth, SmallerLags;
     119             :     int32_t i, Lag;
     120             :     int16_t j, FractionalResolution;
     121             :     int32_t Limit;
     122             :     int16_t Index;
     123             :     int16_t *tmp;
     124             : 
     125      218869 :     Bandwidth = 0;
     126      218869 :     if ( NumCoeffs >= 256 )
     127             :     {
     128      218869 :         Bandwidth = 1;
     129             :     }
     130             : 
     131      218869 :     SmallerLags = 0;
     132             : 
     133      218869 :     if ( TargetBits <= kSmallerLagsTargetBitsThreshold || Bandwidth == 0 )
     134             :     {
     135       10368 :         SmallerLags = 1;
     136             :     }
     137             : 
     138      218869 :     UnmapIndex( PeriodicityIndex, Bandwidth, LtpPitchLag, SmallerLags, &FractionalResolution, &Lag );
     139             : 
     140             :     /* Set up and fill peakIndices */
     141      218869 :     hm_cfg->peakIndices = hm_cfg->indexBuffer;
     142      218869 :     tmp = hm_cfg->peakIndices;
     143      218869 :     Limit = ( NumCoeffs - 1 ) << FractionalResolution;
     144             : 
     145    21528993 :     for ( i = Lag; i < Limit; i += Lag )
     146             :     {
     147    21310124 :         Index = (int16_t) ( i >> FractionalResolution );
     148    21310124 :         *tmp++ = Index - 1;
     149    21310124 :         *tmp++ = Index;
     150    21310124 :         *tmp++ = Index + 1;
     151             :     }
     152      218869 :     hm_cfg->numPeakIndices = (int16_t) ( tmp - hm_cfg->indexBuffer );
     153             : 
     154             :     /* Set up and fill holeIndices */
     155      218869 :     hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices;
     156      218869 :     tmp = hm_cfg->holeIndices;
     157      218869 :     Index = 0;
     158             : 
     159    21528993 :     for ( j = 0; j < hm_cfg->numPeakIndices; j += 3 )
     160             :     {
     161   138468088 :         for ( ; Index < hm_cfg->peakIndices[j]; ++Index )
     162             :         {
     163   117157964 :             *tmp++ = Index;
     164             :         }
     165    21310124 :         Index += 3; /* Skip the peak */
     166             :     }
     167             : 
     168     1568293 :     for ( ; Index < NumCoeffs; ++Index )
     169             :     {
     170     1349424 :         *tmp++ = Index;
     171             :     }
     172      218869 :     hm_cfg->numHoleIndices = (int16_t) ( tmp - hm_cfg->holeIndices );
     173             :     /* Add extremal element signaling the end of the buffer */
     174      218869 :     *tmp++ = NumCoeffs;
     175             : 
     176      218869 :     return;
     177             : }
     178             : 
     179             : 
     180             : /*-------------------------------------------------------------------*
     181             :  * CountIndexBits()
     182             :  *
     183             :  *
     184             :  *-------------------------------------------------------------------*/
     185             : 
     186      207761 : int16_t CountIndexBits(
     187             :     const int16_t Bandwidth,
     188             :     const int16_t PeriodicityIndex )
     189             : {
     190      207761 :     if ( PeriodicityIndex & kLtpHmFlag )
     191             :     {
     192       55575 :         int16_t LtpPitchIndex = PeriodicityIndex >> 9;
     193       55575 :         return NumRatioBits[Bandwidth][LtpPitchIndex];
     194             :     }
     195             : 
     196      152186 :     return 8;
     197             : }
     198             : 
     199             : #define WMC_TOOL_SKIP
     200             : 
     201             : /*-------------------------------------------------------------------*
     202             :  * tcx_hm_render()
     203             :  *
     204             :  *
     205             :  *-------------------------------------------------------------------*/
     206             : 
     207       33728 : int16_t tcx_hm_render(
     208             :     const int32_t lag,       /* i  : pitch lag                             */
     209             :     const int16_t fract_res, /* i  : fractional resolution of the lag      */
     210             :     Word16 p[]               /* o  : harmonic model (Q13)                  */
     211             : )
     212             : {
     213             :     int16_t k;
     214             :     Word32 f0, tmp32;
     215             :     Word16 height, PeakDeviation, tmp;
     216             : 
     217             :     /* Set up overall shape */
     218             : 
     219       33728 :     f0 = L_shl( lag, sub( 15, fract_res ) ); /* Q15 */
     220             : 
     221       33728 :     tmp32 = Mpy_32_16( f0, -26474 );
     222       33728 :     tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 );
     223       33728 :     tmp32 = L_sub( 603979776L, tmp32 );
     224       33728 :     tmp32 = L_add( L_add( tmp32, tmp32 ), Mpy_32_16( tmp32, 26214 ) );
     225       33728 :     height = round_fx( tmp32 ); /* Q13 */
     226             : 
     227       33728 :     tmp32 = Mpy_32_16( f0, -18910 );
     228       33728 :     tmp32 = L_shr_r( BASOP_Util_InvLog2( L_shl( tmp32, 7 ) ), 2 );
     229       33728 :     tmp32 = L_sub( 1395864371L, tmp32 );
     230       33728 :     PeakDeviation = round_fx( tmp32 ); /* Q14 */
     231             : 
     232       33728 :     IF( sub( 13915, PeakDeviation ) > 0 )
     233             :     {
     234             :         /* A bit error was encountered */
     235           0 :         return 1;
     236             :     }
     237             :     ELSE
     238             :     {
     239       33728 :         tmp = div_s( 13915, PeakDeviation );
     240       33728 :         tmp = mult_r( tmp, tmp ); /* Q15 */
     241             :     }
     242             : 
     243             :     /* Render the prototype peak */
     244       33728 :     p[kTcxHmParabolaHalfWidth] = height;
     245             : 
     246      168640 :     for ( k = 1; k <= kTcxHmParabolaHalfWidth; ++k )
     247             :     {
     248      134912 :         p[kTcxHmParabolaHalfWidth + k] = round_fx( Mpy_32_16( BASOP_Util_InvLog2( L_shl( L_mult0( mult0( negate( k ), k ), tmp ), 10 ) ), height ) );
     249             :     }
     250             :     /* Mirror */
     251      168640 :     for ( k = -kTcxHmParabolaHalfWidth; k < 0; ++k )
     252             :     {
     253      134912 :         p[kTcxHmParabolaHalfWidth + k] = p[kTcxHmParabolaHalfWidth - k];
     254             :     }
     255             : 
     256       33728 :     return 0;
     257             : }
     258             : 
     259             : 
     260             : /*-------------------------------------------------------------------*
     261             :  * tcx_hm_modify_envelope()
     262             :  *
     263             :  *
     264             :  *-------------------------------------------------------------------*/
     265             : 
     266       56309 : void tcx_hm_modify_envelope(
     267             :     const Word16 gain, /* i  : HM gain (Q11)                         */
     268             :     const int32_t lag,
     269             :     const int16_t fract_res,
     270             :     const Word16 p[],     /* i  : harmonic model (Q13)                  */
     271             :     Word32 env[],         /* i/o: envelope (Q16)                        */
     272             :     const int16_t L_frame /* i  : number of spectral lines              */
     273             : )
     274             : {
     275             :     int32_t h, x, k;
     276             :     Word16 inv_shape[2 * kTcxHmParabolaHalfWidth + 1]; /* Q15 */
     277             : 
     278       56309 :     if ( gain == 0 )
     279             :     {
     280       10559 :         return;
     281             :     }
     282             : 
     283      457500 :     for ( k = 0; k < 2 * kTcxHmParabolaHalfWidth + 1; ++k )
     284             :     {
     285      411750 :         inv_shape[k] = div_s( 512, add( 512, round_fx( L_mult( gain, p[k] ) ) ) );
     286             :     }
     287             : 
     288       45750 :     h = 1;
     289       45750 :     k = lag >> fract_res;
     290             : 
     291     2238856 :     while ( k <= L_frame + kTcxHmParabolaHalfWidth - 1 )
     292             :     {
     293    21806407 :         for ( x = max( 0, k - kTcxHmParabolaHalfWidth ); x <= min( k + kTcxHmParabolaHalfWidth, L_frame - 1 ); ++x )
     294             :         {
     295    19613301 :             env[x] = Mpy_32_16( env[x], inv_shape[x - k + kTcxHmParabolaHalfWidth] );
     296             :         }
     297     2193106 :         ++h;
     298     2193106 :         k = ( h * lag ) >> fract_res;
     299             :     }
     300             : 
     301       45750 :     return;
     302             : }
     303             : 
     304             : #undef WMC_TOOL_SKIP

Generated by: LCOV version 1.14