LCOV - code coverage report
Current view: top level - lib_lc3plus - plc_main.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 113 0.0 %
Date: 2025-05-23 08:37:30 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 "options.h"
      11             : #include "wmc_auto.h"
      12             : #include "functions.h"
      13             : 
      14           0 : void processPlcMain_fl(LC3_FLOAT *q_d_fl_c, LC3_FLOAT *syntM_fl_c, LC3PLUS_Dec* decoder, DecSetup* h_DecSetup, LC3_INT bfi,
      15             :                PlcAdvSetup *PlcAdvSetup, PlcSetup *PlcSetup, LC3_INT plcMeth, LC3_INT ltpf_pitch_int, LC3_INT ltpf_pitch_fr,
      16             :                LC3_INT tilt, const LC3_INT *bands_offset, LC3_INT bands_number, const LC3_INT *bands_offsetPLC,
      17             :                LC3_INT n_bandsPLC, LC3_INT16 hrmode, pcState *statePC
      18             : )
      19             : {
      20             :     LC3_FLOAT r[MAX_BANDS_NUMBER_PLC], A[M + 1], synth[MAX_LEN + MDCT_MEM_LEN_MAX], energies[MAX_BANDS_NUMBER_PLC];
      21             :     LC3_INT32 pitch_classifier;
      22             :     LC3_FLOAT xcorr;
      23             :     LC3_INT32 yLen;
      24             :     LC3_INT16 prev_bfi_plc2;
      25             :     LC3_FLOAT  phEcu_env_stab_local[1];
      26             :     LC3_FLOAT  phEcu_pfind_sens[1];
      27             :     
      28           0 :     LC3_INT16 consecutiveLostThreshold = 0;
      29             : 
      30             :     LC3_INT16 thresh_tdc_cnt;
      31             :     LC3_INT16 thresh_ns_cnt;
      32             :     LC3_INT16 thresh_tdc_ns_cnt;
      33             : 
      34           0 :     prev_bfi_plc2 = 1;
      35           0 :     if (PlcSetup->nbLostCmpt == 0)
      36             :     {
      37           0 :         prev_bfi_plc2 = 0;
      38             :     }
      39           0 :     assert((h_DecSetup->PlcSetup.prevBfi == 1) == (prev_bfi_plc2 == 1));
      40             : 
      41           0 :     if (bfi == 1 && PlcAdvSetup)
      42             :     {
      43             :         /* FFLC increases the PFLC counter */
      44           0 :         statePC->ns_nbLostCmpt_pc = statePC->ns_nbLostCmpt_pc + 1;
      45             :     }
      46             : 
      47           0 :     pitch_classifier = ltpf_pitch_int;
      48             : 
      49           0 :     processPlcClassify_fl(plcMeth, &h_DecSetup->concealMethod, &PlcSetup->nbLostCmpt, bfi, &xcorr,
      50             :                           decoder->frame_length, decoder->frame_dms, pitch_classifier, decoder->fs,
      51             :                           bands_offset, bands_number, tilt, PlcAdvSetup, hrmode
      52             :         );
      53             : 
      54           0 :     if (bfi == 1)
      55             :     {
      56           0 :         switch(decoder->frame_dms)
      57             :         {
      58           0 :                 case 25: 
      59           0 :                     consecutiveLostThreshold  = 16;
      60           0 :                     thresh_tdc_cnt = THRESH_025_DMS_TDC_CNT;
      61           0 :                     thresh_ns_cnt = THRESH_025_DMS_NS_CNT;
      62           0 :                     thresh_tdc_ns_cnt =  THRESH_025_DMS_TDC_NS_CNT;                  
      63           0 :                     break;
      64           0 :                 case 50: consecutiveLostThreshold  = 8;  
      65           0 :                     thresh_tdc_cnt = THRESH_050_DMS_TDC_CNT;
      66           0 :                     thresh_ns_cnt = THRESH_050_DMS_NS_CNT;
      67           0 :                     thresh_tdc_ns_cnt =  THRESH_050_DMS_TDC_NS_CNT;                  
      68           0 :                     break;
      69           0 :                 case 75: consecutiveLostThreshold  = 6;
      70           0 :                     thresh_tdc_cnt = THRESH_075_DMS_TDC_CNT;
      71           0 :                     thresh_ns_cnt = THRESH_075_DMS_NS_CNT;
      72           0 :                     thresh_tdc_ns_cnt =  THRESH_075_DMS_TDC_NS_CNT;                   
      73           0 :                     break;
      74           0 :                 case 100: consecutiveLostThreshold = 4;  
      75           0 :                     thresh_tdc_cnt = THRESH_100_DMS_TDC_CNT;
      76           0 :                     thresh_ns_cnt = THRESH_100_DMS_NS_CNT;
      77           0 :                     thresh_tdc_ns_cnt =  THRESH_100_DMS_TDC_NS_CNT;
      78           0 :                     break;
      79           0 :             default: assert(0);
      80             :         }
      81             :         
      82           0 :             if (decoder->fs_idx == 2 || decoder->fs_idx >= 4)
      83             :             {
      84           0 :                 if (PlcAdvSetup->longterm_counter_plcTdc < thresh_tdc_cnt){
      85           0 :                     PlcAdvSetup->plc_fadeout_type = 1;
      86             :                 }
      87           0 :                 else if (PlcAdvSetup->longterm_counter_plcNsAdv < thresh_ns_cnt){
      88           0 :                     PlcAdvSetup->plc_fadeout_type = 1;
      89             :                 }
      90           0 :                 else if (PlcAdvSetup->longterm_counter_plcTdc + PlcAdvSetup->longterm_counter_plcNsAdv < thresh_tdc_ns_cnt){
      91           0 :                     PlcAdvSetup->plc_fadeout_type = 1;
      92             :                 }
      93             :                 else {
      94           0 :                     PlcAdvSetup->plc_fadeout_type = 0;
      95             :                     }
      96             :                 
      97           0 :                 if ((PlcAdvSetup->overall_counter - (int)(PLC_LONGTERM_ANALYSIS_STARTUP_FILL * PlcAdvSetup->longterm_analysis_counter_max)) < 0)
      98             :                 {
      99           0 :                     PlcAdvSetup->plc_fadeout_type = 0;
     100             :                 }
     101           0 :             if (h_DecSetup->rel_pitch_change > REL_PITCH_THRESH && hrmode == 1 && (decoder->frame_dms == 50 || decoder->frame_dms == 25) ){
     102           0 :                 PlcAdvSetup->plc_fadeout_type = 2;
     103             :             } else 
     104           0 :                 if ( h_DecSetup->concealMethod != 2 ) {
     105             :                     /* not PhECU */
     106           0 :                     if (PlcSetup->nbLostCmpt < consecutiveLostThreshold )
     107             :                     {
     108           0 :                         PlcAdvSetup->plc_fadeout_type = 0; 
     109             :                     }
     110             :                 }
     111             :             } else {
     112           0 :                 PlcAdvSetup->plc_fadeout_type = 0;
     113             :             }
     114             : 
     115           0 :         switch (h_DecSetup->concealMethod)
     116             :         {
     117           0 :         case 2:
     118             :         {
     119             :             LC3_FLOAT pitch_fl_c;
     120             :             
     121           0 :             assert(decoder->fs_idx == floor(decoder->fs / 10000));
     122             :             /* phaseECU supports only 10ms framing*/
     123           0 :             assert(PlcSetup->nbLostCmpt != 0 || decoder->frame_dms == 100);
     124             :             
     125           0 :             if (decoder->frame_dms != 100)
     126             :             {
     127             :                 /* muting, if frame size changed during phaseECU concealment */
     128           0 :                 memset(q_d_fl_c, 0, sizeof(LC3_FLOAT) * decoder->frame_length);
     129           0 :                 h_DecSetup->alpha = 0;
     130           0 :                 break;
     131             :             }
     132             : 
     133             :             /*  call phaseEcu  */
     134           0 :             pitch_fl_c = (LC3_FLOAT)ltpf_pitch_int + (LC3_FLOAT)ltpf_pitch_fr / 4.0; /* use non-rounded pitch indeces  */
     135             : 
     136             : 
     137           0 :             if (prev_bfi_plc2 == 0)
     138             :             {
     139             :                 /* convert fractional pitch lag info at current fs to a normalized fractional bin-frequency   */
     140           0 :                 PlcAdvSetup->PlcPhEcuSetup.PhECU_f0hzLtpBin = plc_phEcuSetF0Hz(decoder->fs, &pitch_fl_c);
     141             :                 /* several buffers  used in Cflt , a  copy  pcmbufHist,  right  before calling PhEcu in bad frames    */
     142           0 :                 assert(bfi == 1);
     143           0 :                 move_float(PlcAdvSetup->PlcPhEcuSetup.PhECU_xfp,
     144           0 :                            &(PlcAdvSetup->pcmbufHist[PlcAdvSetup->max_len_pcm_plc - PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot]),
     145             :                            PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot);
     146             : 
     147             :                 /* a first bfi frame:: calc windowed 16 ms energy twice in a 26 ms buffer separated by 10 ms*/
     148             :                 {
     149             :                     const LC3_FLOAT *w, *prev_xfp;
     150             :                     LC3_INT32 i, oold_start;
     151             : 
     152           0 :                     oold_start = PlcAdvSetup->max_len_pcm_plc - (decoder->frame_length + PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot);
     153           0 :                     assert(oold_start > 0);
     154           0 :                     w = PhECU_whr16ms_wins[decoder->fs_idx]; /* hammrect table */
     155           0 :                     prev_xfp = &(PlcAdvSetup->pcmbufHist[oold_start + 0]);
     156             : 
     157           0 :                     PlcAdvSetup->PlcPhEcuSetup.PhECU_L_oold_xfp_w_E = 0;
     158           0 :                     PlcAdvSetup->PlcPhEcuSetup.PhECU_L_old_xfp_w_E = 0;
     159           0 :                     for (i = 0; i < PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot; i++)
     160             :                     {
     161           0 :                         PlcAdvSetup->PlcPhEcuSetup.PhECU_L_oold_xfp_w_E += sqrf(prev_xfp[i] * w[i]);
     162           0 :                         PlcAdvSetup->PlcPhEcuSetup.PhECU_L_old_xfp_w_E  += sqrf(PlcAdvSetup->PlcPhEcuSetup.PhECU_xfp[i] * w[i]);
     163             :                     }
     164             : 
     165             :                 }
     166             : 
     167             :             } /* (prev_bfi_plc2 == 0)*/
     168             :             else 
     169             :             {
     170             :                 /* overwrite  last 3.75 ms of  xfp with most recent pcmbufHist   tail ,  right  before calling PhEcu in bursts of bad frames   */           
     171           0 :                 LC3_INT32  lenCopyOla =  decoder->la_zeroes;  /*copy_part + ola_part = 3.75 ms for 10 ms frame*/
     172             : 
     173           0 :                 assert(bfi == 1 && prev_bfi_plc2);
     174           0 :                 move_float(&(PlcAdvSetup->PlcPhEcuSetup.PhECU_xfp[PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot-lenCopyOla]),
     175           0 :                            &(PlcAdvSetup->pcmbufHist[PlcAdvSetup->max_len_pcm_plc - lenCopyOla]), lenCopyOla);
     176             :                    
     177             :             }
     178             : 
     179             :             {
     180             :                 LC3_FLOAT x_tda[MAX_LEN]; /* 960/2 */
     181           0 :                 PlcAdvSetup->PlcPhEcuSetup.PhECU_norm_corr = xcorr;
     182           0 :                 phEcu_env_stab_local[0] = (LC3_FLOAT)PHECU_ENV_STAB_LOCAL;
     183           0 :                 phEcu_pfind_sens[0]     = (LC3_FLOAT)PHECU_PFIND_SENS;
     184             : 
     185           0 :                 plc_phEcu_hq_ecu(&(PlcAdvSetup->PlcPhEcuSetup.PhECU_f0hzLtpBin),
     186             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_norm_corr),
     187             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_xfp,
     188             :                                  prev_bfi_plc2,
     189             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_short_flag_prev),
     190             :                                  decoder->fs,
     191             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_time_offs),
     192             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_X_sav_m, /* Complex */
     193             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_num_plocs),
     194             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_plocs,
     195             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_f0est,
     196           0 :                                  MDCT_WINS_10ms[hrmode][decoder->fs_idx],
     197             : 
     198             :                                  phEcu_env_stab_local,
     199             :                                  PHECU_DELTA_CORR,
     200             :                                  phEcu_pfind_sens, 
     201             :                                  PHECU_LA,
     202             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_t_adv,
     203           0 :                                  PhECU_whr16ms_wins[decoder->fs_idx],
     204             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_oold_grp_shape,
     205             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_L_oold_xfp_w_E),
     206             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_old_grp_shape,
     207             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_L_old_xfp_w_E),
     208             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhECU_beta_mute),
     209             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_mag_chg_1st,
     210             :                                  PlcAdvSetup->PlcPhEcuSetup.PhECU_Xavg,
     211             :                                  decoder->la_zeroes,
     212             :                                  x_tda, /* time domain aliased output */
     213             :                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
     214             :                                  ,
     215             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhEcu_Fft),
     216             :                                  &(PlcAdvSetup->PlcPhEcuSetup.PhEcu_Ifft)
     217           0 :                                  ,PlcAdvSetup->plc_fadeout_type,                   
     218             :                                                      &(PlcAdvSetup->PlcPhEcuSetup.PhECU_nonpure_tone_flag)  /* nonpure tone flag */
     219             :                  );
     220             : 
     221             : 
     222           0 :                 ProcessingITDA_WIN_OLA_fl(x_tda, decoder->frame_length, decoder->imdct_win, decoder->imdct_winLen, decoder->imdct_laZeros,
     223           0 :                                           h_DecSetup->imdct_mem, synth);
     224           0 :                 move_float(syntM_fl_c, synth, decoder->frame_length);
     225             : 
     226             :             
     227             :             }
     228             :         }
     229           0 :         break;
     230           0 :         case 3:
     231           0 :             if (PlcSetup->nbLostCmpt == 1)
     232             :             {
     233           0 :                 PlcAdvSetup->PlcTdcSetup.fract = ltpf_pitch_fr;
     234             :             }
     235             : 
     236           0 :             processPerBandEnergy_fl(n_bandsPLC, bands_offsetPLC, hrmode, decoder->frame_dms, energies, PlcSetup->q_d_prev);
     237           0 :             processTdcPreemphasis_fl(energies, &PlcAdvSetup->PlcTdcSetup.preemphFac, n_bandsPLC);
     238           0 :             processTdcInverseOdft_fl(energies, n_bandsPLC, r, PlcAdvSetup->PlcTdcSetup.lpcorder);
     239           0 :             processTdcLpcEstimation_fl(r, decoder->fs_idx, PlcAdvSetup->PlcTdcSetup.lpcorder + 1, A, decoder->frame_dms);
     240           0 :             processTdcApply_fl(ltpf_pitch_int, &PlcAdvSetup->PlcTdcSetup.preemphFac, A, PlcAdvSetup->PlcTdcSetup.lpcorder, PlcAdvSetup->pcmbufHist, PlcAdvSetup->max_len_pcm_plc, decoder->frame_length,
     241           0 :                                decoder->frame_dms, decoder->fs, PlcSetup->nbLostCmpt, decoder->frame_length - decoder->la_zeroes, &PlcAdvSetup->stabFac, PlcAdvSetup->PlcTdcSetup.harmonicBuf,
     242           0 :                                PlcAdvSetup->PlcTdcSetup.synthHist, &PlcAdvSetup->PlcTdcSetup.fract, &PlcAdvSetup->PlcTdcSetup.seed, &PlcAdvSetup->PlcTdcSetup.gain_c,
     243             :                                &h_DecSetup->alpha, synth
     244           0 :                                , PlcAdvSetup->plc_fadeout_type
     245           0 :                                , decoder->alpha_type_2_table
     246             : );
     247             : 
     248           0 :             processTdcTdac_fl(synth, decoder->imdct_win, decoder->frame_length, decoder->la_zeroes, h_DecSetup->imdct_mem);
     249           0 :             memmove(syntM_fl_c, synth, sizeof(LC3_FLOAT) * decoder->frame_length);
     250           0 :             break;
     251           0 :         case 4:
     252           0 :             processNoiseSubstitution_fl(q_d_fl_c, PlcSetup->q_d_prev, decoder->yLen);
     253           0 :             break;
     254           0 :         default:
     255             :             assert("Invalid PLC method!");
     256             :         }
     257             :     }
     258             : 
     259           0 :     if (bfi == 0)
     260             :     {
     261           0 :         processPlcUpdateSpec_fl(PlcSetup->q_d_prev, q_d_fl_c, decoder->yLen);
     262             :     }
     263             : 
     264           0 :     yLen = MIN(decoder->frame_length, MAX_PLC_LMEM);
     265           0 :     if (PlcAdvSetup != NULL && (decoder->frame_dms == 100) && (hrmode == 0))
     266             :         {
     267             :             /*  BASOP processPLCspec2shape_fx(prev_bfi, bfi, q_old_d_fx, yLen, plcAd->PhECU_oold_grp_shape_fx, plcAd->PhECU_old_grp_shape_fx);*/
     268           0 :             plc_phEcu_processPLCspec2shape(prev_bfi_plc2, bfi, q_d_fl_c, yLen,
     269             :                                            PlcAdvSetup->PlcPhEcuSetup.PhECU_oold_grp_shape, PlcAdvSetup->PlcPhEcuSetup.PhECU_old_grp_shape);
     270             :         }
     271           0 : }
     272             : 

Generated by: LCOV version 1.14