LCOV - code coverage report
Current view: top level - lib_dec - jbm_pcmdsp_similarityestimation.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 76 111 68.5 %
Date: 2025-05-03 01:55:50 Functions: 5 7 71.4 %

          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             : /*! @file jbm_pcmdsp_similarityestimation.c Algorithms for correlation and similarity estimation. */
      38             : 
      39             : /* system headers */
      40             : #include <stdlib.h>
      41             : #include <math.h>
      42             : #include <stdint.h>
      43             : #include <assert.h>
      44             : #include "options.h"
      45             : #include "wmc_auto.h"
      46             : #include "basop_util.h"
      47             : 
      48             : /* local headers */
      49             : #include "jbm_pcmdsp_similarityestimation.h"
      50             : 
      51             : 
      52             : /* Calculates cross correlation coefficient for template segment. */
      53         566 : void scaleSignal16( const Word16 *src, Word16 *dst, Word16 n, Word16 rightShift )
      54             : {
      55             :     Word16 i;
      56             : 
      57     1826166 :     FOR( i = 0; i < n; i++ )
      58             :     {
      59     1825600 :         dst[i] = shr_r( src[i], rightShift );
      60     1825600 :         move16();
      61             :     }
      62         566 : }
      63             : /* Calculates cross correlation coefficient for template segment. */
      64       97200 : Word32 cross_correlation_subsampled_self_fx( const Word16 *signal,
      65             :                                              Word16 x,
      66             :                                              Word16 y,
      67             :                                              Word16 corr_len,
      68             :                                              Word16 subsampling )
      69             : {
      70             :     Word32 sum;
      71             :     Word16 i;
      72             : 
      73       97200 :     sum = 0;
      74       97200 :     move32();
      75     7873200 :     FOR( i = 0; i < corr_len; i += subsampling )
      76             :     {
      77     7776000 :         sum = L_mac0( sum, signal[x + i], signal[y + i] );
      78             :     }
      79             : 
      80       97200 :     return sum;
      81             : }
      82             : 
      83             : /* Calculates cross correlation coefficient for template segment. */
      84             : 
      85        3608 : Word16 normalized_cross_correlation_self_fx( const Word16 *signal,
      86             :                                              Word16 x,
      87             :                                              Word16 y,
      88             :                                              Word16 corr_len,
      89             :                                              Word16 subsampling,
      90             :                                              Word32 *energy )
      91             : {
      92             :     const Word16 *signalX, *signalY;
      93             :     Word32 sumXY, sumXX, sumYY, product;
      94             :     Word16 sqrtXY, cc;
      95             :     Word16 i, normX, normY, normXY, normCC;
      96             : 
      97        3608 :     signalX = &signal[x];
      98        3608 :     signalY = &signal[y];
      99        3608 :     sumXY = 0;
     100        3608 :     sumXX = 0;
     101        3608 :     sumYY = 0;
     102        3608 :     move32();
     103        3608 :     move32();
     104        3608 :     move32();
     105      758488 :     FOR( i = 0; i < corr_len; i += subsampling )
     106             :     {
     107      754880 :         sumXY = L_mac0( sumXY, signalX[i], signalY[i] );
     108      754880 :         sumXX = L_mac0( sumXX, signalX[i], signalX[i] );
     109      754880 :         sumYY = L_mac0( sumYY, signalY[i], signalY[i] );
     110             :     }
     111             : 
     112        3608 :     normX = norm_l( sumXX );
     113        3608 :     sumXX = L_shl( sumXX, normX );
     114        3608 :     normY = norm_l( sumYY );
     115        3608 :     sumYY = L_shl( sumYY, normY );
     116        3608 :     product = L_mult0( extract_h( sumXX ), extract_h( sumYY ) );
     117        3608 :     normXY = add( normX, normY );
     118        3608 :     normXY = sub( normXY, 32 );
     119             : 
     120             :     /* change norm to factor of 2 */
     121        3608 :     IF( s_and( normXY, 0x1 ) != 0 )
     122             :     {
     123        1566 :         product = L_shr( product, 1 );
     124        1566 :         normXY = sub( normXY, 1 );
     125             :     }
     126        3608 :     sqrtXY = getSqrtWord32( product );
     127        3608 :     normXY = shr( normXY, 1 );
     128             : 
     129        3608 :     IF( sqrtXY != 0 )
     130             :     {
     131        3544 :         Flag Overflow = 0;
     132        3544 :         move32();
     133        3544 :         normCC = 0;
     134        3544 :         move16();
     135        3544 :         cc = BASOP_Util_Divide3216_Scale( sumXY, sqrtXY, &normCC );
     136        3544 :         normCC = add( normCC, 16 );
     137             :         /* scale to Q15 with saturation */
     138             :         BASOP_SATURATE_WARNING_OFF
     139        3544 :         cc = shl_ro( cc, add( normXY, normCC ), &Overflow );
     140             :         BASOP_SATURATE_WARNING_ON
     141        3544 :         *energy = L_shr_r( L_deposit_l( sqrtXY ), normXY );
     142             :     }
     143             :     ELSE /* conceal silent frames */
     144             :     {
     145          64 :         cc = 0;
     146          64 :         move16();
     147          64 :         *energy = L_deposit_l( 1 );
     148          64 :         move32();
     149             :     }
     150             : 
     151        3608 :     return cc; /* Q15 */
     152             : }
     153             : 
     154          27 : Word16 getSignalScaleForCorrelation( Word32 sampleRate )
     155             : {
     156             :     Word16 ret;
     157             : 
     158          27 :     IF( LT_32( sampleRate, 16000 ) )
     159             :     {
     160           0 :         ret = 2;
     161           0 :         move16();
     162             :     }
     163          27 :     ELSE IF( GE_32( sampleRate, 32000 ) )
     164             :     {
     165          24 :         ret = 4;
     166          24 :         move16();
     167             :     }
     168             :     ELSE
     169             :     {
     170           3 :         ret = 3;
     171           3 :         move16();
     172             :     }
     173             : 
     174          27 :     return ret;
     175             : }
     176             : 
     177           0 : Word32 cross_correlation_self_fx( const Word16 *signal,
     178             :                                   Word16 x,
     179             :                                   Word16 y,
     180             :                                   Word16 corr_len )
     181             : {
     182             :     Word32 sum;
     183             :     Word16 i;
     184             : 
     185           0 :     sum = 0;
     186           0 :     move32();
     187           0 :     FOR( i = 0; i < corr_len; i++ )
     188             :     {
     189           0 :         sum = L_mac0( sum, signal[x + i], signal[y + i] );
     190             :     }
     191             : 
     192           0 :     return sum;
     193             : }
     194             : 
     195           0 : Word8 isSilence_fx( const Word16 *signal, Word16 len, Word16 segments )
     196             : {
     197             :     Word16 i, j, samplesPerSegment;
     198             :     Word32 energy, maxEnergy;
     199             :     Word8 ret;
     200             : 
     201           0 :     assert( len > 0 );
     202           0 :     assert( segments > 0 );
     203             : 
     204             :     /* Every segment is checked using the following formula:
     205             :      *   10 * log10(sum_i(signal[i]*signal[i]))) > -65
     206             :      * For simplification/complexity, this is replaced by:
     207             :      *   20 * log10(sum_i(abs(signal[i]))) > -65
     208             :      */
     209             : 
     210           0 :     ret = 1;
     211           0 :     move16();
     212           0 :     energy = 0;
     213           0 :     move32();
     214           0 :     samplesPerSegment = idiv1616U( len, segments );
     215             :     /* calculate maxEnergy with factor 2 to reduce rounding error */
     216           0 :     maxEnergy = L_mult0( samplesPerSegment, 37 ); /* 37 = 2 * exp10(-65.0 / 20) * 32768 */
     217           0 :     maxEnergy = L_shr( maxEnergy, 1 );
     218           0 :     j = samplesPerSegment;
     219           0 :     move16();
     220             :     /* check all but last segment */
     221           0 :     FOR( i = 0; i < len; i++ )
     222             :     {
     223             :         /* division by 32768 is done later */
     224           0 :         energy = L_add( energy, L_abs( L_deposit_l( signal[i] ) ) );
     225           0 :         IF( EQ_16( i, j ) )
     226             :         {
     227             :             /* check energy of current segment */
     228             :             /*     20 * log10(energy / 32768 / samplesPerSegment) > -65
     229             :              * =>  energy > samplesPerSegment * 10 ^ (-65 / 20) * 32768 */
     230           0 :             IF( GT_32( energy, maxEnergy ) )
     231             :             {
     232           0 :                 ret = 0;
     233           0 :                 move16();
     234           0 :                 BREAK;
     235             :             }
     236           0 :             energy = 0;
     237           0 :             move32();
     238           0 :             j = add( j, samplesPerSegment );
     239             :         }
     240             :     }
     241             :     /* check last segment */
     242           0 :     if ( GT_32( energy, maxEnergy ) )
     243             :     {
     244           0 :         ret = 0;
     245           0 :         move16();
     246             :     }
     247           0 :     return ret;
     248             : }
     249             : 
     250         566 : Word8 isSilence_ivas_fx( const Word16 *signal, Word16 q_sig, Word16 len, Word16 segments )
     251             : {
     252             :     Word16 i, j, samplesPerSegment;
     253             :     Word64 energy, maxEnergy;
     254         566 :     Word16 sig_shift = shl( q_sig, 1 );
     255             : 
     256         566 :     assert( len > 0 );
     257         566 :     assert( segments > 0 );
     258             : 
     259             :     /* Every segment is checked using the following formula:
     260             :      *   10 * log10(sum_i(signal[i] / 32768.0 *signal[i] / 32768.0)) / samples_per_segment) > -65
     261             :      * For simplification/complexity, this is replaced by:
     262             :      *   sum_i(signal[i] / 32768.0 * signal[i] / 32768.0) / samples_per_segment > 10^(-65 / 10)
     263             :      *   sum_i(signal[i] * signal[i]) > 10^(-65 / 10) * 32768.0 * 32768.0 * samples_per_segment
     264             :      */
     265             : 
     266         566 :     energy = 0;
     267         566 :     move64();
     268         566 :     samplesPerSegment = idiv1616U( len, segments );
     269         566 :     maxEnergy = W_shl( W_mac0_16_16( 0, samplesPerSegment, 340 ), sig_shift ); /* 340 = 10^(-65.0 / 10) * 32768 * 32768.0 */
     270         566 :     j = samplesPerSegment;
     271         566 :     move16();
     272             :     /* check all but last segment */
     273        1144 :     FOR( i = 0; i < len; i++ )
     274             :     {
     275             :         /* division by 32768 is done later */
     276        1144 :         energy = W_mac0_16_16( energy, signal[i], signal[i] );
     277             :         /* check energy of current segment
     278             :          * =>  energy > samplesPerSegment * 10 ^ (-65 / 10) * 32768 * 32768.0*/
     279        1144 :         IF( GT_64( energy, maxEnergy ) )
     280             :         {
     281         566 :             return 0;
     282             :         }
     283         578 :         IF( EQ_16( i, j ) )
     284             :         {
     285           3 :             energy = 0;
     286           3 :             move64();
     287           3 :             j = add( j, samplesPerSegment );
     288             :         }
     289             :     }
     290             : 
     291           0 :     return 1;
     292             : }

Generated by: LCOV version 1.14