LCOV - code coverage report
Current view: top level - lib_lc3plus - plc_apply_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 144 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.5.1                               *
       3             : *              Low Complexity Communication Codec Plus (LC3plus)              *
       4             : *                                                                             *
       5             : * Copyright licence is solely granted through ETSI Intellectual Property      *
       6             : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
       7             : * estoppel or otherwise.                                                      *
       8             : ******************************************************************************/
       9             : 
      10             : #include "defines.h"
      11             : #include "constants.h"
      12             : #include "functions.h"
      13             : 
      14           0 : void processPLCapply_fx(
      15             :     Word16 *concealMethod, 
      16             :     Word16 nbLostFramesInRow, Word16 bfi, Word16 prev_bfi,
      17             :                         Word16 frame_length, Word16 la_zeroes,
      18             : #ifdef ENABLE_HR_MODE
      19             :                         const Word32 w[],
      20             : #else
      21             :                         const Word16 w[],
      22             : #endif
      23             :                         Word16 x_fx[], Word16 ola_mem[],
      24             :                         Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[],
      25             :                         Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, Word16 *damping, Word16 old_pitch_int,
      26             :                         Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, Word16 frame_dms, AplcSetup *plcAd,
      27             :                         Word8 *scratchBuffer
      28             : #ifdef ENABLE_HR_MODE
      29             :                         , Word16 hrmode
      30             : #endif
      31             :                         , Word32 rel_pitch_change
      32             :                         , Word16 *alpha_type_2_table
      33             :                         )
      34             : {
      35             :     Dyn_Mem_Deluxe_In(
      36             :         Counter i;
      37             :         Word32 *d2_fx;
      38             :         Word32 *q_old_d_fx32;
      39             :         Word32 *r_fx;
      40             :         Word32 *tdc_A_32;
      41             :         Word16  d2_fx_exp;
      42             :         Word16  r_fx_exp;
      43             :         Word16  Q_syn;
      44             :         Word8 * buffer_perBandEnergy, *buffer_preEmphasis, *buffer_InverseODFT, *buffer_Levinson,
      45             :             *buffer_tdac, *buffer_phecu;
      46             :         Word16        y_e;             /*exponent of L_ecu_rec */
      47             :         Word16        tmp_is_trans[2]; /* may be  changed to a single variable */
      48             :         Word16        env_stab;
      49             :         
      50             :         Word16        n_bands, prev_bfi_plc2;
      51             :         const Word16 *band_offsets;
      52             :         Word32 *      L_ecu_rec; /*  local xtda  output is MAX_LEN -> input  buffer,
      53             :                                     as  tmp buffer for w32 fft MAX_LPROT */
      54             :     );
      55           0 :     Word16 consecutiveLostThreshold = 0;
      56             : 
      57             : #ifndef ENABLE_HR_MODE
      58             :     UNUSED(rel_pitch_change);
      59             : #endif
      60             : 
      61             :     Word16 thresh_tdc_cnt;
      62             :     Word16 thresh_ns_cnt;
      63             :     Word16 thresh_tdc_ns_cnt;
      64             : 
      65           0 :     band_offsets = NULL;
      66             : 
      67           0 :     d2_fx        = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_BANDS_NUMBER_PLC */
      68           0 :     q_old_d_fx32 = (Word32 *)scratchAlign(d2_fx, sizeof(*d2_fx) * MAX_BANDS_NUMBER_PLC); /* Size = 4 * MAX_BW */
      69           0 :     r_fx         = (Word32 *)scratchAlign(d2_fx, sizeof(*d2_fx) * MAX_BANDS_NUMBER_PLC); /* Size = 4 * (M + 1) */
      70           0 :     tdc_A_32     = (Word32 *)scratchAlign(r_fx, sizeof(*r_fx) * (M + 1));                /* Size = 4 * (M + 1) */
      71             : 
      72           0 :     L_ecu_rec = (Word32 *)scratchAlign(tdc_A_32, sizeof(*tdc_A_32) * (M + 1)); /* Size = 4 * MAX_LPROT bytes */
      73             : 
      74           0 :     buffer_perBandEnergy =
      75           0 :         (Word8 *)scratchAlign(q_old_d_fx32, sizeof(*q_old_d_fx32) * (MAX_LEN)); /* Size = 2 * MAX_BANDS_NUMBER_PLC */
      76           0 :     buffer_preEmphasis =
      77           0 :         (Word8 *)scratchAlign(tdc_A_32, sizeof(*tdc_A_32) * (M + 1)); /* Size = 2 * MAX_BANDS_NUMBER_PLC */
      78           0 :     buffer_InverseODFT = buffer_preEmphasis;                          /* Size = 640 bytes */
      79           0 :     buffer_Levinson    = buffer_preEmphasis;                          /* Size = 4 * (M + 1) */
      80             : 
      81           0 :     buffer_tdac  = scratchBuffer; /* Size = 2 * MAX_LEN bytes */
      82           0 :     buffer_phecu = scratchBuffer; /* Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */
      83             :     /* Buffers overlap since they are not used at once */
      84             : 
      85             :     
      86             :     UNUSED(ns_cum_alpha);
      87             :     UNUSED(ns_seed);
      88             : 
      89             :     /* Apply/Prepare PLC in bfi-case */
      90           0 :     IF (sub(bfi, 1) == 0)
      91             :     {
      92           0 :             SWITCH(frame_dms)
      93             :             {
      94           0 :                 case 25: 
      95           0 :                     consecutiveLostThreshold  = 16;
      96           0 :                     thresh_tdc_cnt = THRESH_025_DMS_TDC_CNT;
      97           0 :                     thresh_ns_cnt = THRESH_025_DMS_NS_CNT;
      98           0 :                     thresh_tdc_ns_cnt =  THRESH_025_DMS_TDC_NS_CNT;                  
      99           0 :                     break;
     100           0 :                 case 50: consecutiveLostThreshold  = 8;  
     101           0 :                     thresh_tdc_cnt = THRESH_050_DMS_TDC_CNT;
     102           0 :                     thresh_ns_cnt = THRESH_050_DMS_NS_CNT;
     103           0 :                     thresh_tdc_ns_cnt =  THRESH_050_DMS_TDC_NS_CNT;                
     104           0 :                     break;
     105           0 :                 case 75: consecutiveLostThreshold  = 6;
     106           0 :                     thresh_tdc_cnt = THRESH_075_DMS_TDC_CNT;
     107           0 :                     thresh_ns_cnt = THRESH_075_DMS_NS_CNT;
     108           0 :                     thresh_tdc_ns_cnt =  THRESH_075_DMS_TDC_NS_CNT;                  
     109           0 :                     break;
     110           0 :                 case 100: consecutiveLostThreshold = 4;  
     111           0 :                     thresh_tdc_cnt = THRESH_100_DMS_TDC_CNT;
     112           0 :                     thresh_ns_cnt = THRESH_100_DMS_NS_CNT;
     113           0 :                     thresh_tdc_ns_cnt =  THRESH_100_DMS_TDC_NS_CNT;
     114           0 :                     break;
     115           0 :                 default: assert(0);
     116             :             }
     117             : 
     118           0 :             IF (sub(fs_idx, 2) == 0 || sub(fs_idx, 4) >= 0)
     119             :             {
     120           0 :                 if (sub(plcAd->longterm_counter_plcTdc, thresh_tdc_cnt) < 0){
     121           0 :                     plcAd->plc_fadeout_type = 1;
     122             :                 }
     123           0 :                 else if (sub(plcAd->longterm_counter_plcNsAdv, thresh_ns_cnt) < 0){
     124           0 :                     plcAd->plc_fadeout_type = 1;
     125             :                 }
     126           0 :                 else if (sub(plcAd->longterm_counter_plcTdc + plcAd->longterm_counter_plcNsAdv, thresh_tdc_ns_cnt) < 0){
     127           0 :                     plcAd->plc_fadeout_type = 1;
     128             :                 }
     129             :                 else {
     130           0 :                     plcAd->plc_fadeout_type = 0;
     131             :                 }
     132             : 
     133           0 :                 env_stab = norm_s(plcAd->longterm_analysis_counter_max);           
     134           0 :                 IF(sub(shl_pos(plcAd->overall_counter, env_stab), mult(shl_pos(plcAd->longterm_analysis_counter_max, env_stab), PLC_LONGTERM_ANALYSIS_STARTUP_FILL)) < 0)
     135             :                 {
     136           0 :                     plcAd->plc_fadeout_type = 0;
     137             :                 }
     138             : #ifdef ENABLE_HR_MODE
     139           0 :             IF (L_sub(rel_pitch_change,REL_PITCH_THRESH) > 0 && sub(hrmode,1) == 0 && (sub(frame_dms,50) == 0 || sub(frame_dms,25) == 0)){
     140           0 :                 plcAd->plc_fadeout_type = 2;move16();
     141             :             } ELSE 
     142             : #endif
     143           0 :                 IF((sub(nbLostFramesInRow, consecutiveLostThreshold) < 0) && (*concealMethod != LC3_CON_TEC_PHASE_ECU))
     144             :                 {
     145           0 :                     plcAd->plc_fadeout_type = 0;
     146             :                 }
     147             :             } ELSE {
     148           0 :                 plcAd->plc_fadeout_type = 0; /*fs_idx == 0,1,3 */
     149             :             } 
     150             : 
     151           0 :         SWITCH (*concealMethod)
     152             :         {
     153           0 :         case LC3_CON_TEC_PHASE_ECU:
     154           0 :             ASSERT(frame_dms == 100);
     155             :             /* call phaseEcu */
     156           0 :             env_stab        = 32767; move16();                 /* 1.0=stable , 0.0=dynamic Q15*/
     157           0 :             tmp_is_trans[0] = plcAd->PhECU_short_flag_prev; move16();
     158           0 :             tmp_is_trans[1] = plcAd->PhECU_short_flag_prev; move16();
     159             :             
     160           0 :             ASSERT(prev_bfi == 0 || prev_bfi == 1|| prev_bfi == 2);  /*PC prev_bfi has three states */
     161           0 :             prev_bfi_plc2 = prev_bfi; move16();
     162           0 :             if (sub(prev_bfi_plc2, 2) == 0) 
     163             :             {
     164           0 :                prev_bfi_plc2 = 0; move16();
     165             :             }  
     166             : 
     167           0 :             ASSERT(prev_bfi_plc2 == 0 || prev_bfi_plc2 == 1); /*PhEcu does not accept prev_bfi == 2 */
     168           0 :             IF(prev_bfi_plc2 == 0)
     169             :             { /* convert pitch lag info at current fs to a normalized fractional bin-frequency   */
     170           0 :                plcAd->PhECU_f0hzLtpBinQ7 = plc_phEcuSetF0Hz_fx(fs_idx, old_pitch_int, old_pitch_fr);  move16();
     171             : 
     172             : 
     173             : 
     174             :                /* first bfi frame calc decoded pcm  energy 16,16 ms, in 26 ms buffer separated by 10 ms*/
     175             :                 
     176             :                {   /* compute energy normalization needed for concealment method 2  Xavg  and transient analysis */
     177             :                     
     178             :                    /* left   */                
     179           0 :                   processPLCUpdateXFP_w_E_hist_fx(0, 0,
     180           0 :                      &(plcAd->x_old_tot_fx[ sub(plcAd->max_len_pcm_plc , add(num_FsByResQ0[fs_idx],rectLengthTab[fs_idx]  )) ]), plcAd->q_fx_old_exp,0,  
     181             :                   
     182             :                      fs_idx,
     183             :                      &plcAd->PhECU_L_oold_xfp_w_E_fx, &plcAd->PhECU_oold_xfp_w_E_exp_fx,
     184             :                      &plcAd->PhECU_L_old_xfp_w_E_fx, &plcAd->PhECU_old_xfp_w_E_exp_fx,
     185             :                      &plcAd->PhECU_oold_Ltot_exp_fx, &plcAd->PhECU_old_Ltot_exp_fx);
     186             : 
     187             :                   /* right  */
     188           0 :                   processPLCUpdateXFP_w_E_hist_fx(0, 0, plcAd->PhECU_xfp_fx, plcAd->PhECU_xfp_exp_fx, 
     189           0 :                      plcAd->PhECU_margin_xfp, fs_idx,
     190             :                      &plcAd->PhECU_L_oold_xfp_w_E_fx, &plcAd->PhECU_oold_xfp_w_E_exp_fx,
     191             :                      &plcAd->PhECU_L_old_xfp_w_E_fx, &plcAd->PhECU_old_xfp_w_E_exp_fx,
     192             :                      &plcAd->PhECU_oold_Ltot_exp_fx, &plcAd->PhECU_old_Ltot_exp_fx);               
     193             :                }
     194             :             }
     195             : 
     196           0 :             hq_phase_ecu_fx(
     197           0 :                 plcAd->PhECU_xfp_fx,       /* i :  only valid first Bfi frame , buffer of previous synt signal length */
     198             :                 L_ecu_rec,                 /* o  : reconstructed frame in folded tda domain xtda  Word32  Q x     */
     199             :                 &plcAd->PhECU_time_offs,   /* i/o: Sample offset for consecutive frame losses*/
     200             :                 plcAd->PhECU_X_sav_fx,     /* i(prev_bfi==1)/o(prev_bfi==0): Stored Complex spectrum of prototype frame */
     201             :                 &plcAd->PhECU_X_savQ_fx,   /* i/o: Q value of stored spectrum                */
     202             :                 &plcAd->PhECU_num_plocs,   /* i/o: Number of identified peaks                */
     203             :                 plcAd->PhECU_plocs,        /* i/o: Peak locations   Q0                         */
     204             :                 plcAd->PhECU_f0est,        /* i/o: Interpolated peak locations           Q16 */
     205             :                 env_stab,                  /* i  : Envelope stability parameter              */
     206           0 :                 plcAd->PhECU_f0hzLtpBinQ7, /* i:  LTP bin frequency in normalized Hz  Q7 */
     207           0 :                 plcAd->norm_corrQ15_fx,    /* i : correlation for lag at f0hzLtpBinQ7 */
     208             :                 prev_bfi_plc2,                  /* i   : indicating burst frame error             */
     209             :                 tmp_is_trans,              /* i   : flags indicating previous transient frames */
     210           0 :                 plcAd->PhECU_mag_chg_1st,  /* i/o: per band magnitude modifier for transients*/
     211             :                 NULL,                      /*  o: dbg per band magnitude modifier, incl. burst attenuation   */
     212           0 :                 plcAd->PhECU_Xavg,         /* i/o: Frequency group average gain to fade to   */
     213             :                 &plcAd->PhECU_beta_mute,   /* o   : Factor for long-term mute                */
     214             :                 fs_idx,                    /* i  : Encoded bandwidth   "nb(0),WB,sWB,WB,FB"  */
     215             :                 frame_length,              /* i   : frame length                             */
     216             :                 NULL ,                      /* o  :  seed synch dbg                          */ 
     217             :                 NULL ,                      /* o  :  evolved Spectrum   dbg                  */ 
     218           0 :                 plcAd->PhECU_t_adv,       /* i  : time adjustment excluding time_offs         */
     219             :                  PhECU_wins[fs_idx][2], /* i:  2 ms initial part pre_tda = mdct-ana */
     220             :                  PhECU_wins[fs_idx][1], /* i:  16 ms pretda combined part  IWHR+MDCT-ana  */
     221             :                 PhECU_wins[fs_idx][0], 
     222           0 :                 plcAd->PhECU_xfp_exp_fx, 
     223           0 :                 plcAd->max_lprot, 
     224           0 :                 plcAd->max_plocs,
     225           0 :                 plcAd->PhECU_L_oold_xfp_w_E_fx,plcAd->PhECU_oold_xfp_w_E_exp_fx, plcAd->PhECU_oold_Ltot_exp_fx,
     226           0 :                 plcAd->PhECU_oold_grp_shape_fx,
     227           0 :                 plcAd->PhECU_L_old_xfp_w_E_fx,plcAd->PhECU_old_xfp_w_E_exp_fx, plcAd->PhECU_old_Ltot_exp_fx,
     228           0 :                 plcAd->PhECU_old_grp_shape_fx,
     229           0 :                 plcAd->PhECU_margin_xfp,
     230           0 :                 plcAd->plc_fadeout_type  ,                          /* i  : fadeout scheme  */
     231             :                                 &(plcAd->PhECU_nonpure_tone_flag),  /* i/o : non-pure single tone indicator state */
     232             :                 buffer_phecu);
     233             :  
     234           0 :             y_e = 18;  move16();  /*  the  fixed exponent (exp)  from Lecu_rec  from PhaseECU is 18    */
     235             : 
     236           0 :             Processing_ITDA_WIN_OLA(
     237             :                 L_ecu_rec,   /* i:     X_TDA buffer data   =  "y"  DCT-IV output */
     238             :                 &y_e,        /* i/o:    x_tda exponent  "y_e"  */
     239             :                 w,           /* i:     window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */
     240             :                 ola_mem,     /* i/o:  overlap add memory */
     241             :                 ola_mem_exp, /* i/o:  overlap add exponent */
     242             :                 x_fx,        /* o:    time signal out */
     243           0 :                 LowDelayShapes_n960_len[fs_idx],                         /* i:   window length */
     244             :                 frame_length,                                            /* i:   block size */
     245           0 :                 sub(frame_length, LowDelayShapes_n960_la_zeroes[fs_idx]) /* i:   overlap add buffer size */
     246             :             ); 
     247           0 :            *q_fx_exp = y_e;  move16();   /*  assign updated Q */
     248           0 :             BREAK;
     249             : 
     250           0 :         case LC3_CON_TEC_TDPLC:
     251           0 :             IF (sub(nbLostFramesInRow, 1) == 0)
     252             :             {
     253           0 :                 plcAd->tdc_fract = old_pitch_fr; move16();
     254           0 :                 n_bands          = s_min(frame_length, MAX_BANDS_NUMBER_PLC);
     255           0 :                 SWITCH (frame_dms)
     256             :                 {
     257           0 :                 case 25:
     258           0 :                     band_offsets = bands_offset_lin_2_5ms[fs_idx];  move16();
     259           0 :                     IF (sub(fs_idx, 4) == 0)
     260             :                     {
     261           0 :                         n_bands = 60;  move16();
     262             :                     }
     263           0 :                     BREAK;
     264           0 :                 case 50:
     265           0 :                     band_offsets = bands_offset_lin_5ms[fs_idx]; move16();
     266           0 :                     IF (sub(fs_idx, 2) == 0)
     267             :                     {
     268           0 :                         n_bands = 40; move16();
     269             :                     }
     270           0 :                     BREAK;
     271           0 :                 case 75:
     272           0 :                     band_offsets = bands_offset_lin_7_5ms[fs_idx];  move16();
     273             : #ifdef ENABLE_HR_MODE
     274           0 :                     IF (sub(fs_idx, 5) != 0)
     275             :                     {
     276             : #endif
     277           0 :                         IF (sub(fs_idx, 3) != 0)
     278             :                         {
     279           0 :                             n_bands = 60;  move16();
     280             :                         }
     281             : #ifdef ENABLE_HR_MODE
     282             :                     }
     283             : #endif
     284           0 :                     BREAK;
     285           0 :                 case 100:
     286           0 :                     band_offsets = bands_offset_lin[fs_idx]; move16();
     287           0 :                     BREAK;
     288             :                 }
     289             : 
     290           0 :                 FOR (i = 0; i < yLen; i++)
     291             :                 {
     292           0 :                     q_old_d_fx32[i] = L_deposit_h(q_old_d_fx[i]);
     293             :                 }
     294             : 
     295             :                 /* LPC Analysis */
     296             :                 /* calculate per band energy*/
     297           0 :                 processPerBandEnergy_fx(d2_fx, &d2_fx_exp, q_old_d_fx32, *q_old_fx_exp, band_offsets, fs_idx, n_bands,
     298             :                                         1, frame_dms, buffer_perBandEnergy
     299             : #ifdef ENABLE_HR_MODE
     300             :                                         , hrmode
     301             : #endif
     302             :                 );
     303             : 
     304             :                 /* calculate pre-emphasis */
     305           0 :                 processPreEmphasis_fx(d2_fx, &d2_fx_exp, fs_idx, n_bands, frame_dms, buffer_preEmphasis);
     306             : 
     307             :                 /* inverse ODFT */
     308           0 :                 processInverseODFT_fx(r_fx, &r_fx_exp, d2_fx, d2_fx_exp, n_bands, plcAd->tdc_lpc_order, buffer_InverseODFT);
     309             : 
     310             :                 /* lag windowing */
     311           0 :                 processLagwin_fx(r_fx, lag_win[fs_idx], plcAd->tdc_lpc_order);
     312             : 
     313             :                 /* Levinson Durbin */
     314           0 :                 processLevinson_fx(tdc_A_32, r_fx, plcAd->tdc_lpc_order, NULL, NULL, buffer_Levinson);
     315             : 
     316             :                 /* 32Q27 -> 16Qx */
     317           0 :                 processPLCLpcScaling_fx(tdc_A_32, plcAd->tdc_A, add(plcAd->tdc_lpc_order, 1));
     318             :             }
     319             :             
     320             :             /* call TD-PLC */
     321             :             /* Q_syn = plcAd->q_fx_old_exp; */ /* makes q_fx_old_exp
     322             :                available in processTimeDomainConcealment_Apply_fx() for
     323             :                debugging */
     324           0 :             processTimeDomainConcealment_Apply_fx(
     325           0 :                 old_pitch_int, plcAd->tdc_preemph_fac, plcAd->tdc_A, plcAd->tdc_lpc_order, plcAd->x_old_tot_fx, frame_length, frame_dms,
     326           0 :                 fs_idx, nbLostFramesInRow, sub(frame_length, la_zeroes), plcAd->stab_fac, &plcAd->tdc_fract,
     327             :                 &plcAd->tdc_seed, 
     328             :                 &plcAd->tdc_gain_c, x_fx, &Q_syn, damping,
     329           0 :                 plcAd->max_len_pcm_plc,
     330           0 :                 plcAd->harmonicBuf_fx, plcAd->synthHist_fx, &plcAd->harmonicBuf_Q, scratchBuffer
     331           0 :                 , plcAd->plc_fadeout_type
     332             :                 , alpha_type_2_table
     333             : );
     334             :                 
     335             :             /* exponent of TD-PLC output */
     336           0 :             Q_syn     = add(Q_syn, sub(15, plcAd->q_fx_old_exp));
     337           0 :             *q_fx_exp = sub(15, Q_syn); move16();
     338             : 
     339             :             /* TDAC */
     340           0 :             processTdac_fx(ola_mem, ola_mem_exp, x_fx, *q_fx_exp, w, la_zeroes, frame_length, buffer_tdac);
     341           0 :             BREAK;
     342             : 
     343           0 :         case LC3_CON_TEC_NS_ADV:
     344           0 :             *q_fx_exp = *q_old_fx_exp; move16();
     345             : 
     346             :             /* call Noise Substitution */
     347           0 :             processPLCNoiseSubstitution_fx(q_d_fx, q_old_d_fx, yLen);
     348             :             
     349           0 :             BREAK;
     350           0 :         default: ASSERT(!"Unsupported PLC method!");
     351             :         }
     352           0 :     }
     353             : 
     354             :     Dyn_Mem_Deluxe_Out();
     355           0 : }
     356             : 
     357             : 

Generated by: LCOV version 1.14