LCOV - code coverage report
Current view: top level - lib_dec - nelp_dec_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 0 204 0.0 %
Date: 2025-05-03 01:55:50 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include "options.h" /* Compilation switches */
       7             : #include "prot_fx.h" /* Function prototypes */
       8             : #include "rom_com.h"
       9             : 
      10             : /*===================================================================*/
      11             : /* FUNCTION      :  normalize_arr()                                  */
      12             : /*-------------------------------------------------------------------*/
      13             : /* PURPOSE       :  Normalize array                                  */
      14             : /*                                                                   */
      15             : /*-------------------------------------------------------------------*/
      16             : /* GLOBAL INPUT ARGUMENTS  :                                         */
      17             : /*    _ (Word16*) qf                                                 */
      18             : /*    _ (Word16*) size                                               */
      19             : /*    _ (Word16*) hdr                                                */
      20             : /*-------------------------------------------------------------------*/
      21             : /* OUTPUT ARGUMENTS :                                                */
      22             : /*    _ (Word16*) arr : Normalized array                             */
      23             : /*-------------------------------------------------------------------*/
      24             : 
      25             : /*     _ None                                                        */
      26             : /*-------------------------------------------------------------------*/
      27             : /* RETURN ARGUMENTS :                                                */
      28             : /*     _ None                                                        */
      29             : /*===================================================================*/
      30           0 : static void normalize_arr( Word16 *arr, Word16 *qf, Word16 size, Word16 hdr )
      31             : {
      32           0 :     Word16 i, max_s = 0;
      33           0 :     move16();
      34             : 
      35           0 :     FOR( i = 0; i < size; i++ )
      36             :     {
      37           0 :         max_s = s_max( max_s, abs_s( arr[i] ) );
      38             :     }
      39             : 
      40           0 :     *qf = norm_s( (Word16) max_s );
      41           0 :     test();
      42           0 :     IF( ( *qf == 0 ) && ( ( (Word16) max_s ) == 0 ) )
      43             :     {
      44           0 :         *qf = 15;
      45           0 :         move16();
      46             :     }
      47             : 
      48           0 :     *qf = sub( *qf, hdr );
      49           0 :     move16();
      50             : 
      51           0 :     FOR( i = 0; i < size; i++ )
      52             :     {
      53           0 :         arr[i] = shl( arr[i], *qf );
      54           0 :         move16(); /* saturation can occur here */
      55             :     }
      56             : 
      57           0 :     return;
      58             : }
      59             : 
      60             : /*===================================================================*/
      61             : /* FUNCTION      :  nelp_decoder_fx()                                */
      62             : /*-------------------------------------------------------------------*/
      63             : /* PURPOSE       :  NELP decoding for the current frame              */
      64             : /*                                                                   */
      65             : /*-------------------------------------------------------------------*/
      66             : /* GLOBAL INPUT ARGUMENTS  :                                         */
      67             : /*    _ (Struct)   st                                                */
      68             : /*    _ (Word16[]) exc_nelp    : adapt. excitation/total exc (Q0)    */
      69             : /*    _ (Word16[]) exc         : adapt. excitation exc (Q0)          */
      70             : /*    _ (Word16)   bfi         : frame error rate                    */
      71             : /*    _ (Word16)   coder_type  : coding type                         */
      72             : /*-------------------------------------------------------------------*/
      73             : /* OUTPUT ARGUMENTS :                                                */
      74             : /*    _ (Word16[]) exc_nelp    : adapt. excitation/total exc (Q0)    */
      75             : /*      (Word16[]) gain_buf    : floating pitch gain for each subframe */
      76             : /*-------------------------------------------------------------------*/
      77             : 
      78             : /*    _ (Word16[])  shape1_filt_mem_dec : filter memory (Q0)         */
      79             : /*    _ (Word16[])  shape2_filt_mem_dec : filter memory (Q0)         */
      80             : /*    _ (Word16[])  shape3_filt_mem_dec : filter memory (Q0)         */
      81             : /*    _ (Word16[])  bp1_filt_mem_wb_dec : filter memory (Q0)         */
      82             : /*    _ (Word16[])  bp1_filt_mem_nb_dec : filter memory (Q0)         */
      83             : /*-------------------------------------------------------------------*/
      84             : /* RETURN ARGUMENTS :                                                */
      85             : /*     _ None                                                        */
      86             : /*===================================================================*/
      87             : 
      88           0 : void nelp_decoder_fx(
      89             :     Decoder_State *st_fx,
      90             :     Word16 *exc_nelp, /* Q0 */
      91             :     Word16 *exc,      /* Q_exc */
      92             :     Word16 *Q_exc,
      93             :     Word16 bfi,              /* Q0 */
      94             :     const Word16 coder_type, /* Q0 */
      95             :     Word16 *gain_buf         /* Q14 */
      96             : )
      97             : {
      98           0 :     Word16 i, fid = 0;
      99           0 :     move16();
     100             :     Word16 ptr[L_FRAME], filtRes[L_FRAME], gain_fac; /*ptr, filtRes - Q0, gain_fac - Q14 */
     101             :     Word16 Gains[10];                                /* Q0 */
     102             :     Word32 Gain, E3, E2;
     103           0 :     Word16 BP1_ORDER = 4;
     104           0 :     move16();
     105             :     Word16 ptr_tmp[L_FRAME]; /* Q0 */
     106             :     Word16 iG1, iG2[2];
     107             :     Word16 exp_E2, exp_E3, frac_E2, frac_E3;
     108             :     Word16 tmp, scale, exp, frac;
     109             :     Word32 L_tmp, L_tmp1;
     110             :     Word32 exc_sqr[L_SUBFR];
     111             :     Word32 max_exc_sqr;
     112             :     Word16 n;
     113           0 :     Word16 max_val = 0, norm_val = 0;
     114           0 :     move16();
     115           0 :     move16();
     116           0 :     Word16 qGain = 0;
     117           0 :     move16();
     118             :     SC_VBR_DEC_HANDLE hSC_VBR;
     119             : 
     120           0 :     hSC_VBR = st_fx->hSC_VBR;
     121             : 
     122           0 :     test();
     123           0 :     if ( EQ_16( st_fx->last_nelp_mode_dec, 1 ) && NE_16( st_fx->bwidth, st_fx->last_bwidth ) )
     124             :     {
     125           0 :         st_fx->last_nelp_mode_dec = 0;
     126           0 :         move16();
     127             :     }
     128             : 
     129           0 :     test();
     130           0 :     test();
     131           0 :     test();
     132           0 :     IF( EQ_16( coder_type, UNVOICED ) && EQ_16( st_fx->bwidth, NB ) )
     133             :     {
     134           0 :         IF( NE_16( st_fx->last_nelp_mode_dec, 1 ) )
     135             :         {
     136           0 :             BP1_ORDER = 7; /* Q0 */
     137           0 :             move16();
     138             : 
     139           0 :             set32_fx( hSC_VBR->bp1_filt_mem_nb_dec_fx, 0, BP1_ORDER * 2 );
     140             :         }
     141             :     }
     142           0 :     ELSE IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
     143             :     {
     144           0 :         BP1_ORDER = 4; /* Q0 */
     145           0 :         move16();
     146           0 :         IF( NE_16( st_fx->last_nelp_mode_dec, 1 ) )
     147             :         {
     148           0 :             set16_fx( hSC_VBR->bp1_filt_mem_wb_dec_fx, 0, shl( BP1_ORDER, 1 ) );
     149             :         }
     150             :     }
     151             : 
     152           0 :     IF( NE_16( st_fx->last_nelp_mode_dec, 1 ) )
     153             :     {
     154           0 :         set16_fx( hSC_VBR->shape1_filt_mem_dec_fx, 0, 10 );
     155           0 :         set16_fx( hSC_VBR->shape2_filt_mem_dec_fx, 0, 10 );
     156           0 :         set16_fx( hSC_VBR->shape3_filt_mem_dec_fx, 0, 10 );
     157             :     }
     158             : 
     159           0 :     IF( bfi == 0 )
     160             :     {
     161           0 :         test();
     162           0 :         IF( EQ_16( st_fx->rf_frame_type, RF_NELP ) && EQ_16( st_fx->use_partial_copy, 1 ) )
     163             :         {
     164           0 :             iG1 = st_fx->rf_indx_nelp_iG1; /* Q0 */
     165           0 :             move16();
     166           0 :             iG2[0] = st_fx->rf_indx_nelp_iG2[0]; /* Q0 */
     167           0 :             move16();
     168           0 :             iG2[1] = st_fx->rf_indx_nelp_iG2[1]; /* Q0 */
     169           0 :             move16();
     170             :         }
     171             :         ELSE
     172             :         {
     173             :             /* Do Unvoiced/NELP Decoding */
     174           0 :             iG1 = (Word16) get_next_indice_fx( st_fx, 5 ); /* Q0 */
     175           0 :             move16();
     176           0 :             iG2[0] = (Word16) get_next_indice_fx( st_fx, 6 ); /* Q0 */
     177           0 :             move16();
     178           0 :             iG2[1] = (Word16) get_next_indice_fx( st_fx, 6 ); /* Q0 */
     179           0 :             move16();
     180             :         }
     181             : 
     182           0 :         test();
     183           0 :         test();
     184           0 :         IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
     185             :         {
     186           0 :             test();
     187           0 :             IF( EQ_16( st_fx->rf_frame_type, RF_NELP ) && EQ_16( st_fx->use_partial_copy, 1 ) )
     188             :             {
     189           0 :                 fid = st_fx->rf_indx_nelp_fid; /* Q0 */
     190           0 :                 move16();
     191             :             }
     192             :             ELSE
     193             :             {
     194           0 :                 fid = (Word16) get_next_indice_fx( st_fx, 2 ); /* Q0 */
     195           0 :                 move16();
     196             :             }
     197             :         }
     198             : 
     199           0 :         *Q_exc = dequantize_uvg_fx( iG1, iG2, Gains, st_fx->bwidth, 1 );
     200           0 :         move16(); /* Gains - Q0/Q3 */
     201             :     }
     202             :     ELSE
     203             :     {
     204           0 :         FOR( i = 1; i <= L_SUBFR; i++ )
     205             :         {
     206           0 :             exc_sqr[i - 1] = L_mult0( exc[-i], exc[-i] );
     207           0 :             move32(); /*2*Q_exc */
     208             :         }
     209           0 :         max_exc_sqr = L_deposit_l( 0 );
     210           0 :         FOR( i = 0; i < L_SUBFR; i++ )
     211             :         {
     212           0 :             max_exc_sqr = L_max( max_exc_sqr, exc_sqr[i] ); /*2*Q_exc */
     213             :         }
     214           0 :         IF( max_exc_sqr != 0 )
     215             :         {
     216           0 :             exp = norm_l( max_exc_sqr );
     217           0 :             FOR( i = 0; i < L_SUBFR; i++ )
     218             :             {
     219           0 :                 exc_sqr[i] = L_shl( exc_sqr[i], exp );
     220           0 :                 move32(); /*Q30 */
     221             :             }
     222           0 :             exp = sub( 30, add( exp, add( *Q_exc, *Q_exc ) ) );
     223             : 
     224           0 :             Gain = L_deposit_l( 1 );
     225           0 :             FOR( i = 0; i < L_SUBFR; i++ )
     226             :             {
     227           0 :                 Gain = L_add( Gain, L_shr( exc_sqr[i], 6 ) ); /*Q24 */
     228             :             }
     229           0 :             Gain = Mult_32_16( Gain, 20972 ); /*Q24; 20972=sqr(0.8) in Q15 */
     230           0 :             exp = sub( exp, 6 );              /*due to /L_SUBFR */
     231             : 
     232           0 :             IF( s_and( exp, 1 ) != 0 )
     233             :             {
     234           0 :                 Gain = L_shr( Gain, 1 ); /*Q24 */
     235           0 :                 exp = add( exp, 1 );
     236             :             }
     237           0 :             exp = shr( exp, 1 );
     238           0 :             n = norm_l( Gain );
     239           0 :             frac = round_fx( L_shl( Gain, n ) );
     240           0 :             n = sub( add( n, 24 ), 30 );
     241           0 :             frac = div_s( 16384, frac );                               /* Q15 */
     242           0 :             Gain = Isqrt_lc( L_deposit_h( frac ), &n );                /*Q(31-n-exp) */
     243           0 :             tmp = round_fx( L_shl( Gain, sub( add( n, exp ), 15 ) ) ); /*Q0 */
     244             :         }
     245             :         ELSE
     246             :         {
     247           0 :             tmp = 0;
     248           0 :             move16();
     249             :         }
     250             : 
     251           0 :         set16_fx( Gains, tmp, 10 );
     252           0 :         *Q_exc = 0;
     253           0 :         move16();
     254             :     }
     255             : 
     256             : 
     257           0 :     gain_fac = 22446;
     258           0 :     move16(); /* 1.37f - Q14 */
     259           0 :     test();
     260           0 :     test();
     261           0 :     if ( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
     262             :     {
     263           0 :         gain_fac = 19005;
     264           0 :         move16(); /* 1.16f - Q14 */
     265             :     }
     266             : 
     267           0 :     test();
     268           0 :     IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) )
     269             :     {
     270             :         /* Normalize Gains[10] with headroom 4, qGain is the new Q value os Gains, not Q0*/
     271             :         /* This is done to avoid internal overflow observed in the wb bp filter below, similar to encoder */
     272           0 :         normalize_arr( Gains, &qGain, 10, 4 );
     273             :     }
     274             : 
     275           0 :     generate_nelp_excitation_fx( &( hSC_VBR->nelp_dec_seed ), Gains, ptr, gain_fac );
     276             :     /* o: ptr = nelp_exc in Q=qGain, qGain = 0 always for NB */
     277             : 
     278           0 :     test();
     279           0 :     test();
     280           0 :     IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
     281             :     {
     282           0 :         BP1_ORDER = 4; /* Q0 */
     283           0 :         move16();
     284           0 :         Scale_sig( hSC_VBR->bp1_filt_mem_wb_dec_fx, shl( BP1_ORDER, 1 ), qGain ); /* bring filter prev memory from Q0 to qGain */
     285           0 :         pz_filter_sp_fx( bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr, ptr_tmp, hSC_VBR->bp1_filt_mem_wb_dec_fx,
     286           0 :                          BP1_ORDER, BP1_ORDER, L_FRAME, ( sub( 16, BP1_COEF_WB_QF ) ) );
     287             : 
     288           0 :         Scale_sig( hSC_VBR->bp1_filt_mem_wb_dec_fx, shl( BP1_ORDER, 1 ), negate( qGain ) ); /* bring filter prev memory from qGain to Q0 */
     289           0 :         Scale_sig( ptr_tmp, L_FRAME, -qGain );                                              /* bring nelp_exc to Q0 */
     290           0 :         Copy( ptr_tmp, ptr, L_FRAME );                                                      /* Q0 */
     291             :     }
     292             : 
     293           0 :     test();
     294           0 :     IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, NB ) ) )
     295             :     {
     296           0 :         BP1_ORDER = 7; /* Q0 */
     297           0 :         move16();
     298             : 
     299           0 :         FOR( i = 0; i < L_FRAME; i++ )
     300             :         {
     301           0 :             max_val = s_max( ptr[i], max_val ); /* Q0 */
     302             :         }
     303           0 :         tmp = shl( BP1_ORDER, 1 );
     304           0 :         FOR( i = 0; i < tmp; i++ )
     305             :         {
     306           0 :             max_val = s_max( round_fx( L_shr( hSC_VBR->bp1_filt_mem_nb_dec_fx[i], 16 ) ), max_val );
     307             :         }
     308           0 :         norm_val = norm_s( max_val );
     309             : 
     310           0 :         norm_val = s_max( 0, sub( norm_val, 4 ) ); /* 4 bit head room */
     311             : 
     312           0 :         norm_val = s_min( norm_val, 8 ); /* scale only for very low level signals */
     313             : 
     314           0 :         IF( norm_val > 0 )
     315             :         {
     316           0 :             Scale_sig32( hSC_VBR->bp1_filt_mem_nb_dec_fx, shl( BP1_ORDER, 1 ), norm_val ); /* norm_val */
     317           0 :             Scale_sig( ptr, L_FRAME, norm_val );                                           /* norm_val + Q_exc */
     318           0 :             *Q_exc = add( norm_val, *Q_exc );
     319           0 :             move16();
     320             :         }
     321             : 
     322           0 :         BP1_ORDER = 7; /* Q0 */
     323           0 :         move16();
     324           0 :         pz_filter_dp_fx( bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr, ptr_tmp, hSC_VBR->bp1_filt_mem_nb_dec_fx,
     325           0 :                          BP1_ORDER, BP1_ORDER, L_FRAME, ( sub( 16, BP1_COEF_NB_QF_ORDER7 ) ) );
     326             : 
     327             : 
     328           0 :         IF( norm_val > 0 )
     329             :         {
     330           0 :             Scale_sig32( hSC_VBR->bp1_filt_mem_nb_dec_fx, shl( BP1_ORDER, 1 ), negate( norm_val ) );
     331             :         }
     332             : 
     333           0 :         Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
     334             :     }
     335             : 
     336           0 :     E3 = L_deposit_l( 1 );
     337           0 :     FOR( i = 0; i < L_FRAME; i++ )
     338             :     {
     339           0 :         E3 = L_mac0_sat( E3, ptr[i], ptr[i] ); /*2*Q_exc */
     340             :     }
     341             : 
     342             : 
     343           0 :     test();
     344           0 :     test();
     345           0 :     IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
     346             :     {
     347           0 :         pz_filter_sp_fx( shape1_num_coef_fx, shape1_den_coef_fx, ptr, ptr_tmp, hSC_VBR->shape1_filt_mem_dec_fx,
     348           0 :                          10, 10, L_FRAME, ( sub( 16, SHAPE1_COEF_QF ) ) );
     349           0 :         Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
     350             : 
     351           0 :         SWITCH( fid )
     352             :         {
     353           0 :             case 1:
     354             :                 /* Update other filter memory */
     355           0 :                 pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr, filtRes, hSC_VBR->shape3_filt_mem_dec_fx,
     356           0 :                                  10, 10, L_FRAME, ( sub( 16, SHAPE3_COEF_QF ) ) );
     357             : 
     358             :                 /* filter the residual to desired shape */
     359           0 :                 pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr, ptr_tmp, hSC_VBR->shape2_filt_mem_dec_fx,
     360           0 :                                  10, 10, L_FRAME, ( sub( 16, SHAPE2_COEF_QF ) ) );
     361             : 
     362           0 :                 Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
     363             : 
     364           0 :                 BREAK;
     365           0 :             case 2:
     366             :                 /* Update other filter memory */
     367           0 :                 pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr, filtRes, hSC_VBR->shape2_filt_mem_dec_fx,
     368           0 :                                  10, 10, L_FRAME, ( sub( 16, SHAPE2_COEF_QF ) ) );
     369             : 
     370             :                 /* filter the residual to desired shape */
     371           0 :                 pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr, ptr_tmp, hSC_VBR->shape3_filt_mem_dec_fx,
     372           0 :                                  10, 10, L_FRAME, ( sub( 16, SHAPE3_COEF_QF ) ) );
     373             : 
     374           0 :                 Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
     375             : 
     376           0 :                 BREAK;
     377           0 :             default:
     378             :                 /* Update other filter memory */
     379           0 :                 pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr, filtRes, hSC_VBR->shape2_filt_mem_dec_fx,
     380           0 :                                  10, 10, L_FRAME, ( sub( 16, SHAPE2_COEF_QF ) ) );
     381           0 :                 pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr, filtRes, hSC_VBR->shape3_filt_mem_dec_fx,
     382           0 :                                  10, 10, L_FRAME, ( sub( 16, SHAPE3_COEF_QF ) ) );
     383             : 
     384           0 :                 BREAK;
     385             :         }
     386             : 
     387           0 :         E2 = L_deposit_l( 1 );
     388           0 :         FOR( i = 0; i < L_FRAME; i++ )
     389             :         {
     390           0 :             E2 = L_mac0_sat( E2, ptr[i], ptr[i] ); /*2*Q_exc */
     391             :         }
     392             : 
     393           0 :         exp_E3 = norm_l( E3 );
     394           0 :         frac_E3 = extract_h( L_shl( E3, exp_E3 ) );
     395           0 :         exp_E3 = sub( 30, add( exp_E3, 2 * ( *Q_exc ) ) );
     396             : 
     397           0 :         exp_E2 = norm_l( E2 );
     398           0 :         frac_E2 = round_fx_sat( L_shl_sat( E2, exp_E2 ) );
     399           0 :         exp_E2 = sub( 30, add( exp_E2, shl( ( *Q_exc ), 1 ) ) );
     400             : 
     401           0 :         scale = shr( sub( frac_E3, frac_E2 ), 15 );
     402           0 :         frac_E2 = shl( frac_E2, scale );
     403           0 :         exp_E2 = sub( exp_E2, scale );
     404             : 
     405           0 :         tmp = div_s( frac_E2, frac_E3 );
     406           0 :         exp = sub( exp_E2, exp_E3 );
     407             : 
     408           0 :         L_tmp1 = Isqrt_lc( L_deposit_h( tmp ), &exp ); /*Q(31-exp) */
     409             : 
     410           0 :         FOR( i = 0; i < L_FRAME; i++ )
     411             :         {
     412           0 :             L_tmp = Mult_32_16( L_tmp1, ptr[i] );     /*Q(16-exp+Q_exc) */
     413           0 :             ptr[i] = round_fx( L_shl( L_tmp, exp ) ); /*Q_exc */
     414           0 :             move16();
     415             :         }
     416             :     }
     417             : 
     418           0 :     Copy( ptr, exc_nelp, L_FRAME ); /*Q_exc */
     419           0 :     set16_fx( gain_buf, 0, NB_SUBFR16k );
     420           0 :     return;
     421             : }

Generated by: LCOV version 1.14