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 "cnst.h"    /* Common constants                     */
       8             : #include "cnst.h"
       9             : #include "rom_com.h"     /* Common constants                       */
      10             : #include "prot_fx.h"     /* Function prototypes                    */
      11             : #include "prot_fx_enc.h" /* Function prototypes                    */
      12             : #include "basop_util.h"  /* Function prototypes                    */
      13             : 
      14             : 
      15             : /*---------------------------------------------------------------------*
      16             :  * hf_cod_init()
      17             :  *
      18             :  *
      19             :  *---------------------------------------------------------------------*/
      20             : 
      21           3 : void hf_cod_init_fx(
      22             :     Word16 *mem_hp400_enc,  /* o: memory of hp 400 Hz filter   */
      23             :     Word16 *mem_hf1_enc,    /* o: HF band-pass filter memory   */
      24             :     Word16 *mem_syn_hf_enc, /* o: HF synthesis memory          */
      25             :     Word16 *mem_hf2_enc,    /* o: HF band-pass filter memory   */
      26             :     Word16 *gain_alpha_fx   /* o: smoothing gain for transitions between active and inactive frames */
      27             : )
      28             : {
      29           3 :     set16_fx( mem_hp400_enc, 0, 6 );
      30           3 :     set16_fx( mem_hf1_enc, 0, L_FIR - 1 );
      31           3 :     set16_fx( mem_syn_hf_enc, 0, M );
      32           3 :     set16_fx( mem_hf2_enc, 0, L_FIR - 1 );
      33             : 
      34           3 :     *gain_alpha_fx = 16384;
      35           3 :     move16();
      36             : 
      37           3 :     return;
      38             : }
      39             : 
      40             : /*---------------------------------------------------------------------*
      41             :  * hf_cod()
      42             :  *
      43             :  *
      44             :  *---------------------------------------------------------------------*/
      45             : 
      46           0 : void hf_cod_fx(
      47             :     const Word32 core_brate_fx, /* i  : core bitrate                 */
      48             :     const Word16 *speech16k_fx, /* i  : original speech at 16 kHz    */
      49             :     const Word16 Aq_fx[],       /* i  : quantized Aq                 */
      50             :     const Word16 exc_fx[],      /* i  : excitation at 12.8 kHz       */
      51             :     Word16 synth_fx[],          /* i  : 12.8kHz synthesis signal     */
      52             :     Word16 *seed2_enc_fx,       /* i/o: random seed for HF noise gen */
      53             :     Word16 *mem_hp400_enc_fx,   /* i/o: memory of hp 400 Hz filter   */
      54             :     Word16 *mem_syn_hf_enc_fx,  /* i/o: HF synthesis memory          */
      55             :     Word16 *mem_hf1_enc_fx,     /* i/o: HF band-pass filter memory   */
      56             :     Word16 *mem_hf2_enc_fx,     /* i/o: HF band-pass filter memory   */
      57             :     const Word16 dtxHangoverCount_fx,
      58             :     Word16 *gain_alpha_fx, /* i/o: smoothing gain for transitions between active and inactive frames */
      59             :     Word16 *hf_gain_fx,    /* o  :  HF gain to be transmitted to decoder */
      60             :     Word16 Q_exc,
      61             :     Word16 Q_syn )
      62             : {
      63             :     /*------------------------Scaling-------------------------------------------------
      64             :     speech16k - Q0
      65             :     Aq - Q12
      66             :     exc - Q_exc
      67             :     synth - Q_syn
      68             :     mem_hp400_enc - Q_syn
      69             :     mem_syn_hf_enc - Q0
      70             :     mem_hf1_enc - Q0
      71             :     mem_hf2_enc - Q0
      72             :     gain_alpha_fx - Q14
      73             :     ener - all dynamic
      74             :     fac, scale - Q12
      75             :     Ap - Q12
      76             :     HF_SP - Q0
      77             :     ---------------------------------------------------------------------------------*/
      78             : 
      79             :     Word16 i, q1, q2, sign;
      80             :     Word16 shift;
      81             :     Word16 ener_hf_fx, ener_exc_fx, ener_input_fx, fac_fx, tmp_fx, ener_fx, scale_fx;
      82             :     Word16 Ap_fx[M + 1];
      83             :     Word16 HF_SP_fx[L_SUBFR16k];
      84             :     Word16 HF_est_gain_fx, HF_calc_gain_fx, HF_corr_gain_fx, HF_gain_ind_fx;
      85             :     Word32 dist_min_fx, dist_fx;
      86             :     Word16 HF_fx[L_SUBFR16k], HF_syn_fx[L_SUBFR16k]; /* o  : HF excitation                */
      87             :     Word32 L_tmp;
      88             :     Word16 *pt1;
      89             :     const Word16 *pt2;
      90             : 
      91             :     /* Original speech signal as reference for high band gain quantisation */
      92           0 :     Copy( speech16k_fx, HF_SP_fx, L_SUBFR16k );
      93             : 
      94             :     /*-----------------------------------------------------------------*
      95             :      * generate white noise vector
      96             :      *-----------------------------------------------------------------*/
      97             : 
      98           0 :     Random_Fill( seed2_enc_fx, L_SUBFR16k, HF_fx, 3 ); /*Q(-3) */
      99             : 
     100             :     /*-----------------------------------------------------------------*
     101             :      * calculate energy scaling factor so that white noise would have the
     102             :      * same energy as exc12k8
     103             :      *-----------------------------------------------------------------*/
     104             : 
     105           0 :     ener_exc_fx = dot_prod_satcontr( exc_fx, exc_fx, Q_exc, Q_exc, &q1, L_SUBFR );
     106           0 :     ener_hf_fx = dot_prod_satcontr( HF_fx, HF_fx, -3, -3, &q2, L_SUBFR16k );
     107             : 
     108           0 :     scale_fx = div_s( shl( 1, 14 ), ener_exc_fx );                     /*Q(29-q1) */
     109           0 :     L_tmp = L_mult( ener_hf_fx, scale_fx );                            /*30-q1+q2 */
     110           0 :     q2 = sub( q1, q2 );                                                /*30-q2 */
     111           0 :     scale_fx = round_fx( Isqrt( L_shl_sat( L_tmp, sub( q2, 26 ) ) ) ); /*Q13 */
     112             : 
     113           0 :     pt1 = HF_fx;
     114           0 :     FOR( i = 0; i < L_SUBFR16k; i++ )
     115             :     {
     116           0 :         *pt1 = round_fx( L_shl( L_mult( ( *pt1 ), scale_fx ), 5 ) ); /*Q0 */
     117           0 :         pt1++;
     118             :     }
     119             : 
     120             :     /*-----------------------------------------------------------------*
     121             :      * calculate energy scaling factor to respect tilt of synth12k8
     122             :      * (tilt: 1=voiced, -1=unvoiced)
     123             :      *-----------------------------------------------------------------*/
     124             : 
     125           0 :     hp400_12k8_fx( synth_fx, L_SUBFR, mem_hp400_enc_fx ); /*synth_fx: Q(Q_syn-4) */
     126             : 
     127           0 :     ener_fx = dot_prod_satcontr( &synth_fx[1], &synth_fx[1], sub( Q_syn, 4 ), sub( Q_syn, 4 ), &q1, sub( L_SUBFR, 1 ) );
     128           0 :     tmp_fx = dot_prod_satcontr( &synth_fx[1], synth_fx, sub( Q_syn, 4 ), sub( Q_syn, 4 ), &q2, sub( L_SUBFR, 1 ) );
     129             : 
     130           0 :     IF( GE_16( abs_s( tmp_fx ), ener_fx ) )
     131             :     {
     132           0 :         tmp_fx = shr( tmp_fx, 1 );
     133           0 :         q2 = sub( q2, 1 );
     134             :     }
     135             : 
     136           0 :     sign = 0;
     137           0 :     move16();
     138           0 :     IF( tmp_fx < 0 )
     139             :     {
     140           0 :         tmp_fx = abs_s( tmp_fx );
     141           0 :         sign = 1;
     142           0 :         move16();
     143             :     }
     144             : 
     145           0 :     fac_fx = div_s( tmp_fx, ener_fx ); /*Q(15+q2-q1) */
     146           0 :     shift = sub( q1, add( q2, 5 ) );
     147           0 :     fac_fx = shl( fac_fx, shift ); /*Q10 */
     148           0 :     IF( sign )
     149             :     {
     150           0 :         fac_fx = s_xor( fac_fx, -1 );
     151             :     }
     152             : 
     153           0 :     HF_est_gain_fx = sub( 1024, fac_fx ); /*Q12 */
     154             : 
     155           0 :     test();
     156           0 :     IF( EQ_32( core_brate_fx, SID_1k75 ) || core_brate_fx == FRAME_NO_DATA )
     157             :     {
     158           0 :         HF_est_gain_fx = round_fx( L_shl( L_mult( HF_est_gain_fx, 20480 ), 1 ) ); /*Q10 */
     159             :     }
     160             : 
     161           0 :     HF_est_gain_fx = s_max( HF_est_gain_fx, 102 );
     162           0 :     HF_est_gain_fx = s_min( HF_est_gain_fx, 1024 );
     163             : 
     164             :     /*-----------------------------------------------------------------*
     165             :      * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz
     166             :      *-----------------------------------------------------------------*/
     167             : 
     168           0 :     weight_a_lc_fx( Aq_fx, Ap_fx, Gamma_19661_Tbl_fx, M );
     169           0 :     Syn_filt_s( 0, Ap_fx, M, HF_fx, HF_syn_fx, L_SUBFR16k, mem_syn_hf_enc_fx, 1 ); /*Q0 */
     170             : 
     171             :     /*-----------------------------------------------------------------*
     172             :      * high pass filtering (0.9375ms of delay = 15 samples@16k)
     173             :      *-----------------------------------------------------------------*/
     174             : 
     175           0 :     fir_fx( HF_syn_fx, fir_6k_8k_fx, HF_syn_fx, mem_hf1_enc_fx, L_SUBFR16k, L_FIR - 1, 1, 0 );
     176           0 :     fir_fx( HF_SP_fx, fir_6k_8k_fx, HF_SP_fx, mem_hf2_enc_fx, L_SUBFR16k, L_FIR - 1, 1, 0 );
     177             : 
     178             :     /* check the gain difference */
     179             : 
     180           0 :     ener_hf_fx = dot_prod_satcontr( HF_syn_fx, HF_syn_fx, 0, 0, &q2, L_SUBFR16k );
     181           0 :     ener_input_fx = dot_prod_satcontr( HF_SP_fx, HF_SP_fx, 0, 0, &q1, L_SUBFR16k );
     182             : 
     183           0 :     HF_calc_gain_fx = div_s( shl( 1, 14 ), ener_input_fx );                       /*Q(29-q1) */
     184           0 :     L_tmp = L_mult( ener_hf_fx, HF_calc_gain_fx );                                /*30-q1+q2 */
     185           0 :     q2 = sub( q1, q2 );                                                           /*30-q2 */
     186           0 :     HF_calc_gain_fx = round_fx_sat( Isqrt( L_shl_sat( L_tmp, sub( q2, 20 ) ) ) ); /*Q10  */
     187             : 
     188             :     /* set energy of HF synthesis to energy of original HF:
     189             :        cross-fade between HF levels in active and inactive frame in hangover period */
     190             : 
     191           0 :     IF( GT_16( 4, dtxHangoverCount_fx ) )
     192             :     {
     193           0 :         *gain_alpha_fx = 16384;
     194           0 :         move16();
     195             :     }
     196             :     ELSE
     197             :     {
     198           0 :         L_tmp = L_shl( L_mult( sub( 10, dtxHangoverCount_fx ), 4681 ), 15 ); /*Q31 */
     199           0 :         L_tmp = Mult_32_16( L_tmp, *gain_alpha_fx );                         /*Q30 */
     200           0 :         *gain_alpha_fx = round_fx( L_tmp );                                  /*Q14 */
     201             :     }
     202           0 :     L_tmp = L_mult( sub( 16384, *gain_alpha_fx ), HF_est_gain_fx ); /*Q25 */
     203           0 :     L_tmp = L_mac( L_tmp, *gain_alpha_fx, HF_calc_gain_fx );        /*Q25  */
     204           0 :     IF( GE_32( L_tmp, 67108863 ) )
     205             :     {
     206           0 :         L_tmp = 67108863;
     207           0 :         move32();
     208             :     }
     209           0 :     L_tmp = L_shl( L_tmp, 5 );
     210           0 :     HF_corr_gain_fx = extract_h( L_tmp ); /*Q14; HF_corr_gain_fx/2 in Q15 */
     211             : 
     212             :     /* Quantize the correction gain */
     213           0 :     dist_min_fx = 2147483647;
     214           0 :     move32();
     215           0 :     HF_gain_ind_fx = 0;
     216           0 :     move16();
     217           0 :     pt2 = HP_gain_fx;
     218           0 :     FOR( i = 0; i < 16; i++ )
     219             :     {
     220           0 :         dist_fx = L_mult( sub( HF_corr_gain_fx, *pt2 ), sub( HF_corr_gain_fx, *pt2 ) );
     221           0 :         pt2++;
     222           0 :         IF( GT_32( dist_min_fx, dist_fx ) )
     223             :         {
     224           0 :             dist_min_fx = L_add( dist_fx, 0 );
     225           0 :             HF_gain_ind_fx = i;
     226           0 :             move16();
     227             :         }
     228             :     }
     229           0 :     *hf_gain_fx = HF_gain_ind_fx;
     230           0 :     move16();
     231             : 
     232           0 :     return;
     233             : }
       |