LCOV - code coverage report
Current view: top level - lib_lc3plus - ltpf_coder.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 1ecb9137d23f3dad766c8f6f3eb1e829e795f071 Lines: 130 140 92.9 %
Date: 2025-10-29 06:44:26 Functions: 2 2 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             : static LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len);
      15             : 
      16     1617786 : LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len)
      17             : {
      18     1617786 :     LC3_INT   max_i = 0, i;
      19     1617786 :     LC3_FLOAT max = 0;
      20             : 
      21     1617786 :     if (len <= 0) {
      22           0 :         return -128;
      23             :     }
      24             : 
      25    14407825 :     for (i = 0; i < len; i++) {
      26    12790039 :         if (in[i] > max) {
      27     6806040 :             max   = in[i];
      28     6806040 :             max_i = i;
      29             :         }
      30             :     }
      31             : 
      32     1617786 :     return max_i;
      33             : }
      34             : 
      35     1189311 : void process_ltpf_coder_fl(LC3_FLOAT* xin, LC3_INT xLen, LC3_INT ltpf_enable, LC3_INT pitch_ol, LC3_FLOAT pitch_ol_norm_corr, LC3_INT frame_dms,
      36             :                            LC3_FLOAT* mem_old_x, LC3_INT memLen, LC3_FLOAT* mem_norm_corr_past, LC3_INT* mem_on, LC3_FLOAT* mem_pitch,
      37             :                            LC3_INT* param, LC3_FLOAT* mem_norm_corr_past_past, LC3_INT* bits
      38             :                           , LC3_INT16 hrmode
      39             : )
      40             : {
      41     1189311 :     LC3_FLOAT buffer[LTPF_MEMIN_LEN + LEN_12K8 + 1 + (LEN_12K8 >> 2)], sum = 0, cor_up[(MAX_PITCH_12K8 - MIN_PITCH_12K8) / 2] = {0}, *x;
      42             :     LC3_INT   i, j, n, step, N, ltpf_active, pitch_search_delta,
      43     1189311 :         pitch_search_upsamp = 0, pitch_search_L_interpol1 = 0,
      44     1189311 :         t0_min = 0, t0_max = 0, t_min = 0, t_max = 0, temp2 = 0, t1 = 0, pitch_int = 0, pitch_fr = 0, midpoint = 0,
      45     1189311 :         delta_up = 0, delta_down = 0, pitch_index = 0, gain = 0, acflen = 0;
      46     1189311 :     LC3_FLOAT cor_tmp, cor_int_tmp, norm_corr = 0, cor[MAX_LEN_NR], cor_int[MAX_LEN_NR], sum1 = 0, sum2 = 0, sum3 = 0;
      47     1189311 :     LC3_FLOAT pitch = 0;
      48             : 
      49     1189311 :     LC3_FLOAT normCorrTh = 0.0f; 
      50     1189311 :     if (hrmode) {
      51           0 :         normCorrTh = 0.4;
      52             :     } else {
      53     1189311 :         normCorrTh = 0.6;
      54             :     }
      55             : 
      56             :     /* Signal Buffer */
      57     1189311 :     N = xLen - 1;
      58     1189311 :     x = &buffer[memLen];
      59             : 
      60     1189311 :     move_float(buffer, mem_old_x, memLen);
      61     1189311 :     move_float(x, xin, xLen);
      62     1189311 :     move_float(mem_old_x, &buffer[N], xLen + memLen - N);
      63             : 
      64     1189311 :     ltpf_active = 0;
      65     1189311 :     norm_corr   = 0;
      66             : 
      67     1189311 :     pitch_search_delta       = 4;
      68     1189311 :     pitch_search_upsamp      = 4;
      69     1189311 :     pitch_search_L_interpol1 = 4;
      70             : 
      71     1189311 :     if (pitch_ol_norm_corr > normCorrTh) {
      72             :         /* Search Bounds */
      73      889031 :         t0_min = pitch_ol - pitch_search_delta;
      74      889031 :         t0_max = pitch_ol + pitch_search_delta;
      75      889031 :         t0_min = MAX(t0_min, MIN_PITCH_12K8);
      76      889031 :         t0_max = MIN(t0_max, MAX_PITCH_12K8);
      77      889031 :         acflen = N;
      78             :         
      79      889031 :         if (frame_dms == 25)
      80             :         {
      81           0 :             acflen = 2 * N;
      82           0 :             x = x - N;
      83             :         }
      84             : 
      85             :         /* Cross-Correlation Bounds */
      86      889031 :         t_min = t0_min - pitch_search_L_interpol1;
      87      889031 :         t_max = t0_max + pitch_search_L_interpol1;
      88             : 
      89             :         /* Compute norm */
      90      889031 :         sum1 = sum2 = 0;
      91    60324871 :         for (j = 0; j < acflen; j++) {
      92    59435840 :             sum1 += x[j] * x[j];
      93    59435840 :             sum2 += x[j - t_min] * x[j - t_min];
      94             :         }
      95             :         
      96             :         /* Do first iteration outside of loop */
      97      889031 :         sum = mac_loop(x, &x[-t_min], acflen);
      98             : 
      99      889031 :         sum3      = LC3_SQRT(sum1 * sum2) + 1.00e-05;
     100      889031 :         norm_corr = sum / sum3;
     101             :             
     102      889031 :         norm_corr = MAX(0, norm_corr);
     103      889031 :         cor[0] = norm_corr;
     104             : 
     105             :         /* Compute Cross-Correlation */
     106    15052435 :         for (i = t_min + 1; i <= t_max; i++) {
     107    14163404 :             sum = mac_loop(x, &x[-i], acflen);
     108             : 
     109    14163404 :             sum2 = sum2 + x[-i]*x[-i]
     110    14163404 :                             - x[acflen - 1 - ( i - 1 )]*x[acflen - 1 - ( i - 1 )];
     111             : 
     112    14163404 :             sum3      = LC3_SQRT(sum1 * sum2) + 1.00e-05;
     113    14163404 :             norm_corr = sum / sum3;
     114             :             
     115    14163404 :             norm_corr = MAX(0, norm_corr);
     116    14163404 :             cor[i - t_min] = norm_corr;
     117             : 
     118             :         }
     119             : 
     120             :         /* Find Integer Pitch-Lag */
     121      889031 :         temp2 = searchMaxIndice(&cor[pitch_search_L_interpol1], t_max - t_min - pitch_search_L_interpol1 - pitch_search_L_interpol1 + 1);
     122             : 
     123      889031 :         t1 = temp2 + t0_min;
     124      889031 :         assert(t1 >= t0_min && t1 <= t0_max);
     125             : 
     126             :         /* Find Fractional Pitch-Lag */
     127      889031 :         if (t1 >= RES2_PITCH_12K8) {
     128      160276 :             pitch_int = t1;
     129      160276 :             pitch_fr  = 0;
     130             :         } else {
     131      728755 :             j = 0;
     132             :             
     133    13081600 :             for (i = 0; i < pitch_search_upsamp * (t_max - t_min) + 1; i = i + pitch_search_upsamp) {
     134    12352845 :                 cor_up[i] = cor[j];
     135    12352845 :                 j++;
     136             :             }
     137             : 
     138    26819975 :             for (i = 0; i < pitch_search_upsamp * (t0_max - t0_min + 1); i++) {
     139    26091220 :                 sum = mac_loop(&cor_up[i], (const LC3_FLOAT *)inter4_1, 32);
     140             : 
     141    26091220 :                 cor_int[i] = sum;
     142             :             }
     143             : 
     144      728755 :             if (t1 >= RES4_PITCH_12K8) {
     145       34614 :                 step = 2;
     146             :             } else {
     147      694141 :                 step = 1;
     148             :             }
     149             : 
     150      728755 :             midpoint = pitch_search_upsamp * (t1 - t0_min) + 1;
     151      728755 :             delta_up = pitch_search_upsamp - step;
     152             : 
     153      728755 :             if (t1 == t0_min) {
     154       38899 :                 delta_down = 0;
     155             :             } else {
     156      689856 :                 delta_down = pitch_search_upsamp - step;
     157             :             }
     158             :             
     159      728755 :             j = 0;
     160     6272748 :             for (i = midpoint - delta_down - 1; i <= midpoint + delta_up; i = i + step) {
     161     5543993 :                 cor[j] = cor_int[i];
     162     5543993 :                 j++;
     163             :             }
     164             : 
     165             : 
     166      728755 :             temp2    = searchMaxIndice(cor, ((midpoint + delta_up) - (midpoint - delta_down)) / step + 1);
     167      728755 :             pitch_fr = temp2 * step - delta_down;
     168             : 
     169      728755 :             if (pitch_fr >= 0) {
     170      643832 :                 pitch_int = t1;
     171             :             } else {
     172       84923 :                 pitch_int = t1 - 1;
     173       84923 :                 pitch_fr  = pitch_search_upsamp + pitch_fr;
     174             :             }
     175             :         }
     176             : 
     177      889031 :         assert((pitch_int <= MAX_PITCH_12K8 && pitch_int >= RES2_PITCH_12K8 && pitch_fr == 0) ||
     178             :                (pitch_int < RES2_PITCH_12K8 && pitch_int >= RES4_PITCH_12K8 && (pitch_fr == 0 || pitch_fr == 2)) ||
     179             :                (pitch_int < RES4_PITCH_12K8 && pitch_int >= MIN_PITCH_12K8 &&
     180             :                 (pitch_fr == 0 || pitch_fr == 1 || pitch_fr == 2 || pitch_fr == 3)));
     181             :         
     182      889031 :         if (pitch_int < RES4_PITCH_12K8) {
     183      694273 :             pitch_index = pitch_int * 4 + pitch_fr - (MIN_PITCH_12K8 * 4);
     184      194758 :         } else if (pitch_int < RES2_PITCH_12K8) {
     185       34482 :             pitch_index = pitch_int * 2 + floor(pitch_fr / 2) - (RES4_PITCH_12K8 * 2) + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4);
     186             :         } else {
     187      160276 :             pitch_index = pitch_int - RES2_PITCH_12K8 + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) + ((RES2_PITCH_12K8 - RES4_PITCH_12K8) * 2);
     188             :         }
     189             : 
     190      889031 :         assert(pitch_index >= 0 && pitch_index < 512);
     191      889031 :         pitch = (LC3_FLOAT) pitch_int + (LC3_FLOAT) pitch_fr / 4.0;
     192             :         
     193             : 
     194             :         /* Normalized Correlation */
     195      889031 :         sum1 = sum2 = sum3 = 0;
     196    60324871 :         for (n = 0; n < acflen; n++)
     197             :         {
     198    59435840 :             cor_tmp = x[n + 1] * enc_inter_filter[0][0] +
     199    59435840 :                            x[n]     * enc_inter_filter[0][1] +
     200    59435840 :                            x[n - 1] * enc_inter_filter[0][2];
     201             : 
     202    59435840 :             cor_int_tmp = x[n - pitch_int + 1] * enc_inter_filter[pitch_fr][0] +
     203    59435840 :                            x[n - pitch_int]     * enc_inter_filter[pitch_fr][1] +
     204    59435840 :                            x[n - pitch_int - 1] * enc_inter_filter[pitch_fr][2] +
     205    59435840 :                            x[n - pitch_int - 2] * enc_inter_filter[pitch_fr][3];
     206             :             
     207    59435840 :             sum1 += cor_tmp * cor_int_tmp;
     208    59435840 :             sum2 += cor_tmp * cor_tmp;
     209    59435840 :             sum3 += cor_int_tmp * cor_int_tmp;
     210             :         }
     211             : 
     212      889031 :         sum2      = LC3_SQRT(sum2 * sum3) + 1.00e-05;
     213      889031 :         norm_corr = sum1 / sum2;
     214             : 
     215      889031 :         assert(norm_corr >= -1.00001 && norm_corr <= 1.00001);
     216      889031 :         norm_corr = MIN(1, MAX(-1, norm_corr));
     217      889031 :         if (norm_corr < 0) {
     218        2138 :             norm_corr = 0;
     219             :         }
     220             : 
     221      889031 :         if (ltpf_enable == 1) {
     222             :             /* Decision if ltpf active */
     223           0 :             if ((*mem_on == 0 && (frame_dms == 100 || *mem_norm_corr_past_past > 0.94) && *mem_norm_corr_past > 0.94 &&
     224           0 :                  norm_corr > 0.94) ||
     225           0 :                 (*mem_on == 1 && norm_corr > 0.9) ||
     226           0 :                 (*mem_on == 1 && LC3_FABS(pitch - *mem_pitch) < 2 && (norm_corr - *mem_norm_corr_past) > -0.1 &&
     227           0 :                  norm_corr > 0.84)) {
     228           0 :                 ltpf_active = 1;
     229             :             }
     230             :         }
     231             : 
     232      889031 :         gain = 4;
     233             : 
     234             :     } else {
     235      300280 :         gain      = 0;
     236      300280 :         norm_corr = pitch_ol_norm_corr;
     237      300280 :         pitch     = 0;
     238             :     }
     239             : 
     240     1189311 :     if (gain > 0) {
     241      889031 :         param[0] = 1;
     242      889031 :         param[1] = ltpf_active;
     243      889031 :         param[2] = pitch_index;
     244      889031 :         *bits    = 11;
     245             :     } else {
     246      300280 :         zero_int(param, 3);
     247             : 
     248      300280 :         *bits = 1;
     249             :     }
     250             : 
     251     1189311 :     if (frame_dms < 100) {
     252     1139339 :         *mem_norm_corr_past_past = *mem_norm_corr_past;
     253             :     }
     254             : 
     255     1189311 :     *mem_norm_corr_past = norm_corr;
     256     1189311 :     *mem_on             = ltpf_active;
     257     1189311 :     *mem_pitch          = pitch;
     258     1189311 : }

Generated by: LCOV version 1.14