LCOV - code coverage report
Current view: top level - lib_lc3plus - plc_classify.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ 9b04ec3cb36f5e8dc438cf854fa3e349998fa1e9 Lines: 123 134 91.8 %
Date: 2025-10-31 05:45:46 Functions: 7 7 100.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     3539970 : static LC3_INT32 change_bit_at_position(LC3_INT32 value, LC3_UINT8 bit_position, LC3_INT8 bit)
      15             : {
      16     3539970 :     LC3_INT32 helper_mask = ~(1 << bit_position);
      17     3539970 :     LC3_INT32 tmp = value & helper_mask;
      18     3539970 :     tmp = tmp | (bit << bit_position);
      19     3539970 :     return tmp;
      20             : }
      21             : 
      22     1769985 : static void update_bit_and_byte_positions(LC3_INT16 longterm_analysis_counter_max_bytebuffer, LC3_INT8 *byte_position, LC3_INT8 *bit_position)
      23             : {
      24     1769985 :     if (*bit_position == 29)
      25             :     {
      26       58174 :         *bit_position = 0;
      27             :         
      28       58174 :         if ((*byte_position - longterm_analysis_counter_max_bytebuffer) < -1)
      29             :         {
      30       55116 :             *byte_position = *byte_position + 1;
      31             :         } else {
      32        3058 :             *byte_position = 0;
      33             :         }
      34             :     } else {
      35     1711811 :         *bit_position = *bit_position + 1;
      36             :     }
      37     1769985 : }
      38             : 
      39     3539970 : static void array_insert_and_shift(LC3_INT32 *array, LC3_UINT8 value, LC3_INT16 longterm_analysis_counter_max, LC3_INT16 *overall_counter, LC3_INT8 *byte_position, LC3_INT8 *bit_position)
      40             : {
      41     3539970 :     LC3_INT32 current_byte = 0;
      42             :     
      43     3539970 :     if (overall_counter != NULL) 
      44             :     {
      45     1769985 :         *overall_counter = MIN(*overall_counter + 1, longterm_analysis_counter_max);
      46             :     }
      47             :     
      48     3539970 :     current_byte = array[*byte_position];
      49             :     
      50     3539970 :     current_byte = change_bit_at_position(current_byte, *bit_position, value);
      51             :     
      52     3539970 :     array[*byte_position] = current_byte;
      53     3539970 : }
      54             : 
      55     1769985 : static void array_calculate(LC3_INT32 *array_tdc, LC3_INT32 *array_ns, int length, LC3_INT16 *counter_tdc, LC3_INT16 *counter_ns, LC3_INT16 longterm_analysis_counter_max)
      56             : {
      57             :     int i, k;
      58     1769985 :     LC3_INT32 current_byte_tdc = 0, current_byte_ns = 0;
      59     1769985 :     LC3_INT16 counter_loc_tdc = 0, counter_loc_ns = 0, counter_tmp = 0;
      60             : 
      61    25975041 :     for (i = length - 1; i >= 0; i--)
      62             :     {
      63    24205056 :         current_byte_tdc = array_tdc[i];
      64    24205056 :         current_byte_ns = array_ns[i];
      65             :         
      66   714008671 :         for (k = 0; k < 30; k++)
      67             :         {
      68   691573600 :             counter_loc_tdc += ((current_byte_tdc >> k) & 1);
      69   691573600 :             counter_loc_ns += ((current_byte_ns >> k) & 1);
      70   691573600 :             counter_tmp++;
      71             :             
      72             :             /* Break from both loops if full 2s buffer has been evaluated */
      73   691573600 :             if (counter_tmp >= longterm_analysis_counter_max)
      74             :             {
      75     1769985 :                 i = -1;
      76     1769985 :                 k = 30;
      77     1769985 :                 break;
      78             :             }
      79             :         }
      80             :     }
      81             :     
      82     1769985 :     *counter_tdc = counter_loc_tdc;
      83     1769985 :     *counter_ns = counter_loc_ns;
      84     1769985 : }
      85             : 
      86             : static void plc_xcorr_lc(LC3_FLOAT *pcmbufHist, LC3_INT32 max_len_pcm_plc, LC3_INT32 pitch_int, LC3_INT32 framelength, LC3_INT32 frame_dms, LC3_INT32 fs, LC3_FLOAT *xcorr);
      87             : static void spectral_centroid_lc(LC3_FLOAT *gains, LC3_INT32 tilt, const LC3_INT *bands_offset, LC3_INT32 bands_number, LC3_INT32 framelength, LC3_INT32 fs, LC3_FLOAT *sc);
      88             : 
      89     1777035 : void processPlcClassify_fl(LC3_INT plcMeth, LC3_INT *concealMethod, LC3_INT32 *nbLostCmpt, LC3_INT32 bfi,
      90             :                            LC3_FLOAT *xcorr, LC3_INT32 framelength, LC3_INT32 frame_dms, LC3_INT32 pitch_int,
      91             :                            LC3_INT32 fs, const LC3_INT *band_offsets, LC3_INT32 bands_number, LC3_INT32 tilt, PlcAdvSetup *plcAd
      92             :                            , LC3_INT32 hrmode
      93             : )
      94             : {
      95             :         LC3_FLOAT sc, class;
      96             :         int fs_idx_tmp;
      97             : 
      98     1777035 :     if (plcAd)
      99             :     {
     100     1777035 :         *xcorr = 0;
     101             :     }
     102             :     
     103     1777035 :     fs_idx_tmp = FS2FS_IDX(fs);
     104             :     /* Save statistics for 24 kHz, 48 kHz and 96 kHz */
     105     1777035 :     if ((bfi == 1) || ((bfi >= 0) && (bfi <= 2) && ((fs_idx_tmp == 2) || (fs_idx_tmp == 4) || (fs_idx_tmp == 5))))   /* Partial Concealment PC(bfi==2) requires allowing value  2 to pass thru  as well */
     106             :     {
     107     1777027 :         if (bfi == 1)
     108             :         {
     109        8287 :             *nbLostCmpt = *nbLostCmpt + 1;
     110             :         }
     111             :         
     112             :         /* Use pitch correlation at ltpf integer lag if available */
     113     1777027 :         if ((*nbLostCmpt == 1) || (bfi != 1) )/* PC(bfi==2) requires allowing 2 to pass thru  as well */
     114             :         {
     115     1769985 :             *concealMethod = 4;  /* Noise Substitution */
     116             :             UNUSED(plcMeth);
     117             : 
     118             :             /* Advanced PLC */
     119     1769985 :             if (pitch_int > 0)
     120             :             {
     121     1371192 :                 *concealMethod = 3; /* Timedomain PLC assumed */
     122     1371192 :                 plc_xcorr_lc(plcAd->pcmbufHist, plcAd->max_len_pcm_plc, pitch_int, framelength, frame_dms, fs, xcorr);
     123             : 
     124     1371192 :                 spectral_centroid_lc(plcAd->scf_q_old, tilt, band_offsets, bands_number, framelength, fs, &sc);
     125     1371192 :                 class = *xcorr * 7640.0 / 32768.0 - sc - 5112.0 / 32768.0;
     126             :                 
     127     1371192 :                 if (class <= 0)
     128             :                 {
     129      523461 :                     if (frame_dms == 100 && hrmode == 0)
     130             :                     {
     131       21063 :                         *concealMethod = 2; /* PhaseEcu selected */
     132       21063 :                         array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     133       21063 :                         array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     134             :                     }
     135             :                     else
     136             :                     {
     137      502398 :                         array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     138      502398 :                         array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     139             :                     }
     140             :                 }
     141             :                 else {
     142      847731 :                     array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 1, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     143      847731 :                     array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     144             :                 }
     145             :             }
     146             :             else
     147             :             {
     148      398793 :                 *concealMethod = 4; /* Noise Substitution */
     149      398793 :                 array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     150      398793 :                 array_insert_and_shift(plcAd->plc_longterm_advc_ns, 1, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     151             :             }
     152             :             
     153     1769985 :             array_calculate(plcAd->plc_longterm_advc_tdc, plcAd->plc_longterm_advc_ns, plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_plcTdc, &plcAd->longterm_counter_plcNsAdv, plcAd->longterm_analysis_counter_max);
     154     1769985 :             update_bit_and_byte_positions(plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position);
     155             :         }
     156             :     }
     157     1777035 : }
     158             : 
     159     1371192 : static void spectral_centroid_lc(LC3_FLOAT *gains, LC3_INT32 tilt, const LC3_INT *band_offsets, LC3_INT32 bands_number, LC3_INT32 framelength, LC3_INT32 fs, LC3_FLOAT *sc)
     160             : {
     161             :         LC3_FLOAT gains_lin[M], gains_dee[M], numerator, denumerator;
     162             :         LC3_INT32 i, j, sum, len, start, stop;
     163             :         LC3_INT band_offsets_local[MAX_BANDS_NUMBER + 1];
     164             :     
     165     1371192 :     numerator = 0;
     166             : 
     167    23310264 :     for (i = 0; i < M; i++)
     168             :     {
     169    21939072 :         gains_lin[i] = LC3_POW(2, gains[i]);
     170             :     }
     171             :     
     172    23310264 :     for (i = 0; i < M; i++)
     173             :     {
     174    21939072 :         gains_dee[i] = gains_lin[i] / LC3_POW(10, i * (LC3_FLOAT) tilt / (LC3_FLOAT) (M - 1) / 10.0);
     175             :     }
     176             :     
     177     1371192 :     if (bands_number == 64)
     178             :     {
     179       67447 :         memmove(band_offsets_local, band_offsets, (bands_number + 1) * sizeof(LC3_INT));
     180             :     }
     181             : 
     182     1371192 :     if (bands_number < 32)
     183             :     {
     184           0 :         band_offsets_local[0] = 0;
     185           0 :         j = 32 - bands_number;
     186           0 :         for (i = bands_number - 1; i >= j; i--)
     187             :         {
     188           0 :             band_offsets_local[(i + j) * 2 + 1 + 1] = band_offsets[i + 1];
     189           0 :             band_offsets_local[(i + j) * 2 + 0 + 1] = band_offsets[i + 1];
     190             :         }
     191           0 :         for (i = j - 1; i >= 0; i--)
     192             :         {
     193           0 :             band_offsets_local[i * 4 + 3 + 1] = band_offsets[i + 1];
     194           0 :             band_offsets_local[i * 4 + 2 + 1] = band_offsets[i + 1];
     195           0 :             band_offsets_local[i * 4 + 1 + 1] = band_offsets[i + 1];
     196           0 :             band_offsets_local[i * 4 + 0 + 1] = band_offsets[i + 1];
     197             :         }
     198             :     }
     199             :     else
     200     1371192 :     if (bands_number < 64)
     201             :     {
     202     1303745 :         band_offsets_local[0] = 0;
     203     1303745 :         j = 64 - bands_number;
     204    61276015 :         for (i = bands_number - 1; i >= j; i--)
     205             :         {
     206    59972270 :             band_offsets_local[i + j + 1] = band_offsets[i + 1];
     207             :         }
     208    13037450 :         for (i = j - 1; i >= 0; i--)
     209             :         {
     210    11733705 :             band_offsets_local[i * 2 + 1 + 1] = band_offsets[i + 1];
     211    11733705 :             band_offsets_local[i * 2 + 0 + 1] = band_offsets[i + 1];
     212             :         }
     213             :     }
     214             : 
     215     1371192 :     denumerator = 0.001;
     216             :     
     217    23310264 :     for (i = 0; i < M; i++)
     218             :     {
     219    21939072 :         sum = 0; len = 0;
     220    21939072 :         start = band_offsets_local[i * 4] + 1; stop = band_offsets_local[i * 4 + 4];
     221             :         
     222   309666872 :         for (j = stop; j >= start; j--)
     223             :         {
     224   287727800 :             sum += j;
     225   287727800 :             len++;
     226             :         }
     227             :         
     228    21939072 :         numerator += gains_dee[i] * ((LC3_FLOAT) sum / (LC3_FLOAT) framelength);
     229    21939072 :         denumerator += gains_dee[i] * len;
     230             :     }
     231             :     
     232     1371192 :     *sc = numerator / denumerator;
     233     1371192 :     *sc = *sc * (LC3_FLOAT) fs / 48000.0; /* scaling, because training is for 48kHz */
     234     1371192 : }
     235             : 
     236     1371192 : static void plc_xcorr_lc(LC3_FLOAT *pcmbufHist, LC3_INT32 max_len_pcm_plc, LC3_INT32 pitch_int, LC3_INT32 framelength,
     237             :                          LC3_INT32 frame_dms, LC3_INT32 fs, LC3_FLOAT *xcorr)
     238             : {
     239             :         LC3_INT32 max_corr_len, pitch_min, corr_len, min_corr_len, pcm_max_corr_len, range1Start, range2Start, i;
     240             :         LC3_FLOAT norm_w, norm_w_t;
     241             :     
     242     1371192 :     norm_w_t = 0; norm_w = 0;
     243             : 
     244     1371192 :     assert(pitch_int >= 0);
     245     1371192 :     assert(pitch_int <= MAX_LEN*100*MAX_PITCH_12K8/12800);
     246             :     
     247     1371192 :     *xcorr = 0;
     248             : 
     249     1371192 :     if (pitch_int > 0)
     250             :     {
     251     1371192 :         pitch_min = fs * MIN_PITCH_12K8/12800;
     252     1371192 :         pcm_max_corr_len = max_len_pcm_plc - pitch_int;
     253             : 
     254     1371192 :         min_corr_len = 2 * pitch_min;              /* at least 5 ms (=2*pitchmin*) corr length */
     255     1371192 :         max_corr_len = framelength*100/frame_dms;  /* maximum 10 ms */
     256     1371192 :         max_corr_len = MIN( max_corr_len, pcm_max_corr_len );
     257             : 
     258     1371192 :         corr_len = MIN( max_corr_len, pitch_int ); /* pitch_int is prefered, but maximum 10ms or left pcm buf size */
     259     1371192 :         corr_len = MAX( min_corr_len, corr_len );
     260             : 
     261     1371192 :         range1Start = max_len_pcm_plc - corr_len;
     262     1371192 :         range2Start = range1Start - pitch_int;
     263             : 
     264     1371192 :         assert( corr_len >= min_corr_len );
     265     1371192 :         assert( corr_len <= max_corr_len );
     266     1371192 :         assert( range2Start >= 0 );
     267             : 
     268   465230507 :         for (i = 0; i < corr_len; i++)
     269             :         {
     270   463859315 :             norm_w += pcmbufHist[range1Start + i] * pcmbufHist[range1Start + i];
     271             :         }
     272             : 
     273   465230507 :         for (i = 0; i < corr_len; i++)
     274             :         {
     275   463859315 :             norm_w_t += pcmbufHist[range2Start + i] * pcmbufHist[range2Start + i];
     276             :         }
     277             : 
     278   465230507 :         for (i = 0; i < corr_len; i++)
     279             :         {
     280   463859315 :             *xcorr = *xcorr + pcmbufHist[range1Start + i] * pcmbufHist[range2Start + i];
     281             :         }
     282             : 
     283     1371192 :         *xcorr = *xcorr / sqrt(norm_w * norm_w_t + 0.1);
     284     1371192 :         *xcorr = MAX(0, *xcorr);
     285             :     } else {
     286           0 :         *xcorr = 0;
     287             :     }
     288     1371192 : }
     289             : 

Generated by: LCOV version 1.14