LCOV - code coverage report
Current view: top level - lib_enc - ivas_agc_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 377 435 86.7 %
Date: 2025-05-03 01:55:50 Functions: 8 8 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             : #include <stdint.h>
      35             : #include <math.h>
      36             : #include <assert.h>
      37             : #include "options.h"
      38             : #include "prot_fx.h"
      39             : #include "rom_com.h"
      40             : #include "wmc_auto.h"
      41             : #include "ivas_prot_fx.h"
      42             : #include "basop_util.h"
      43             : 
      44             : /*------------------------------------------------------------------------------------------*
      45             :  * Local constants
      46             :  *------------------------------------------------------------------------------------------*/
      47             : 
      48             : #define AGC_MIN_DELTA_FX              1 // q31
      49             : #define TWO_IN_Q29                    1073741824
      50             : #define ONE_MINUS_M_DELTA_PROD_FLT_FC 1073741824 // Q15
      51             : 
      52             : static Word16 ceil_fx( Word16 inp, Word16 Q );
      53             : static Word32 pow32_fx( Word16 inp, Word16 indx );
      54             : static Word16 BASOP_Util_Cmp_Mant32Exp_sat( Word32 a_m, Word16 a_e, Word32 b_m, Word16 b_e );
      55         307 : static Word16 ceil_fx( Word16 inp, Word16 Q )
      56             : {
      57             :     Word16 ret;
      58             :     Word32 ret_32;
      59         307 :     IF( inp > 0 )
      60             :     {
      61         307 :         IF( EQ_16( Q, 15 ) )
      62             :         {
      63         282 :             return 1;
      64             :         }
      65             :         ELSE
      66             :         {
      67          25 :             ret_32 = L_add( inp, sub( shl( 1, Q ), 1 ) ); //(inp+(pow(2,q)-1))/pow(2,q)//
      68          25 :             ret_32 = L_shr( ret_32, Q );
      69          25 :             return extract_l( ret_32 );
      70             :         }
      71             :     }
      72             :     ELSE
      73             :     {
      74           0 :         ret = negate( shr( abs_s( inp ), Q ) );
      75             :     }
      76             : 
      77           0 :     return ret;
      78             : }
      79             : 
      80   109837500 : Word16 BASOP_Util_Cmp_Mant32Exp_sat /*!< o: flag: result of comparison */
      81             :     /*      0, if a == b               */
      82             :     /*      1, if a > b                */
      83             :     /*     -1, if a < b                */
      84             :     ( Word32 a_m,  /*!< i: Mantissa of 1st operand a  */
      85             :       Word16 a_e,  /*!< i: Exponent of 1st operand a  */
      86             :       Word32 b_m,  /*!< i: Mantissa of 2nd operand b  */
      87             :       Word16 b_e ) /*!< i: Exponent of 2nd operand b  */
      88             : 
      89             : {
      90             :     Word32 diff_m;
      91             :     Word16 diff_e, shift, result;
      92             : 
      93             : 
      94             :     /*
      95             :        This function compares two input parameters, both represented by a 32-bit mantissa and a 16-bit exponent.
      96             :        If both values are identical, 0 is returned.
      97             :        If a is greater b, 1 is returned.
      98             :        If a is less than b, -1 is returned.
      99             :     */
     100             : 
     101             :     /* Check, if both mantissa and exponents are identical, when normalized: return 0 */
     102   109837500 :     shift = norm_l( a_m );
     103   109837500 :     IF( shift )
     104   109737354 :     a_m = L_shl( a_m, shift );
     105   109837500 :     IF( shift )
     106   109737354 :     a_e = sub( a_e, shift );
     107             : 
     108   109837500 :     shift = norm_l( b_m );
     109   109837500 :     IF( shift )
     110    79280545 :     b_m = L_shl( b_m, shift );
     111   109837500 :     IF( shift )
     112    79280545 :     b_e = sub( b_e, shift );
     113             : 
     114             :     /* align exponent, if any mantissa is zero */
     115   109837500 :     if ( !a_m )
     116             :     {
     117       89984 :         a_e = b_e;
     118       89984 :         move16();
     119             :     }
     120   109837500 :     if ( !b_m )
     121             :     {
     122       69509 :         b_e = a_e;
     123       69509 :         move16();
     124             :     }
     125             : 
     126             :     BASOP_SATURATE_WARNING_OFF_EVS
     127   109837500 :     diff_m = L_sub_sat( a_m, b_m );
     128             :     BASOP_SATURATE_WARNING_ON_EVS
     129   109837500 :     diff_e = sub( a_e, b_e );
     130             : 
     131   109837500 :     test();
     132   109837500 :     IF( diff_m == 0 && diff_e == 0 )
     133             :     {
     134       48438 :         return 0;
     135             :     }
     136             : 
     137             :     /* Check sign, exponent and mantissa to identify, whether a is greater b or not */
     138   109789062 :     result = -1; // sub( 0, 1 );
     139   109789062 :     move16();
     140             : 
     141   109789062 :     IF( a_m >= 0 )
     142             :     {
     143             :         /* a is positive */
     144    64238519 :         if ( b_m < 0 )
     145             :         {
     146           0 :             result = 1;
     147           0 :             move16();
     148             :         }
     149             : 
     150    64238519 :         test();
     151    64238519 :         test();
     152    64238519 :         test();
     153    64238519 :         if ( ( b_m >= 0 ) && ( ( diff_e > 0 ) || ( diff_e == 0 && diff_m > 0 ) ) )
     154             :         {
     155     1046519 :             result = 1;
     156     1046519 :             move16();
     157             :         }
     158             :     }
     159             :     ELSE
     160             :     {
     161             :         /* a is negative */
     162    45550543 :         test();
     163    45550543 :         test();
     164    45550543 :         test();
     165    45550543 :         if ( ( b_m < 0 ) && ( ( diff_e < 0 ) || ( diff_e == 0 && diff_m > 0 ) ) )
     166             :         {
     167         132 :             result = 1;
     168         132 :             move16();
     169             :         }
     170             :     }
     171   109789062 :     return result;
     172             : }
     173             : 
     174     3466817 : Word32 pow32_fx( Word16 inp, Word16 indx )
     175             : {
     176             :     Word32 temp_1, temp_2;
     177     3466817 :     IF( EQ_16( indx, 1 ) )
     178             :     {
     179      386178 :         return L_deposit_h( inp );
     180             :     }
     181     3080639 :     ELSE IF( indx == 0 )
     182             :     {
     183     3080639 :         return ONE_IN_Q31;
     184             :     }
     185             :     ELSE
     186             :     {
     187           0 :         temp_1 = L_mult( inp, inp ); // Q31
     188           0 :         temp_2 = temp_1;
     189           0 :         move32();
     190           0 :         FOR( Word16 i = 0; i < ( indx >> 1 ); i++ )
     191             :         {
     192           0 :             temp_1 = Mpy_32_32( temp_1, temp_1 ); // Q31
     193             :         }
     194           0 :         IF( s_and( indx, 1 ) )
     195             :         {
     196           0 :             temp_1 = Mpy_32_32( temp_2, temp_1 ); // Q31
     197             :         }
     198             :     }
     199           0 :     return temp_1;
     200             : }
     201             : 
     202             : 
     203             : /*-----------------------------------------------------------------------------------------*
     204             :  * Function ivas_agc_enc_get_flag()
     205             :  *
     206             :  * This function determines if AGC is enabled or disabled.
     207             :  *-----------------------------------------------------------------------------------------*/
     208             : 
     209             : /*! r: AGC enable flag */
     210        3419 : Word16 ivas_agc_enc_get_flag(
     211             :     const Word16 nchan_transport /* i  : number of transport channels            Q0*/
     212             : )
     213             : {
     214             :     Word16 agc_flag;
     215             : 
     216             :     /* AGC is enabled only if there is one transport channel. */
     217        3419 :     agc_flag = 0;
     218        3419 :     move16();
     219        3419 :     if ( EQ_16( nchan_transport, 1 ) )
     220             :     {
     221        1217 :         agc_flag = 1;
     222        1217 :         move16();
     223             :     }
     224             : 
     225        3419 :     return agc_flag;
     226             : }
     227             : 
     228             : 
     229             : /*-----------------------------------------------------------------------------------------*
     230             :  * Function ivas_agc_enc_init()
     231             :  *
     232             :  * AGC encoder initialization
     233             :  *-----------------------------------------------------------------------------------------*/
     234             : 
     235         540 : static void ivas_agc_enc_init_fx(
     236             :     ivas_agc_enc_state_t *hAgcEnc,
     237             :     const Word16 input_frame, /* Q0 */
     238             :     const Word16 nchan_inp,   /* Q0 */
     239             :     const Word16 delay        /* Q0 */
     240             : )
     241             : {
     242             :     Word16 i;
     243         540 :     ivas_agc_enc_chan_state_t *ptrG = hAgcEnc->gain_state;
     244         540 :     ivas_agc_chan_data_t *ptr = hAgcEnc->gain_data;
     245             : 
     246         540 :     hAgcEnc->agc_com.in_delay = delay; /* Q0 */
     247         540 :     move16();
     248         540 :     hAgcEnc->agc_com.num_coeff = FOA_CHANNELS;
     249         540 :     move16();
     250             : 
     251         540 :     ivas_agc_calcGainParams_fx( &hAgcEnc->agc_com.absEmin, &hAgcEnc->agc_com.betaE, &hAgcEnc->agc_com.maxAttExp, hAgcEnc->agc_com.num_coeff );
     252             : 
     253         540 :     ivas_agc_initWindowFunc_fx( hAgcEnc->agc_com.winFunc_fx, sub( input_frame, hAgcEnc->agc_com.in_delay ) );
     254             : 
     255         540 :     hAgcEnc->minDelta_fx = AGC_MIN_DELTA_FX;
     256         540 :     move32();
     257         540 :     hAgcEnc->smFact_fx = 214748368; // q31
     258         540 :     move32();
     259             : 
     260        2700 :     FOR( i = 0; i < nchan_inp; i++ )
     261             :     {
     262             :         /* gain_state */
     263        2160 :         ptrG->lastExp = 0;
     264        2160 :         move16();
     265        2160 :         ptrG->prevExp = 0;
     266        2160 :         move16();
     267        2160 :         ptrG->lastGain_fx = ONE_IN_Q31;
     268        2160 :         move32();
     269        2160 :         ptrG->q_lastGain_fx = Q31;
     270        2160 :         move16();
     271        2160 :         ptrG->lastMaxAbs_fx = 0;
     272        2160 :         move32();
     273        2160 :         ptrG->q_lastMaxAbs_fx = Q31;
     274        2160 :         move16();
     275        2160 :         ptrG->gainExpVal = 0;
     276        2160 :         move16();
     277        2160 :         ptrG->MaxAbsVal_del_fx = 0;
     278        2160 :         move32();
     279        2160 :         ptrG->q_MaxAbsVal_del_fx = Q31;
     280        2160 :         move16();
     281        2160 :         ptrG->MaxAbsValIdx_del = 0;
     282        2160 :         move32();
     283        2160 :         ptrG++;
     284             : 
     285             :         /* gain_data */
     286        2160 :         ptr->absGainExp = hAgcEnc->agc_com.absEmin; /* Q0 */
     287        2160 :         move16();
     288        2160 :         ptr->absGainExpCurr = hAgcEnc->agc_com.absEmin; /* Q0 */
     289        2160 :         move16();
     290        2160 :         ptr++;
     291             :     }
     292             : 
     293         540 :     return;
     294             : }
     295             : 
     296             : 
     297             : /*-------------------------------------------------------------------------
     298             :  * ivas_spar_agc_enc_open()
     299             :  *
     300             :  * Allocate and initialize SPAR AGC encoder handle
     301             :  *------------------------------------------------------------------------*/
     302             : 
     303         540 : ivas_error ivas_spar_agc_enc_open_fx(
     304             :     ivas_agc_enc_state_t **hAgcEnc, /* i/o: SPAR AGC encoder handle     */
     305             :     const Word32 input_Fs,          /* i  : input sampling rate         Q0*/
     306             :     const Word16 nchan_inp          /* i  : number of input channels    Q0*/
     307             : )
     308             : {
     309             :     ivas_agc_enc_state_t *hAgc;
     310             :     Word16 input_frame, delay;
     311             : 
     312         540 :     IF( ( hAgc = (ivas_agc_enc_state_t *) malloc( sizeof( ivas_agc_enc_state_t ) ) ) == NULL )
     313             :     {
     314           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
     315             :     }
     316             : 
     317         540 :     input_frame = extract_l( Mpy_32_16_1( input_Fs, INV_FRAME_PER_SEC_Q15 ) ); /* Q0 */
     318         540 :     delay = NS2SA_FX2( input_Fs, ( IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ) );
     319             : 
     320         540 :     IF( ( hAgc->agc_com.winFunc_fx = (Word16 *) malloc( sizeof( Word16 ) * ( input_frame - delay ) ) ) == NULL )
     321             :     {
     322           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
     323             :     }
     324             : 
     325         540 :     IF( ( hAgc->gain_state = (ivas_agc_enc_chan_state_t *) malloc( sizeof( ivas_agc_enc_chan_state_t ) * nchan_inp ) ) == NULL )
     326             :     {
     327           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
     328             :     }
     329             : 
     330         540 :     IF( ( hAgc->gain_data = (ivas_agc_chan_data_t *) malloc( sizeof( ivas_agc_chan_data_t ) * nchan_inp ) ) == NULL )
     331             :     {
     332           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
     333             :     }
     334             : 
     335         540 :     ivas_agc_enc_init_fx( hAgc, input_frame, nchan_inp, delay );
     336             : 
     337         540 :     *hAgcEnc = hAgc;
     338             : 
     339         540 :     return IVAS_ERR_OK;
     340             : }
     341             : 
     342             : 
     343             : /*-------------------------------------------------------------------------
     344             :  * ivas_spar_agc_enc_close()
     345             :  *
     346             :  * Deallocate SPAR AGC encoder handle
     347             :  *------------------------------------------------------------------------*/
     348             : 
     349        1558 : void ivas_spar_agc_enc_close_fx(
     350             :     ivas_agc_enc_state_t **hAgcEnc /* i/o: SPAR AGC encoder handle      */
     351             : )
     352             : {
     353             :     ivas_agc_enc_state_t *hAgc;
     354             : 
     355        1558 :     test();
     356        1558 :     IF( hAgcEnc == NULL || *hAgcEnc == NULL )
     357             :     {
     358        1018 :         return;
     359             :     }
     360             : 
     361         540 :     hAgc = *hAgcEnc;
     362             : 
     363         540 :     free( hAgc->agc_com.winFunc_fx );
     364         540 :     hAgc->agc_com.winFunc_fx = NULL;
     365             : 
     366         540 :     free( hAgc->gain_state );
     367         540 :     hAgc->gain_state = NULL;
     368             : 
     369         540 :     free( hAgc->gain_data );
     370         540 :     hAgc->gain_data = NULL;
     371             : 
     372         540 :     free( *hAgcEnc );
     373         540 :     *hAgcEnc = NULL;
     374             : 
     375         540 :     return;
     376             : }
     377             : 
     378             : 
     379             : /*-----------------------------------------------------------------------------------------*
     380             :  * Function ivas_agc_enc_process()
     381             :  *
     382             :  * AGC encoder
     383             :  *-----------------------------------------------------------------------------------------*/
     384             : 
     385       42018 : void ivas_agc_enc_process_fx(
     386             :     ivas_agc_enc_state_t *hAgcEnc,              /* i/o: AGC encoder handle       */
     387             :     BSTR_ENC_HANDLE hMetaData,                  /* i/o: MetaData handle          */
     388             :     Word32 **ppPcm_in,                          /* i  : input audio channels     q_ppPcm*/
     389             :     Word32 **ppPcm_out,                         /* o  : output audio channels    q_ppPcm*/
     390             :     const Word16 n_channels,                    /* i  : number of channels       Q0*/
     391             :     const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i  : configuration structure  */
     392             :     Word16 *q_ppPcm )
     393             : {
     394             :     Word16 i, j, idx, input_frame, offset;
     395             :     Word16 per_ch_bit[FOA_CHANNELS], AGC_flag;
     396       42018 :     Word16 extendedExpVal = FALSE;
     397       42018 :     move16();
     398             :     Word16 isGainAdjusted;
     399             :     Word16 q_predMaxAbsVal, q_MaxAbsVal;
     400       42018 :     ivas_agc_enc_state_t *pState = hAgcEnc;
     401             : 
     402       42018 :     input_frame = extract_l( Mpy_32_16_1( hEncoderConfig->input_Fs, INV_FRAME_PER_SEC_Q15 ) ); /* Q0 */
     403       42018 :     offset = sub( input_frame, pState->agc_com.in_delay );                                     /* Q0 */
     404             : 
     405       42018 :     AGC_flag = 0;
     406       42018 :     move16();
     407             : 
     408       84036 :     FOR( i = 0; i < n_channels; i++ )
     409             :     {
     410       42018 :         Word16 q_pcm = q_ppPcm[i];
     411       42018 :         move16();
     412             :         Word32 sampleAbsVal;
     413       42018 :         Word16 isClipped = FALSE;
     414       42018 :         move16();
     415       42018 :         Word16 clippedIdx = 0;
     416       42018 :         move16();
     417       42018 :         Word16 MaxAbsValIdx = 0;
     418       42018 :         move16();
     419             :         Word16 q_sampleAbsVal, gain_norm;
     420       42018 :         Word32 MaxAbsVal = pState->gain_state[i].MaxAbsVal_del_fx;
     421       42018 :         move32();
     422       42018 :         Word32 predMaxAbsVal = L_abs( ppPcm_in[i][offset] );
     423       42018 :         q_predMaxAbsVal = q_ppPcm[i];
     424       42018 :         move16();
     425       42018 :         q_MaxAbsVal = pState->gain_state[i].q_MaxAbsVal_del_fx;
     426       42018 :         move16();
     427             : 
     428       42018 :         IF( LT_16( pState->gain_state[i].q_lastGain_fx, Q31 ) )
     429             :         {
     430         282 :             gain_norm = norm_l( L_abs( pState->gain_state[i].lastGain_fx ) );
     431         282 :             pState->gain_state[i].lastGain_fx = L_shl( pState->gain_state[i].lastGain_fx, gain_norm ); /* pState->gain_state[i].q_lastGain_fx + gain_norm */
     432         282 :             move32();
     433         282 :             pState->gain_state[i].q_lastGain_fx = add( pState->gain_state[i].q_lastGain_fx, gain_norm );
     434         282 :             move16();
     435             :         }
     436    30601058 :         FOR( j = 0; j < input_frame; j++ )
     437             :         {
     438    30559040 :             sampleAbsVal = L_abs( ppPcm_in[i][j] ); /* q_ppPcm */
     439    30559040 :             q_sampleAbsVal = q_ppPcm[i];
     440    30559040 :             move16();
     441             : 
     442    30559040 :             IF( EQ_16( BASOP_Util_Cmp_Mant32Exp_sat( sampleAbsVal, sub( Q31, q_sampleAbsVal ), MaxAbsVal, sub( Q31, q_MaxAbsVal ) ), 1 ) )
     443             :             {
     444      239841 :                 MaxAbsVal = sampleAbsVal; /* q_sampleAbsVal */
     445      239841 :                 move32();
     446      239841 :                 q_MaxAbsVal = q_sampleAbsVal;
     447      239841 :                 move16();
     448      239841 :                 MaxAbsValIdx = j;
     449      239841 :                 move16();
     450             :             }
     451             : 
     452    30559040 :             IF( GT_16( j, offset ) )
     453             :             {
     454    18293406 :                 IF( EQ_16( BASOP_Util_Cmp_Mant32Exp_sat( sampleAbsVal, sub( Q31, q_sampleAbsVal ), predMaxAbsVal, sub( Q31, q_predMaxAbsVal ) ), 1 ) )
     455             :                 {
     456      802497 :                     predMaxAbsVal = sampleAbsVal; /* q_sampleAbsVal */
     457      802497 :                     move32();
     458      802497 :                     q_predMaxAbsVal = q_sampleAbsVal;
     459      802497 :                     move16();
     460             :                 }
     461             :             }
     462             : 
     463    30559040 :             ppPcm_out[i][j] = Mpy_32_32( ppPcm_in[i][j], pState->gain_state[i].lastGain_fx ); /* q_ppPcm + State->gain_state[i].q_lastGain_fx - 31 */
     464    30559040 :             move32();
     465    30559040 :             q_pcm = add( q_ppPcm[i], sub( pState->gain_state[i].q_lastGain_fx, Q31 ) );
     466    30559040 :             IF( !isClipped )
     467             :             {
     468    30482657 :                 Word16 comp_flag_1 = 0;
     469    30482657 :                 move16();
     470    30482657 :                 comp_flag_1 = BASOP_Util_Cmp_Mant32Exp_sat( ppPcm_in[i][j], sub( Q31, q_pcm ), ONE_MINUS_M_DELTA_PROD_FLT_FC, Q16 );
     471    30482657 :                 IF( EQ_16( comp_flag_1, 1 ) )
     472             :                 {
     473         175 :                     comp_flag_1 = 1;
     474         175 :                     move16();
     475             :                 }
     476             :                 ELSE
     477             :                 {
     478    30482482 :                     comp_flag_1 = 0;
     479    30482482 :                     move16();
     480             :                 }
     481    30482657 :                 Word16 comp_flag_2 = BASOP_Util_Cmp_Mant32Exp_sat( MIN16B_FLT_FX_IN_Q15, Q16, ppPcm_in[i][j], sub( Q31, q_pcm ) );
     482    30482657 :                 IF( EQ_16( comp_flag_2, 1 ) )
     483             :                 {
     484         132 :                     comp_flag_2 = 1;
     485         132 :                     move16();
     486             :                 }
     487             :                 ELSE
     488             :                 {
     489    30482525 :                     comp_flag_2 = 0;
     490    30482525 :                     move16();
     491             :                 }
     492    30482657 :                 test();
     493    30482657 :                 IF( ( comp_flag_1 ) || ( comp_flag_2 ) )
     494             :                 {
     495         307 :                     clippedIdx = j;
     496         307 :                     move16();
     497         307 :                     isClipped = TRUE;
     498         307 :                     move16();
     499             :                 }
     500             :             }
     501             :         }
     502             : 
     503       42018 :         pState->gain_state[i].MaxAbsVal_del_fx = predMaxAbsVal; /* q_predMaxAbsVal */
     504       42018 :         move32();
     505       42018 :         pState->gain_state[i].q_MaxAbsVal_del_fx = q_predMaxAbsVal;
     506       42018 :         move16();
     507             : 
     508       42018 :         isGainAdjusted = FALSE;
     509       42018 :         move16();
     510       42018 :         IF( !isClipped )
     511             :         {
     512             :             // CHECK THIS PART AGAIN MaxAbsVal < FLT_MIN
     513       41711 :             Word16 flag = 0;
     514       41711 :             move16();
     515       41711 :             if ( MaxAbsVal <= 0 )
     516             :             {
     517          29 :                 flag = 1;
     518          29 :                 move16();
     519             :             }
     520       41711 :             test();
     521       41711 :             IF( ( pState->gain_state[i].lastExp == 0 ) || ( flag ) )
     522             :             {
     523       36630 :                 pState->gain_state[i].gainExpVal = 0;
     524       36630 :                 move16();
     525       36630 :                 pState->gain_state[i].prevExp = pState->gain_state[i].lastExp;
     526       36630 :                 move16();
     527       36630 :                 isGainAdjusted = TRUE;
     528       36630 :                 move16();
     529             :             }
     530             :             ELSE
     531             :             {
     532             :                 Word32 smoothedMaxAbsVal, maxGain;
     533             :                 Word16 q_smoothedMaxAbsVal, q_maxGain;
     534             :                 Word32 temp1, temp2;
     535        5081 :                 Word16 Comp_flag, q_temp, e_result = 0;
     536        5081 :                 temp1 = Mpy_32_32( pState->smFact_fx, MaxAbsVal );                                                    // q_MaxAbsVal
     537        5081 :                 temp2 = Mpy_32_32( ( L_sub( ONE_IN_Q31, pState->smFact_fx ) ), pState->gain_state[i].lastMaxAbs_fx ); // q_lastMaxAbs_fx
     538             : 
     539        5081 :                 smoothedMaxAbsVal = BASOP_Util_Add_Mant32Exp( temp1, sub( Q31, q_MaxAbsVal ), temp2, sub( Q31, pState->gain_state[i].q_lastMaxAbs_fx ), &e_result ); /* exp(e_result) */
     540        5081 :                 q_smoothedMaxAbsVal = sub( Q31, e_result );
     541             : 
     542        5081 :                 pState->gain_state[i].lastMaxAbs_fx = smoothedMaxAbsVal; /* q_smoothedMaxAbsVal */
     543        5081 :                 move32();
     544        5081 :                 pState->gain_state[i].q_lastMaxAbs_fx = q_smoothedMaxAbsVal;
     545        5081 :                 move16();
     546             : 
     547        5081 :                 Comp_flag = BASOP_Util_Cmp_Mant32Exp_sat( smoothedMaxAbsVal, sub( Q31, q_smoothedMaxAbsVal ), MaxAbsVal, sub( Q31, q_MaxAbsVal ) );
     548        5081 :                 IF( EQ_16( Comp_flag, 1 ) )
     549             :                 {
     550        3724 :                     temp1 = smoothedMaxAbsVal; /* q_smoothedMaxAbsVal */
     551        3724 :                     move32();
     552        3724 :                     q_temp = q_smoothedMaxAbsVal;
     553        3724 :                     move16();
     554             :                 }
     555             :                 ELSE
     556             :                 {
     557        1357 :                     temp1 = MaxAbsVal;
     558        1357 :                     move32();
     559        1357 :                     q_temp = q_MaxAbsVal;
     560        1357 :                     move16();
     561             :                 }
     562        5081 :                 temp1 = Mpy_32_32( temp1, TWO_IN_Q29 ); /* q_temp + 29 - 31 */
     563        5081 :                 q_temp = add( q_temp, Q29 - Q31 );
     564        5081 :                 maxGain = Mpy_32_32( temp1, pState->gain_state[i].lastGain_fx ); /* q_temp + pState->gain_state[i].q_lastGain_fx - 31 */
     565        5081 :                 q_maxGain = add( q_temp, sub( pState->gain_state[i].q_lastGain_fx, Q31 ) );
     566             : 
     567        5081 :                 temp2 = ONE_MINUS_M_DELTA_PROD_FLT_FC; // Q15
     568        5081 :                 move16();
     569        5081 :                 Comp_flag = BASOP_Util_Cmp_Mant32Exp_sat( temp2, Q16, maxGain, sub( Q31, q_maxGain ) );
     570        5081 :                 IF( EQ_16( Comp_flag, 1 ) )
     571             :                 {
     572         282 :                     pState->gain_state[i].gainExpVal = -1;
     573         282 :                     move16();
     574             :                 }
     575             :                 ELSE
     576             :                 {
     577        4799 :                     pState->gain_state[i].gainExpVal = 0;
     578        4799 :                     move16();
     579             :                 }
     580             :             }
     581             :         }
     582             :         ELSE
     583             :         {
     584         307 :             pState->gain_state[i].lastMaxAbs_fx = MaxAbsVal; /* q_MaxAbsVal */
     585         307 :             move32();
     586         307 :             pState->gain_state[i].q_lastMaxAbs_fx = q_MaxAbsVal;
     587         307 :             move16();
     588             :         }
     589             : 
     590       42018 :         IF( !isGainAdjusted )
     591             :         {
     592        5388 :             Word32 actualMaxAbsVal = 0;
     593        5388 :             move16();
     594             :             Word16 currMaxAttExp, q_actualMaxAbsVal;
     595             : 
     596        5388 :             currMaxAttExp = s_min( ( add( pState->gain_state[i].lastExp, pState->agc_com.absEmin ) ), pState->agc_com.maxAttExp );
     597        5388 :             extendedExpVal = FALSE;
     598        5388 :             move16();
     599             : 
     600        5388 :             IF( isClipped )
     601             :             {
     602         307 :                 Word16 isCompensated = FALSE;
     603             :                 Word32 temp1, temp2;
     604         307 :                 actualMaxAbsVal = Mpy_32_32( pState->gain_state[i].lastMaxAbs_fx, pState->gain_state[i].lastGain_fx ); // QlastGain_fx
     605         307 :                 q_actualMaxAbsVal = add( pState->gain_state[i].q_lastMaxAbs_fx, sub( pState->gain_state[i].q_lastGain_fx, Q31 ) );
     606         307 :                 idx = s_min( sub( offset, 1 ), MaxAbsValIdx ); /* Q0 */
     607             : 
     608         307 :                 q_actualMaxAbsVal = add( q_actualMaxAbsVal, norm_l( actualMaxAbsVal ) );
     609         307 :                 temp1 = L_shl( actualMaxAbsVal, norm_l( actualMaxAbsVal ) );
     610         307 :                 temp1 = BASOP_Util_Log2( temp1 );                                          // Q25
     611         307 :                 temp1 = L_add( temp1, L_shl( sub( Q31, q_actualMaxAbsVal ), 25 ) );        // Q25
     612         307 :                 temp1 = L_negate( L_add( temp1, LOG2_MDFT_NORM_SCALING_FX ) );             // Q25
     613         307 :                 temp2 = BASOP_Util_Log2( L_deposit_h( pState->agc_com.winFunc_fx[idx] ) ); // Q25
     614             :                 Word16 temp_16, div_e;
     615         307 :                 IF( temp2 == 0 )
     616             :                 {
     617           0 :                     temp_16 = 0;
     618           0 :                     move16();
     619             :                 }
     620             :                 ELSE
     621             :                 {
     622         307 :                     temp_16 = BASOP_Util_Divide3232_Scale( temp1, temp2, &div_e ); /* exp(div_e) */
     623         307 :                     IF( div_e < 0 )
     624             :                     {
     625         248 :                         temp_16 = shr( temp_16, abs_s( div_e ) );
     626         248 :                         div_e = 0;
     627         248 :                         move16();
     628             :                     }
     629         307 :                     temp_16 = ceil_fx( temp_16, sub( Q15, div_e ) ); /* Q0 */
     630             :                 }
     631         307 :                 pState->gain_state[i].gainExpVal = temp_16; /* Q0 */
     632         307 :                 move16();
     633             : 
     634         614 :                 WHILE( !isCompensated )
     635             :                 {
     636             :                     Word32 tmpSignal;
     637             :                     Word16 q_tmpSignal;
     638         307 :                     isCompensated = TRUE;
     639         307 :                     Word16 tmp_1, q_tmp_2 = 31, e_div;
     640         307 :                     move16();
     641         307 :                     Word32 tmp_2 = ONE_IN_Q31;
     642         307 :                     move16();
     643         307 :                     tmp_1 = pState->gain_state[i].gainExpVal; /* Q0 */
     644         307 :                     move16();
     645        5096 :                     FOR( idx = clippedIdx; idx <= MaxAbsValIdx; idx++ )
     646             :                     {
     647        4789 :                         IF( GE_16( idx, offset ) )
     648             :                         {
     649         282 :                             idx = MaxAbsValIdx;
     650         282 :                             move16();
     651         282 :                             IF( tmp_1 < 0 )
     652             :                             {
     653           0 :                                 tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], ( negate( tmp_1 ) ) ); /* Q31 */
     654           0 :                                 IF( tmp_2 < 0 )
     655             :                                 {
     656           0 :                                     tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
     657           0 :                                     tmp_2 = L_negate( tmp_2 );
     658             :                                 }
     659             :                                 ELSE
     660             :                                 {
     661           0 :                                     tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
     662             :                                 }
     663           0 :                                 q_tmp_2 = sub( Q31, e_div );
     664             :                             }
     665             :                             ELSE
     666             :                             {
     667         282 :                                 tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], tmp_1 ); /* Q31 */
     668         282 :                                 q_tmp_2 = Q31;
     669         282 :                                 move16();
     670             :                             }
     671             :                         }
     672             :                         ELSE
     673             :                         {
     674        4507 :                             IF( tmp_1 < 0 )
     675             :                             {
     676           0 :                                 tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], ( negate( tmp_1 ) ) ); /* Q31 */
     677           0 :                                 IF( tmp_2 < 0 )
     678             :                                 {
     679           0 :                                     tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
     680           0 :                                     tmp_2 = L_negate( tmp_2 );
     681             :                                 }
     682             :                                 ELSE
     683             :                                 {
     684           0 :                                     tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
     685             :                                 }
     686           0 :                                 q_tmp_2 = sub( Q31, e_div );
     687             :                             }
     688             :                             ELSE
     689             :                             {
     690        4507 :                                 tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], tmp_1 );
     691        4507 :                                 q_tmp_2 = Q31;
     692        4507 :                                 move16();
     693             :                             }
     694             :                         }
     695             : 
     696        4789 :                         tmpSignal = Mpy_32_32( ppPcm_out[i][idx], tmp_2 ); /* q_pcm + q_tmp_2 - 31 */
     697        4789 :                         q_tmpSignal = add( q_pcm, sub( q_tmp_2, 31 ) );
     698             : 
     699        4789 :                         Word16 comp_flag_1 = BASOP_Util_Cmp_Mant32Exp_sat( tmpSignal, sub( Q31, q_tmpSignal ), ONE_MINUS_M_DELTA_PROD_FLT_FC, Q16 );
     700        4789 :                         IF( EQ_16( comp_flag_1, 1 ) )
     701             :                         {
     702           0 :                             comp_flag_1 = 1;
     703           0 :                             move16();
     704             :                         }
     705             :                         ELSE
     706             :                         {
     707        4789 :                             comp_flag_1 = 0;
     708        4789 :                             move16();
     709             :                         }
     710             : 
     711        4789 :                         Word16 comp_flag_2 = BASOP_Util_Cmp_Mant32Exp_sat( MIN16B_FLT_FX_IN_Q15, Q16, tmpSignal, sub( Q31, q_tmpSignal ) );
     712        4789 :                         IF( EQ_16( comp_flag_2, 1 ) )
     713             :                         {
     714           0 :                             comp_flag_2 = 1;
     715           0 :                             move16();
     716             :                         }
     717             :                         ELSE
     718             :                         {
     719        4789 :                             comp_flag_2 = 0;
     720        4789 :                             move16();
     721             :                         }
     722        4789 :                         test();
     723        4789 :                         IF( ( comp_flag_1 ) || ( comp_flag_2 ) )
     724             :                         {
     725           0 :                             isCompensated = FALSE;
     726           0 :                             move16();
     727           0 :                             BREAK;
     728             :                         }
     729             :                     }
     730         307 :                     IF( !isCompensated )
     731             :                     {
     732           0 :                         pState->gain_state[i].gainExpVal = add( pState->gain_state[i].gainExpVal, 1 ); /* Q0 */
     733           0 :                         move16();
     734             :                     }
     735             : 
     736         307 :                     IF( GT_16( pState->gain_state[i].gainExpVal, currMaxAttExp ) )
     737             :                     {
     738           0 :                         pState->gain_state[i].gainExpVal = s_min( pState->gain_state[i].gainExpVal, currMaxAttExp ); /* Q0 */
     739           0 :                         move16();
     740           0 :                         BREAK;
     741             :                     }
     742             :                 }
     743             :             }
     744             : 
     745        5388 :             Word16 q_pcm_tmp = q_pcm;
     746     3462028 :             FOR( idx = 0; idx < input_frame; idx++ )
     747             :             {
     748             :                 Word16 tmp_1, q_tmp_2, e_div;
     749             :                 Word32 tmp_2;
     750     3456640 :                 tmp_1 = pState->gain_state[i].gainExpVal; /* Q0 */
     751     3456640 :                 move16();
     752             : 
     753     3456640 :                 IF( GT_16( offset, idx ) )
     754             :                 {
     755     1382656 :                     IF( tmp_1 < 0 )
     756             :                     {
     757       72960 :                         tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], ( negate( tmp_1 ) ) );
     758       72960 :                         IF( tmp_2 < 0 )
     759             :                         {
     760           0 :                             tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
     761           0 :                             tmp_2 = L_negate( tmp_2 );
     762             :                         }
     763             :                         ELSE
     764             :                         {
     765       72960 :                             tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
     766             :                         }
     767       72960 :                         q_tmp_2 = sub( Q31, e_div );
     768             :                     }
     769             :                     ELSE
     770             :                     {
     771     1309696 :                         tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], tmp_1 ); /* Q31 */
     772     1309696 :                         q_tmp_2 = Q31;
     773     1309696 :                         move16();
     774             :                     }
     775             :                 }
     776             :                 ELSE
     777             :                 {
     778     2073984 :                     IF( tmp_1 < 0 )
     779             :                     {
     780      109440 :                         tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], ( negate( tmp_1 ) ) ); /* Q31 */
     781      109440 :                         IF( tmp_2 < 0 )
     782             :                         {
     783           0 :                             tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
     784           0 :                             tmp_2 = L_negate( tmp_2 );
     785             :                         }
     786             :                         ELSE
     787             :                         {
     788      109440 :                             tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
     789             :                         }
     790      109440 :                         q_tmp_2 = sub( Q31, e_div );
     791             :                     }
     792             :                     ELSE
     793             :                     {
     794     1964544 :                         tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], tmp_1 ); /* Q31 */
     795     1964544 :                         q_tmp_2 = Q31;
     796     1964544 :                         move16();
     797             :                     }
     798             :                 }
     799             :                 // gain = tmp_2;
     800     3456640 :                 ppPcm_out[i][idx] = Mpy_32_32( ppPcm_out[i][idx], tmp_2 ); // Q remains same
     801     3456640 :                 move32();
     802     3456640 :                 q_pcm = add( q_pcm_tmp, sub( q_tmp_2, Q31 ) );
     803             :             }
     804             : 
     805             : 
     806             :             Word16 tmp_1, q_tmp_2, e_div;
     807             :             Word32 tmp_2;
     808        5388 :             tmp_1 = pState->gain_state[i].gainExpVal; /* Q0 */
     809        5388 :             move16();
     810        5388 :             IF( tmp_1 < 0 )
     811             :             {
     812         282 :                 tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], ( negate( tmp_1 ) ) ); /* Q31 */
     813         282 :                 IF( tmp_2 < 0 )
     814             :                 {
     815           0 :                     tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
     816           0 :                     tmp_2 = L_negate( tmp_2 );
     817             :                 }
     818             :                 ELSE
     819             :                 {
     820         282 :                     tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
     821             :                 }
     822         282 :                 q_tmp_2 = sub( Q31, e_div );
     823             :             }
     824             :             ELSE
     825             :             {
     826        5106 :                 tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], tmp_1 ); /* Q31 */
     827        5106 :                 q_tmp_2 = Q31;
     828        5106 :                 move16();
     829             :             }
     830        5388 :             pState->gain_state[i].lastGain_fx = Mpy_32_32( pState->gain_state[i].lastGain_fx, tmp_2 ); /* pState->gain_state[i].q_lastGain_fx + q_tmp_2 - 31 */
     831        5388 :             move32();
     832        5388 :             pState->gain_state[i].q_lastGain_fx = add( pState->gain_state[i].q_lastGain_fx, sub( q_tmp_2, Q31 ) );
     833        5388 :             move16();
     834             : 
     835             :             /*safety check starts*/
     836        5388 :             if ( EQ_16( pState->gain_state[i].gainExpVal, add( pState->agc_com.maxAttExp, 1 ) ) )
     837             :             {
     838           0 :                 extendedExpVal = TRUE;
     839           0 :                 move16();
     840             :             }
     841             :             /*safety check ends*/
     842             : 
     843        5388 :             pState->gain_state[i].prevExp = pState->gain_state[i].lastExp;
     844        5388 :             move16();
     845             : 
     846        5388 :             pState->gain_state[i].lastExp = sub( pState->gain_state[i].lastExp, pState->gain_state[i].gainExpVal );
     847        5388 :             move16();
     848        5388 :             if ( extendedExpVal )
     849             :             {
     850           0 :                 pState->gain_state[i].gainExpVal = -1;
     851           0 :                 move16();
     852             :             }
     853             :         }
     854             : 
     855       42018 :         pState->gain_data[i].absGainExp = add( pState->gain_state[i].prevExp, pState->agc_com.absEmin );
     856       42018 :         move16();
     857             : 
     858       42018 :         IF( extendedExpVal )
     859             :         {
     860           0 :             IF( pState->gain_state[i].gainExpVal <= 0 )
     861             :             {
     862           0 :                 pState->gain_state[i].gainExpVal = add( pState->agc_com.maxAttExp, 1 ); /* Q0 */
     863           0 :                 move16();
     864             :             }
     865             :         }
     866       42018 :         pState->gain_data[i].absGainExpCurr = sub( pState->gain_data[i].absGainExp, pState->gain_state[i].gainExpVal ); /* Q0 */
     867       42018 :         move16();
     868             : 
     869       42018 :         test();
     870       42018 :         IF( GT_16( pState->gain_data[i].absGainExpCurr, pState->agc_com.absEmin ) || ( pState->gain_data[i].absGainExpCurr < 0 ) )
     871             :         {
     872           0 :             assert( 0 );
     873             :         }
     874             : 
     875       42018 :         IF( EQ_16( pState->gain_data[i].absGainExpCurr, pState->agc_com.absEmin ) )
     876             :         {
     877       36737 :             per_ch_bit[i] = 0;
     878       36737 :             move16();
     879             :         }
     880             :         ELSE
     881             :         {
     882        5281 :             per_ch_bit[i] = 1;
     883        5281 :             move16();
     884        5281 :             AGC_flag = 1;
     885        5281 :             move16();
     886             :         }
     887       42018 :         q_ppPcm[i] = q_pcm;
     888       42018 :         move16();
     889             :     }
     890             : 
     891       42018 :     push_next_indice( hMetaData, AGC_flag, 1 );
     892             :     /* encode AGC parameters */
     893       42018 :     IF( EQ_16( AGC_flag, 1 ) )
     894             :     {
     895        5281 :         IF( GT_16( n_channels, 1 ) )
     896             :         {
     897           0 :             FOR( i = 0; i < n_channels; i++ )
     898             :             {
     899           0 :                 push_next_indice( hMetaData, per_ch_bit[i], 1 );
     900             :             }
     901             :         }
     902        5281 :         assert( AGC_BITS_PER_CH == ( pState->agc_com.betaE + 1 ) );
     903             : 
     904       10562 :         FOR( i = 0; i < n_channels; i++ )
     905             :         {
     906        5281 :             IF( EQ_16( per_ch_bit[i], 1 ) )
     907             :             {
     908        5281 :                 push_next_indice( hMetaData, (UWord16) pState->gain_data[i].absGainExpCurr, (Word16) pState->agc_com.betaE );
     909             :             }
     910             :         }
     911             :     }
     912             : 
     913       42018 :     return;
     914             : }

Generated by: LCOV version 1.14