LCOV - code coverage report
Current view: top level - lib_com - hp50_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ b9bfbe380d1c207f5198ba67a82398b3d313550e Lines: 196 327 59.9 %
Date: 2025-11-14 01:07:58 Functions: 5 6 83.3 %

          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.452 Aug 12, 2021. Version 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #include <stdint.h>
      38             : #include <math.h>
      39             : #include "options.h"
      40             : #include "prot_fx.h"
      41             : #include "wmc_auto.h"
      42             : 
      43             : #define HP20_COEFF_SCALE    ( 2 )
      44             : #define HP20_FX_COEFF_SCALE ( 1 )
      45             : /*
      46             :  * hp20
      47             :  *
      48             :  * Function:
      49             :  *    2nd order high pass filter with nominal cut off frequency at 20 Hz.
      50             :  *
      51             :  * Returns:
      52             :  *    void
      53             :  */
      54             : 
      55    27617100 : static Word32 HP50_Mode2_Mpy_32_16_fix( Word32 a, Word16 b )
      56             : {
      57    27617100 :     Word32 result = Mpy_32_16_1( a, b );
      58             :     /* perform rounding towards lower value for negative results */
      59    27617100 :     if ( result < 0 )
      60    13666982 :         result = L_add( result, 1 );
      61    27617100 :     return result;
      62             : }
      63             : 
      64    18462900 : static Word32 HP50_Mpy_32_32_fix( Word32 a, Word32 b )
      65             : {
      66    18462900 :     Word32 result = Mpy_32_32( a, b );
      67             :     /* perform rounding towards lower value for negative results */
      68    18462900 :     if ( result < 0 )
      69     9229014 :         result = L_add( result, 1 );
      70    18462900 :     return result;
      71             : }
      72             : 
      73             : 
      74       10300 : static void filter_2nd_order(
      75             :     Word16 signal[],
      76             :     const Word16 stride,
      77             :     const Word16 prescale,
      78             :     const Word16 lg,
      79             :     Word32 mem[4],
      80             :     Word32 a1,
      81             :     Word32 a2,
      82             :     Word32 b1,
      83             :     Word32 b2 )
      84             : {
      85             : 
      86             :     Word16 i;
      87             :     Word16 x2, x1;
      88             :     Word32 L_sum, L_y1, L_y2;
      89             : 
      90             :     /*
      91             :      * Saturation: The states of the filter, namely L_y1 and L_y2 shall
      92             :      * never saturate, because that causes error in the filter feedback.
      93             :      * The final output written into signal[] might saturate because of
      94             :      * unavoidable filter overshoot.
      95             :      */
      96             : 
      97             :     /* Execute first 2 iterations with 32-bit x anx y memory values */
      98             :     BASOP_SATURATE_ERROR_ON_EVS
      99       10300 :     L_sum = HP50_Mpy_32_32_fix( b2, mem[2] );                 /* b2*x2 */
     100       10300 :     L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( b1, mem[3] ) ); /* b1*x1 */
     101       10300 :     x2 = shr( signal[0], prescale );
     102       10300 :     L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x2 ) ); /* b2*x0 */
     103       10300 :     L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[0], a2 ) );   /* y2*a2 */
     104       10300 :     L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[1], a1 ) );   /* y1*a1 */
     105             : 
     106       10300 :     L_y2 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
     107             :     BASOP_SATURATE_ERROR_OFF_EVS
     108             :     BASOP_SATURATE_WARNING_OFF_EVS
     109       10300 :     signal[0] = round_fx_sat( L_shl_sat( L_y2, prescale ) );
     110             : 
     111             :     BASOP_SATURATE_WARNING_ON_EVS
     112             : 
     113             :     BASOP_SATURATE_ERROR_ON_EVS
     114       10300 :     L_sum = HP50_Mpy_32_32_fix( b2, mem[3] );                   /* b2*x2 */
     115       10300 :     L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x2 ) ); /* b1*x1 */
     116       10300 :     x1 = shr( signal[stride], prescale );
     117       10300 :     L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x1 ) ); /* b2*x0 */
     118       10300 :     L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( mem[1], a2 ) );   /* y2*a2 */
     119       10300 :     L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a1 ) );     /* y1*a1 */
     120             : 
     121       10300 :     L_y1 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
     122             :     BASOP_SATURATE_ERROR_OFF_EVS
     123             :     BASOP_SATURATE_WARNING_OFF_EVS
     124       10300 :     signal[stride] = round_fx_sat( L_shl_sat( L_y1, prescale ) );
     125             :     BASOP_SATURATE_WARNING_ON_EVS
     126       10300 :     move16();
     127             : 
     128             :     /* New we use a trick and toggle x1/x2 and L_y1/L_y2 to save a few cycles unrolling the loop by 2 */
     129     4608000 :     FOR( i = 2; i < lg; i += 2 )
     130             :     {
     131             :         /* y[i+0] = b2*x[i-2] + b1*x[i-1] + b2*x[i-0] + a2*y[i-2] + a1*y[i-1];  */
     132             :         BASOP_SATURATE_ERROR_ON_EVS
     133     4597700 :         L_sum = HP50_Mode2_Mpy_32_16_fix( b2, x2 );
     134     4597700 :         L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x1 ) );
     135     4597700 :         x2 = shr( signal[i * stride], prescale );
     136     4597700 :         L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x2 ) );
     137     4597700 :         L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a2 ) );
     138     4597700 :         L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y1, a1 ) );
     139             : 
     140     4597700 :         L_y2 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
     141             :         BASOP_SATURATE_ERROR_OFF_EVS
     142             :         BASOP_SATURATE_WARNING_OFF_EVS
     143     4597700 :         signal[i_mult( i, stride )] = round_fx_sat( L_shl_sat( L_y2, prescale ) );
     144             :         BASOP_SATURATE_WARNING_ON_EVS
     145             :         /* y[i+1] = b2*x[i-1] + b1*x[i-0] + b2*x[i+1] + a2*y[i-1] + a1*y[i+0];  */
     146             :         BASOP_SATURATE_ERROR_ON_EVS
     147     4597700 :         L_sum = HP50_Mode2_Mpy_32_16_fix( b2, x1 );
     148     4597700 :         L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b1, x2 ) );
     149     4597700 :         x1 = shr( signal[( i + 1 ) * stride], prescale );
     150     4597700 :         L_sum = L_add( L_sum, HP50_Mode2_Mpy_32_16_fix( b2, x1 ) );
     151     4597700 :         L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y1, a2 ) );
     152     4597700 :         L_sum = L_add( L_sum, HP50_Mpy_32_32_fix( L_y2, a1 ) );
     153             : 
     154     4597700 :         L_y1 = L_shl_sat( L_sum, HP20_COEFF_SCALE );
     155             :         BASOP_SATURATE_ERROR_OFF_EVS
     156             :         BASOP_SATURATE_WARNING_OFF_EVS
     157     4597700 :         signal[i_mult( add( i, 1 ), stride )] = round_fx_sat( L_shl_sat( L_y1, prescale ) );
     158             :         BASOP_SATURATE_WARNING_ON_EVS
     159     4597700 :         move16();
     160             :     }
     161             :     /* update static filter memory from variables */
     162       10300 :     mem[0] = L_y2;
     163       10300 :     move32();
     164       10300 :     mem[1] = L_y1;
     165       10300 :     move32();
     166       10300 :     mem[2] = L_deposit_h( x2 );
     167       10300 :     move32();
     168       10300 :     mem[3] = L_deposit_h( x1 );
     169       10300 :     move32();
     170             : 
     171             : 
     172       10300 :     return;
     173             : }
     174             : 
     175             : 
     176       10300 : void hp20( Word16 signal[],     /* i/o: signal to filter                   any */
     177             :            const Word16 stride, /* i  : stride to be applied accessing signal  */
     178             :            const Word16 lg,     /* i  : length of signal (integer)          Q0 */
     179             :            Word32 mem[5],       /* i/o: static filter memory with this layout: */
     180             :            /*      mem[0]: y[-2] (32-bit)                 */
     181             :            /*      mem[1]; y[-1] (32-bit)                 */
     182             :            /*      mem[2]: x[-2] << 16                    */
     183             :            /*      mem[3]: x[-1] << 16                    */
     184             :            /* Note: mem[0..3] need to be scaled per frame */
     185             :            /*      mem[4]: states scale                   */
     186             :            const Word32 sFreq ) /* i  : input sampling rate                 Q0 */
     187             : {
     188             :     Word32 a1, b1, a2, b2;
     189             :     Word16 prescale, prescaleOld, diff;
     190             : 
     191       10300 :     prescale = getScaleFactor16( signal, lg );
     192       10300 :     prescaleOld = extract_l( mem[4] );
     193       10300 :     diff = norm_l( L_shl_sat( mem[2], prescaleOld ) );
     194       10300 :     if ( mem[2] != 0 )
     195             :     {
     196       10240 :         prescale = s_min( prescale, diff );
     197             :     }
     198       10300 :     diff = norm_l( L_shl_sat( mem[3], prescaleOld ) );
     199       10300 :     if ( mem[3] != 0 )
     200             :     {
     201       10235 :         prescale = s_min( prescale, diff );
     202             :     }
     203             :     /* Take into account the left shift performed into the loop + 1 bit headroom*/
     204       10300 :     prescale = s_max( -12, sub( 1 + HP20_COEFF_SCALE, prescale ) );
     205       10300 :     IF( prescale != prescaleOld )
     206             :     {
     207        4269 :         diff = sub( prescale, prescaleOld );
     208        4269 :         mem[0] = L_shr_sat( mem[0], diff );
     209        4269 :         move32();
     210        4269 :         mem[1] = L_shr_sat( mem[1], diff );
     211        4269 :         move32();
     212        4269 :         mem[2] = L_shr_sat( mem[2], diff );
     213        4269 :         move32();
     214        4269 :         mem[3] = L_shr_sat( mem[3], diff ); //?sat
     215        4269 :         move32();
     216        4269 :         mem[4] = L_deposit_l( prescale );
     217             :     }
     218             : 
     219       10300 :     IF( EQ_32( sFreq, 8000 ) )
     220             :     {
     221             :         /* hp filter 20Hz at 3dB for 8000 Hz input sampling rate
     222             :            [b,a] = butter(2, 20.0/4000.0, 'high');
     223             :            b = [0.988954248067140  -1.977908496134280   0.988954248067140]
     224             :            a = [1.000000000000000  -1.977786483776764   0.978030508491796]*/
     225           0 :         a1 = 1061816033l /* 1.977786483776764 Q29*/;
     226           0 :         move32();
     227           0 :         a2 = -525076131l /*-0.978030508491796 Q29*/;
     228           0 :         move32();
     229           0 :         b1 = -1061881538l /*-1.977908496134280 Q29*/;
     230           0 :         move32();
     231           0 :         b2 = 530940769l /* 0.988954248067140 Q29*/;
     232           0 :         move32();
     233             :     }
     234       10300 :     ELSE IF( EQ_32( sFreq, 16000 ) )
     235             :     {
     236             :         /* hp filter 20Hz at 3dB for 16000KHz sampling rate
     237             :            [b,a] = butter(2, 20.0/8000.0, 'high');
     238             :            b = [0.994461788958195  -1.988923577916390   0.994461788958195]
     239             :            a = [1.000000000000000  -1.988892905899653   0.988954249933127] */
     240           0 :         a1 = 1067778748l /* 1.988892905899653 Q29*/;
     241           0 :         move32();
     242           0 :         a2 = -530940770l /*-0.988954249933127 Q29*/;
     243           0 :         move32();
     244           0 :         b1 = -1067795215l /*-1.988923577916390 Q29*/;
     245           0 :         move32();
     246           0 :         b2 = 533897608l /* 0.994461788958195 Q29*/;
     247           0 :         move32();
     248             :     }
     249       10300 :     ELSE IF( EQ_32( sFreq, 32000 ) )
     250             :     {
     251             :         /* hp filter 20Hz at 3dB for 32000KHz sampling rate
     252             :            [b,a] = butter(2, 20.0/16000.0, 'high');
     253             :            b = [0.997227049904470  -1.994454099808940   0.997227049904470]
     254             :            a = [1.000000000000000  -1.994446410541927   0.994461789075954]*/
     255        2100 :         a1 = 1070760263l /* 1.994446410541927 Q29*/;
     256        2100 :         move32();
     257        2100 :         a2 = -533897608l /*-0.994461789075954 Q29*/;
     258        2100 :         move32();
     259        2100 :         b1 = -1070764392l /*-1.994454099808940 Q29*/;
     260        2100 :         move32();
     261        2100 :         b2 = 535382196l /* 0.997227049904470 Q29*/;
     262        2100 :         move32();
     263             :     }
     264             :     ELSE
     265             :     {
     266        8200 :         assert( sFreq == 48000 );
     267             :         /* hp filter 20Hz at 3dB for 48000KHz sampling rate
     268             :            [b,a] = butter(2, 20.0/24000.0, 'high');
     269             :            b =[0.998150511190452  -1.996301022380904   0.998150511190452]
     270             :            a =[1.000000000000000  -1.996297601769122   0.996304442992686]*/
     271        8200 :         a1 = 1071754114l /* 1.996297601769122 Q29*/;
     272        8200 :         move32();
     273        8200 :         a2 = -534886875l /*-0.996304442992686 Q29*/;
     274        8200 :         move32();
     275        8200 :         b1 = -1071755951l /*-1.996301022380904 Q29*/;
     276        8200 :         move32();
     277        8200 :         b2 = 535877975l /* 0.998150511190452 Q29*/;
     278        8200 :         move32();
     279             :     }
     280             : 
     281             : 
     282       10300 :     filter_2nd_order( signal, stride, prescale, lg,
     283             :                       mem, a1, a2, b1, b2 );
     284             : 
     285       10300 :     return;
     286             : }
     287             : 
     288             : 
     289     3304861 : void hp20_fx_32_opt(
     290             :     Word32 signal_fx[],
     291             :     const Word16 lg,
     292             :     Word32 mem_fx[],
     293             :     const Word32 Fs )
     294             : {
     295             :     Word32 i;
     296             :     Word32 a1_fx, a2_fx, b1_fx, b2_fx;
     297             :     Word16 prescale, prescaleOld, prescale_current_frame, diff;
     298             :     Word32 tmp_mem[4];
     299             : 
     300     3304861 :     prescale = L_norm_arr( signal_fx, lg );
     301     3304861 :     prescale_current_frame = sub( 1 + HP20_FX_COEFF_SCALE, prescale );
     302             : 
     303     3304861 :     prescaleOld = extract_l( mem_fx[4] );
     304             : 
     305     3304861 :     tmp_mem[0] = L_shl_sat( mem_fx[0], prescaleOld );
     306     3304861 :     tmp_mem[1] = L_shl_sat( mem_fx[1], prescaleOld );
     307     3304861 :     tmp_mem[2] = L_shl_sat( mem_fx[2], prescaleOld );
     308     3304861 :     tmp_mem[3] = L_shl_sat( mem_fx[3], prescaleOld );
     309     3304861 :     move32();
     310     3304861 :     move32();
     311     3304861 :     move32();
     312     3304861 :     move32();
     313             : 
     314     3304861 :     diff = L_norm_arr( tmp_mem, 4 );
     315             : 
     316     3304861 :     prescale = s_min( prescale, diff );
     317             : 
     318     3304861 :     prescale = sub( 1 + HP20_FX_COEFF_SCALE, prescale );
     319             : #ifdef FIX_2086_ENABLE_HP20_OPT_FOR_ENC
     320     6547650 :     if ( EQ_16( prescale_current_frame, 1 + HP20_FX_COEFF_SCALE - 31 ) || // signal_fx buffer contains only zeros, so use the mem_fx scale_factor instead
     321     3242789 :          LT_16( prescale_current_frame, prescale ) )                      // To avoid overflow in the subsequent shr() scaling for W_y1, W_y2, x2, and x1 calculations before the for loop.
     322             : #else
     323             :     if ( EQ_16( prescale_current_frame, 1 + HP20_FX_COEFF_SCALE - 31 ) ) // signal_fx buffer contains only zeros, so use the mem_fx scale_factor instead
     324             : #endif
     325             :     {
     326       78967 :         prescale_current_frame = prescale;
     327             :     }
     328             : 
     329     3304861 :     diff = sub( prescale, prescaleOld );
     330     3304861 :     mem_fx[0] = L_shr_sat( mem_fx[0], diff );
     331     3304861 :     mem_fx[1] = L_shr_sat( mem_fx[1], diff );
     332     3304861 :     mem_fx[2] = L_shr_sat( mem_fx[2], diff );
     333     3304861 :     mem_fx[3] = L_shr_sat( mem_fx[3], diff );
     334     3304861 :     move32();
     335     3304861 :     move32();
     336     3304861 :     move32();
     337     3304861 :     move32();
     338     3304861 :     mem_fx[4] = L_deposit_l( prescale_current_frame );
     339     3304861 :     move32();
     340             : 
     341     3304861 :     IF( EQ_32( Fs, 8000 ) )
     342             :     {
     343             :         /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
     344             :            [b,a] = butter(2, 20.0/4000.0, 'high');
     345             :            b = [0.988954248067140  -1.977908496134280   0.988954248067140]
     346             :            a =[1.000000000000000  -1.977786483776764   0.978030508491796]*/
     347           0 :         a1_fx = 2123632067 /* 1.977786483776764 Q30*/;
     348           0 :         a2_fx = -1050152262 /*-0.978030508491796 Q30*/;
     349           0 :         b1_fx = -2123763076 /*-1.977908496134280 Q30*/;
     350           0 :         b2_fx = 1061881538 /* 0.988954248067140 Q30*/;
     351             :     }
     352     3304861 :     ELSE IF( EQ_32( Fs, 16000 ) )
     353             :     {
     354             :         /* hp filter 20Hz at 3dB for 16000KHz sampling rate
     355             :            [b,a] = butter(2, 20.0/8000.0, 'high');
     356             :            b =[ 0.994461788958195  -1.988923577916390   0.994461788958195]
     357             :            a =[1.000000000000000  -1.988892905899653   0.988954249933127] */
     358      210170 :         a1_fx = 2135557497 /* 1.988892905899653 Q30*/;
     359      210170 :         a2_fx = -1061881540 /*-0.988954249933127 Q30*/;
     360      210170 :         b1_fx = -2135590430 /*-1.988923577916390 Q30*/;
     361      210170 :         b2_fx = 1067795215 /* 0.994461788958195 Q30*/;
     362             :     }
     363     3094691 :     ELSE IF( EQ_32( Fs, 32000 ) )
     364             :     {
     365             :         /* hp filter 20Hz at 3dB for 32000KHz sampling rate
     366             :            [b,a] = butter(2, 20.0/16000.0, 'high');
     367             :            b =[0.997227049904470  -1.994454099808940   0.997227049904470]
     368             :            a =[1.000000000000000  -1.994446410541927   0.994461789075954]*/
     369      657188 :         a1_fx = 2141520527 /* 1.994446410541927 Q30*/;
     370      657188 :         a2_fx = -1067795215 /*-0.994461789075954 Q30*/;
     371      657188 :         b1_fx = -2141528783 /*-1.994454099808940 Q30*/;
     372      657188 :         b2_fx = 1070764392 /* 0.997227049904470 Q30*/;
     373             :     }
     374             :     ELSE
     375             :     {
     376             :         /* hp filter 20Hz at 3dB for 48000KHz sampling rate
     377             :            [b,a] = butter(2, 20.0/24000.0, 'high');
     378             :            b =[ 0.998150511190452  -1.996301022380904   0.998150511190452]
     379             :            a =[1.000000000000000  -1.996297601769122   0.996304442992686]*/
     380     2437503 :         a1_fx = 2143508228 /* 1.996297601769122 Q30*/;
     381     2437503 :         a2_fx = -1069773750 /*-0.996304442992686 Q30*/;
     382     2437503 :         b1_fx = -2143511901 /*-1.996301022380904 Q30*/;
     383     2437503 :         b2_fx = 1071755951 /* 0.998150511190452 Q30*/;
     384             :     }
     385     3304861 :     move32();
     386     3304861 :     move32();
     387     3304861 :     move32();
     388     3304861 :     move32();
     389             :     Word64 W_sum, W_y0, W_y1, W_y2;
     390             :     Word32 x0, x1, x2;
     391             : 
     392     3304861 :     W_sum = W_mult0_32_32( b2_fx, mem_fx[2] );                 /* b2*x2 */
     393     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( b1_fx, mem_fx[3] ) ); /* b1*x1 */
     394     3304861 :     x2 = L_shr( signal_fx[0], prescale );
     395     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( b2_fx, x2 ) );        /* b2*x0 */
     396     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( mem_fx[0], a2_fx ) ); /* y2*a2 */
     397     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( mem_fx[1], a1_fx ) ); /* y1*a1 */
     398     3304861 :     W_y2 = W_shl( W_sum, 1 + HP20_FX_COEFF_SCALE );
     399     3304861 :     signal_fx[0] = W_round64_L( W_shl( W_y2, prescale ) );
     400     3304861 :     move32();
     401             : 
     402     3304861 :     W_sum = W_mult0_32_32( b2_fx, mem_fx[3] );          /* b2*x2 */
     403     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( b1_fx, x2 ) ); /* b1*x1 */
     404     3304861 :     x1 = L_shr( signal_fx[1], prescale );
     405     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( b2_fx, x1 ) );                  /* b2*x0 */
     406     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( mem_fx[1], a2_fx ) );           /* y2*a2 */
     407     3304861 :     W_sum = W_add( W_sum, W_mult0_32_32( W_round64_L( W_y2 ), a1_fx ) ); /* y1*a1 */
     408     3304861 :     W_y1 = W_shl( W_sum, 1 + HP20_FX_COEFF_SCALE );
     409     3304861 :     signal_fx[1] = W_round64_L( W_shl( W_y1, prescale ) );
     410     3304861 :     move32();
     411             : 
     412     3304861 :     diff = sub( prescale_current_frame, prescale );
     413     3304861 :     W_y1 = W_shr( W_y1, diff );
     414     3304861 :     W_y2 = W_shr( W_y2, diff );
     415     3304861 :     x2 = L_shr( x2, diff );
     416     3304861 :     x1 = L_shr( x1, diff );
     417             : 
     418  2824552739 :     FOR( i = 2; i < lg; i++ )
     419             :     {
     420  2821247878 :         W_sum = W_mult0_32_32( b2_fx, x2 );                 /* b2*x2 */
     421  2821247878 :         W_sum = W_add( W_sum, W_mult0_32_32( b1_fx, x1 ) ); /* b1*x1 */
     422  2821247878 :         x0 = L_shr( signal_fx[i], prescale_current_frame );
     423  2821247878 :         W_sum = W_add( W_sum, W_mult0_32_32( b2_fx, x0 ) );                  /* b2*x0 */
     424  2821247878 :         W_sum = W_add( W_sum, W_mult0_32_32( W_round64_L( W_y2 ), a2_fx ) ); /* y2*a2 */
     425  2821247878 :         W_sum = W_add( W_sum, W_mult0_32_32( W_round64_L( W_y1 ), a1_fx ) ); /* y1*a1 */
     426  2821247878 :         W_y0 = W_shl( W_sum, 1 + HP20_FX_COEFF_SCALE );
     427             : 
     428  2821247878 :         signal_fx[i] = W_round64_L( W_shl( W_y0, prescale_current_frame ) );
     429  2821247878 :         move32();
     430             : 
     431  2821247878 :         x2 = x1;
     432  2821247878 :         x1 = x0;
     433  2821247878 :         W_y2 = W_y1;
     434  2821247878 :         W_y1 = W_y0;
     435             : 
     436  2821247878 :         move32();
     437  2821247878 :         move32();
     438  2821247878 :         move64();
     439  2821247878 :         move64();
     440             :     }
     441             : 
     442     3304861 :     mem_fx[0] = W_round64_L( W_y2 );
     443     3304861 :     mem_fx[1] = W_round64_L( W_y1 );
     444     3304861 :     mem_fx[2] = x2;
     445     3304861 :     mem_fx[3] = x1;
     446             : 
     447     3304861 :     move32();
     448     3304861 :     move32();
     449     3304861 :     move32();
     450     3304861 :     move32();
     451             : 
     452     3304861 :     return;
     453             : }
     454             : 
     455             : 
     456           0 : void hp20_fx_32(
     457             :     Word32 signal_fx[],
     458             :     const Word16 lg,
     459             :     Word32 mem_fx[],
     460             :     const Word32 Fs )
     461             : {
     462             :     Word16 i;
     463             :     Word32 a1_fx, a2_fx, b1_fx, b2_fx;
     464             :     Word16 Qx0, Qx1, Qx2, Qy1, Qprev_y1, Qy2, Qprev_y2, Qmin;
     465             :     Word64 x0_fx64, x1_fx64, x2_fx64, y0_fx64, y1_fx64, y2_fx64, R1, R2, R3, R4, R5;
     466             : 
     467           0 :     IF( EQ_32( Fs, 8000 ) )
     468             :     {
     469             :         /* hp filter 20Hz at 3dB for 8000KHz input sampling rate
     470             :            [b,a] = butter(2, 20.0/4000.0, 'high');
     471             :            b = [0.988954248067140  -1.977908496134280   0.988954248067140]
     472             :            a =[1.000000000000000  -1.977786483776764   0.978030508491796]*/
     473           0 :         a1_fx = 1061816033l /* 1.977786483776764 Q29*/;
     474           0 :         a2_fx = -525076131l /*-0.978030508491796 Q29*/;
     475           0 :         b1_fx = -1061881538l /*-1.977908496134280 Q29*/;
     476           0 :         b2_fx = 530940769l /* 0.988954248067140 Q29*/;
     477             :     }
     478           0 :     ELSE IF( EQ_32( Fs, 16000 ) )
     479             :     {
     480             :         /* hp filter 20Hz at 3dB for 16000KHz sampling rate
     481             :            [b,a] = butter(2, 20.0/8000.0, 'high');
     482             :            b =[ 0.994461788958195  -1.988923577916390   0.994461788958195]
     483             :            a =[1.000000000000000  -1.988892905899653   0.988954249933127] */
     484           0 :         a1_fx = 1067778748l /* 1.988892905899653 Q29*/;
     485           0 :         a2_fx = -530940770l /*-0.988954249933127 Q29*/;
     486           0 :         b1_fx = -1067795215l /*-1.988923577916390 Q29*/;
     487           0 :         b2_fx = 533897608l /* 0.994461788958195 Q29*/;
     488             :     }
     489           0 :     ELSE IF( EQ_32( Fs, 32000 ) )
     490             :     {
     491             :         /* hp filter 20Hz at 3dB for 32000KHz sampling rate
     492             :            [b,a] = butter(2, 20.0/16000.0, 'high');
     493             :            b =[0.997227049904470  -1.994454099808940   0.997227049904470]
     494             :            a =[1.000000000000000  -1.994446410541927   0.994461789075954]*/
     495           0 :         a1_fx = 1070760263l /* 1.994446410541927 Q29*/;
     496           0 :         a2_fx = -533897608l /*-0.994461789075954 Q29*/;
     497           0 :         b1_fx = -1070764392l /*-1.994454099808940 Q29*/;
     498           0 :         b2_fx = 535382196l /* 0.997227049904470 Q29*/;
     499             :     }
     500             :     ELSE
     501             :     {
     502             :         /* hp filter 20Hz at 3dB for 48000KHz sampling rate
     503             :            [b,a] = butter(2, 20.0/24000.0, 'high');
     504             :            b =[ 0.998150511190452  -1.996301022380904   0.998150511190452]
     505             :            a =[1.000000000000000  -1.996297601769122   0.996304442992686]*/
     506           0 :         a1_fx = 1071754114l /* 1.996297601769122 Q29*/;
     507           0 :         a2_fx = -534886875l /*-0.996304442992686 Q29*/;
     508           0 :         b1_fx = -1071755951l /*-1.996301022380904 Q29*/;
     509           0 :         b2_fx = 535877975l /* 0.998150511190452 Q29*/;
     510             :     }
     511           0 :     move32();
     512           0 :     move32();
     513           0 :     move32();
     514           0 :     move32();
     515             : 
     516           0 :     Qprev_y1 = extract_l( mem_fx[4] );
     517           0 :     Qprev_y2 = extract_l( mem_fx[5] );
     518           0 :     y1_fx64 = W_deposit32_l( mem_fx[0] );
     519           0 :     y2_fx64 = W_deposit32_l( mem_fx[1] );
     520           0 :     x0_fx64 = W_deposit32_l( mem_fx[2] );
     521           0 :     x1_fx64 = W_deposit32_l( mem_fx[3] );
     522             : 
     523           0 :     FOR( i = 0; i < lg; i++ )
     524             :     {
     525           0 :         x2_fx64 = x1_fx64;
     526           0 :         move64();
     527           0 :         x1_fx64 = x0_fx64;
     528           0 :         move64();
     529           0 :         x0_fx64 = W_deposit32_l( signal_fx[i] );
     530             : 
     531           0 :         Qy1 = W_norm( y1_fx64 );
     532           0 :         if ( y1_fx64 == 0 )
     533             :         {
     534           0 :             Qy1 = 62;
     535           0 :             move16();
     536             :         }
     537           0 :         Qy1 = sub( Qy1, 34 );
     538           0 :         R1 = W_mult0_32_32( W_shl_sat_l( y1_fx64, Qy1 ), a1_fx );
     539           0 :         Qy1 = add( Qy1, Qprev_y1 );
     540             : 
     541           0 :         Qy2 = W_norm( y2_fx64 );
     542           0 :         if ( y2_fx64 == 0 )
     543             :         {
     544           0 :             Qy2 = 62;
     545           0 :             move16();
     546             :         }
     547           0 :         Qy2 = sub( Qy2, 34 );
     548           0 :         R2 = W_mult0_32_32( W_shl_sat_l( y2_fx64, Qy2 ), a2_fx );
     549           0 :         Qy2 = add( Qy2, Qprev_y2 );
     550             : 
     551           0 :         Qx0 = W_norm( x0_fx64 );
     552           0 :         if ( x0_fx64 == 0 )
     553             :         {
     554           0 :             Qx0 = 62;
     555           0 :             move16();
     556             :         }
     557           0 :         Qx0 = sub( Qx0, 34 );
     558           0 :         R3 = W_mult0_32_32( W_shl_sat_l( x0_fx64, Qx0 ), b2_fx );
     559             : 
     560           0 :         Qx1 = W_norm( x1_fx64 );
     561           0 :         if ( x1_fx64 == 0 )
     562             :         {
     563           0 :             Qx1 = 62;
     564           0 :             move16();
     565             :         }
     566           0 :         Qx1 = sub( Qx1, 34 );
     567           0 :         R4 = W_mult0_32_32( W_shl_sat_l( x1_fx64, Qx1 ), b1_fx );
     568             : 
     569           0 :         Qx2 = W_norm( x2_fx64 );
     570           0 :         if ( x2_fx64 == 0 )
     571             :         {
     572           0 :             Qx2 = 62;
     573           0 :             move16();
     574             :         }
     575           0 :         Qx2 = sub( Qx2, 34 );
     576           0 :         R5 = W_mult0_32_32( W_shl_sat_l( x2_fx64, Qx2 ), b2_fx );
     577             : 
     578           0 :         Qmin = s_min( Qy1, Qy2 );
     579             : 
     580           0 :         y0_fx64 = W_add( W_shr( R1, sub( Qy1, Qmin ) ), W_shr( R2, sub( Qy2, Qmin ) ) );
     581             : 
     582           0 :         Qmin = s_min( Qmin, Qx0 );
     583           0 :         Qmin = s_min( Qmin, Qx1 );
     584           0 :         Qmin = s_min( Qmin, Qx2 );
     585             : 
     586           0 :         y0_fx64 = W_add( W_shr( y0_fx64, sub( s_min( Qy1, Qy2 ), Qmin ) ), W_add( W_shr( R3, sub( Qx0, Qmin ) ), W_add( W_shr( R4, sub( Qx1, Qmin ) ), W_shr( R5, sub( Qx2, Qmin ) ) ) ) );
     587             : 
     588           0 :         y0_fx64 = W_shr( y0_fx64, 29 );
     589             : 
     590           0 :         signal_fx[i] = W_extract_l( W_shr( y0_fx64, Qmin ) );
     591           0 :         move32();
     592           0 :         IF( signal_fx[i] < 0 )
     593             :         {
     594           0 :             signal_fx[i] = L_add( signal_fx[i], 1 );
     595           0 :             move32();
     596             :         }
     597             : 
     598           0 :         y2_fx64 = y1_fx64;
     599           0 :         y1_fx64 = y0_fx64;
     600           0 :         Qprev_y2 = Qprev_y1;
     601           0 :         Qprev_y1 = Qmin;
     602           0 :         move64();
     603           0 :         move64();
     604           0 :         move16();
     605           0 :         move16();
     606             :     }
     607             : 
     608           0 :     Qy1 = W_norm( y1_fx64 );
     609           0 :     test();
     610           0 :     IF( y1_fx64 != 0 && LT_16( Qy1, 32 ) )
     611             :     {
     612           0 :         y1_fx64 = W_shr( y1_fx64, sub( 32, Qy1 ) );
     613           0 :         Qprev_y1 = sub( Qprev_y1, sub( 32, Qy1 ) );
     614             :     }
     615             : 
     616           0 :     Qy2 = W_norm( y2_fx64 );
     617           0 :     test();
     618           0 :     IF( y2_fx64 != 0 && LT_16( Qy2, 32 ) )
     619             :     {
     620           0 :         y2_fx64 = W_shr( y2_fx64, sub( 32, Qy2 ) );
     621           0 :         Qprev_y2 = sub( Qprev_y2, sub( 32, Qy2 ) );
     622             :     }
     623             : 
     624           0 :     mem_fx[0] = W_extract_l( y1_fx64 );
     625           0 :     mem_fx[1] = W_extract_l( y2_fx64 );
     626           0 :     mem_fx[2] = W_extract_l( x0_fx64 );
     627           0 :     mem_fx[3] = W_extract_l( x1_fx64 );
     628           0 :     mem_fx[4] = Qprev_y1;
     629           0 :     mem_fx[5] = Qprev_y2;
     630             : 
     631           0 :     move32();
     632           0 :     move32();
     633           0 :     move32();
     634           0 :     move32();
     635           0 :     move32();
     636           0 :     move32();
     637             : 
     638           0 :     return;
     639             : }

Generated by: LCOV version 1.14