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

Generated by: LCOV version 1.14