LCOV - code coverage report
Current view: top level - lib_dec - jbm_pcmdsp_similarityestimation_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 72 110 65.5 %
Date: 2025-08-23 01:22:27 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         454 : void scaleSignal16( const Word16 *src, Word16 *dst, Word16 n, Word16 rightShift )
      54             : {
      55             :     Word16 i;
      56             : 
      57     1681734 :     FOR( i = 0; i < n; i++ )
      58             :     {
      59     1681280 :         dst[i] = shr_r( src[i], rightShift );
      60     1681280 :         move16();
      61             :     }
      62         454 : }
      63             : /* Calculates cross correlation coefficient for template segment. */
      64       82560 : 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       82560 :     sum = 0;
      74       82560 :     move32();
      75     6687360 :     FOR( i = 0; i < corr_len; i += subsampling )
      76             :     {
      77     6604800 :         sum = L_mac0( sum, signal[x + i], signal[y + i] );
      78             :     }
      79             : 
      80       82560 :     return sum;
      81             : }
      82             : 
      83             : /* Calculates cross correlation coefficient for template segment. */
      84             : 
      85        3251 : 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        3251 :     signalX = &signal[x];
      98        3251 :     signalY = &signal[y];
      99        3251 :     sumXY = 0;
     100        3251 :     sumXX = 0;
     101        3251 :     sumYY = 0;
     102        3251 :     move32();
     103        3251 :     move32();
     104        3251 :     move32();
     105      673411 :     FOR( i = 0; i < corr_len; i += subsampling )
     106             :     {
     107      670160 :         sumXY = L_mac0( sumXY, signalX[i], signalY[i] );
     108      670160 :         sumXX = L_mac0( sumXX, signalX[i], signalX[i] );
     109      670160 :         sumYY = L_mac0( sumYY, signalY[i], signalY[i] );
     110             :     }
     111             : 
     112        3251 :     normX = norm_l( sumXX );
     113        3251 :     sumXX = L_shl( sumXX, normX );
     114        3251 :     normY = norm_l( sumYY );
     115        3251 :     sumYY = L_shl( sumYY, normY );
     116        3251 :     product = L_shr( L_mult0( extract_h( sumXX ), extract_h( sumYY ) ), 1 );
     117        3251 :     normXY = add( normX, normY );
     118        3251 :     normXY = sub( normXY, 32 + 1 );
     119             : 
     120             :     /* change norm to factor of 2 */
     121        3251 :     IF( s_and( normXY, 0x1 ) != 0 )
     122             :     {
     123        1831 :         product = L_shr( product, 1 );
     124        1831 :         normXY = sub( normXY, 1 );
     125             :     }
     126        3251 :     sqrtXY = getSqrtWord32( product );
     127        3251 :     normXY = shr( normXY, 1 );
     128             : 
     129        3251 :     IF( sqrtXY != 0 )
     130             :     {
     131        3189 :         move32();
     132        3189 :         normCC = 0;
     133        3189 :         move16();
     134        3189 :         cc = BASOP_Util_Divide3216_Scale( sumXY, sqrtXY, &normCC );
     135        3189 :         normCC = add( normCC, 16 );
     136             :         /* scale to Q15 with saturation */
     137             :         BASOP_SATURATE_WARNING_OFF
     138        3189 :         cc = shr_r_sat( cc, negate( add( normXY, normCC ) ) );
     139             :         BASOP_SATURATE_WARNING_ON
     140        3189 :         *energy = L_shr_r( L_deposit_l( sqrtXY ), normXY );
     141             :     }
     142             :     ELSE /* conceal silent frames */
     143             :     {
     144          62 :         cc = 0;
     145          62 :         move16();
     146          62 :         *energy = L_deposit_l( 1 );
     147          62 :         move32();
     148             :     }
     149             : 
     150        3251 :     return cc; /* Q15 */
     151             : }
     152             : 
     153          28 : Word16 getSignalScaleForCorrelation( Word32 sampleRate )
     154             : {
     155             :     Word16 ret;
     156             : 
     157          28 :     IF( LT_32( sampleRate, 16000 ) )
     158             :     {
     159           0 :         ret = 2;
     160           0 :         move16();
     161             :     }
     162          28 :     ELSE IF( GE_32( sampleRate, 32000 ) )
     163             :     {
     164          25 :         ret = 4;
     165          25 :         move16();
     166             :     }
     167             :     ELSE
     168             :     {
     169           3 :         ret = 3;
     170           3 :         move16();
     171             :     }
     172             : 
     173          28 :     return ret;
     174             : }
     175             : 
     176           0 : Word32 cross_correlation_self_fx( const Word16 *signal,
     177             :                                   Word16 x,
     178             :                                   Word16 y,
     179             :                                   Word16 corr_len )
     180             : {
     181             :     Word32 sum;
     182             :     Word16 i;
     183             : 
     184           0 :     sum = 0;
     185           0 :     move32();
     186           0 :     FOR( i = 0; i < corr_len; i++ )
     187             :     {
     188           0 :         sum = L_mac0( sum, signal[x + i], signal[y + i] );
     189             :     }
     190             : 
     191           0 :     return sum;
     192             : }
     193             : 
     194           0 : Word8 isSilence_fx( const Word16 *signal, Word16 len, Word16 segments )
     195             : {
     196             :     Word16 i, j, samplesPerSegment;
     197             :     Word32 energy, maxEnergy;
     198             :     Word8 ret;
     199             : 
     200           0 :     assert( len > 0 );
     201           0 :     assert( segments > 0 );
     202             : 
     203             :     /* Every segment is checked using the following formula:
     204             :      *   10 * log10(sum_i(signal[i]*signal[i]))) > -65
     205             :      * For simplification/complexity, this is replaced by:
     206             :      *   20 * log10(sum_i(abs(signal[i]))) > -65
     207             :      */
     208             : 
     209           0 :     ret = 1;
     210           0 :     move16();
     211           0 :     energy = 0;
     212           0 :     move32();
     213           0 :     samplesPerSegment = idiv1616U( len, segments );
     214             :     /* calculate maxEnergy with factor 2 to reduce rounding error */
     215           0 :     maxEnergy = L_mult0( samplesPerSegment, 37 ); /* 37 = 2 * exp10(-65.0 / 20) * 32768 */
     216           0 :     maxEnergy = L_shr( maxEnergy, 1 );
     217           0 :     j = samplesPerSegment;
     218           0 :     move16();
     219             :     /* check all but last segment */
     220           0 :     FOR( i = 0; i < len; i++ )
     221             :     {
     222             :         /* division by 32768 is done later */
     223           0 :         energy = L_add( energy, L_abs( L_deposit_l( signal[i] ) ) );
     224           0 :         IF( EQ_16( i, j ) )
     225             :         {
     226             :             /* check energy of current segment */
     227             :             /*     20 * log10(energy / 32768 / samplesPerSegment) > -65
     228             :              * =>  energy > samplesPerSegment * 10 ^ (-65 / 20) * 32768 */
     229           0 :             IF( GT_32( energy, maxEnergy ) )
     230             :             {
     231           0 :                 ret = 0;
     232           0 :                 move16();
     233           0 :                 BREAK;
     234             :             }
     235           0 :             energy = 0;
     236           0 :             move32();
     237           0 :             j = add( j, samplesPerSegment );
     238             :         }
     239             :     }
     240             :     /* check last segment */
     241           0 :     if ( GT_32( energy, maxEnergy ) )
     242             :     {
     243           0 :         ret = 0;
     244           0 :         move16();
     245             :     }
     246           0 :     return ret;
     247             : }
     248             : 
     249         454 : Word8 isSilence_ivas_fx( const Word16 *signal, Word16 q_sig, Word16 len, Word16 segments )
     250             : {
     251             :     Word16 i, j, samplesPerSegment;
     252             :     Word64 energy, maxEnergy;
     253         454 :     Word16 sig_shift = shl( q_sig, 1 );
     254             : 
     255         454 :     assert( len > 0 );
     256         454 :     assert( segments > 0 );
     257             : 
     258             :     /* Every segment is checked using the following formula:
     259             :      *   10 * log10(sum_i(signal[i] / 32768.0 *signal[i] / 32768.0)) / samples_per_segment) > -65
     260             :      * For simplification/complexity, this is replaced by:
     261             :      *   sum_i(signal[i] / 32768.0 * signal[i] / 32768.0) / samples_per_segment > 10^(-65 / 10)
     262             :      *   sum_i(signal[i] * signal[i]) > 10^(-65 / 10) * 32768.0 * 32768.0 * samples_per_segment
     263             :      */
     264             : 
     265         454 :     energy = 0;
     266         454 :     move64();
     267         454 :     samplesPerSegment = idiv1616U( len, segments );
     268         454 :     maxEnergy = W_shl( W_mac0_16_16( 0, samplesPerSegment, 340 ), sig_shift ); /* 340 = 10^(-65.0 / 10) * 32768 * 32768.0 */
     269         454 :     j = samplesPerSegment;
     270         454 :     move16();
     271             :     /* check all but last segment */
     272         613 :     FOR( i = 0; i < len; i++ )
     273             :     {
     274             :         /* division by 32768 is done later */
     275         613 :         energy = W_mac0_16_16( energy, signal[i], signal[i] );
     276             :         /* check energy of current segment
     277             :          * =>  energy > samplesPerSegment * 10 ^ (-65 / 10) * 32768 * 32768.0*/
     278         613 :         IF( GT_64( energy, maxEnergy ) )
     279             :         {
     280         454 :             return 0;
     281             :         }
     282         159 :         IF( EQ_16( i, j ) )
     283             :         {
     284           0 :             energy = 0;
     285           0 :             move64();
     286           0 :             j = add( j, samplesPerSegment );
     287             :         }
     288             :     }
     289             : 
     290           0 :     return 1;
     291             : }

Generated by: LCOV version 1.14