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 @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 140 0.0 %
Date: 2025-05-23 08:37:30 Functions: 0 2 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             : static LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len);
      15             : 
      16           0 : LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len)
      17             : {
      18           0 :     LC3_INT   max_i = 0, i;
      19           0 :     LC3_FLOAT max = 0;
      20             : 
      21           0 :     if (len <= 0) {
      22           0 :         return -128;
      23             :     }
      24             : 
      25           0 :     for (i = 0; i < len; i++) {
      26           0 :         if (in[i] > max) {
      27           0 :             max   = in[i];
      28           0 :             max_i = i;
      29             :         }
      30             :     }
      31             : 
      32           0 :     return max_i;
      33             : }
      34             : 
      35           0 : 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           0 :     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           0 :         pitch_search_upsamp = 0, pitch_search_L_interpol1 = 0,
      44           0 :         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           0 :         delta_up = 0, delta_down = 0, pitch_index = 0, gain = 0, acflen = 0;
      46           0 :     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           0 :     LC3_FLOAT pitch = 0;
      48             : 
      49           0 :     LC3_FLOAT normCorrTh = 0.0f; 
      50           0 :     if (hrmode) {
      51           0 :         normCorrTh = 0.4;
      52             :     } else {
      53           0 :         normCorrTh = 0.6;
      54             :     }
      55             : 
      56             :     /* Signal Buffer */
      57           0 :     N = xLen - 1;
      58           0 :     x = &buffer[memLen];
      59             : 
      60           0 :     move_float(buffer, mem_old_x, memLen);
      61           0 :     move_float(x, xin, xLen);
      62           0 :     move_float(mem_old_x, &buffer[N], xLen + memLen - N);
      63             : 
      64           0 :     ltpf_active = 0;
      65           0 :     norm_corr   = 0;
      66             : 
      67           0 :     pitch_search_delta       = 4;
      68           0 :     pitch_search_upsamp      = 4;
      69           0 :     pitch_search_L_interpol1 = 4;
      70             : 
      71           0 :     if (pitch_ol_norm_corr > normCorrTh) {
      72             :         /* Search Bounds */
      73           0 :         t0_min = pitch_ol - pitch_search_delta;
      74           0 :         t0_max = pitch_ol + pitch_search_delta;
      75           0 :         t0_min = MAX(t0_min, MIN_PITCH_12K8);
      76           0 :         t0_max = MIN(t0_max, MAX_PITCH_12K8);
      77           0 :         acflen = N;
      78             :         
      79           0 :         if (frame_dms == 25)
      80             :         {
      81           0 :             acflen = 2 * N;
      82           0 :             x = x - N;
      83             :         }
      84             : 
      85             :         /* Cross-Correlation Bounds */
      86           0 :         t_min = t0_min - pitch_search_L_interpol1;
      87           0 :         t_max = t0_max + pitch_search_L_interpol1;
      88             : 
      89             :         /* Compute norm */
      90           0 :         sum1 = sum2 = 0;
      91           0 :         for (j = 0; j < acflen; j++) {
      92           0 :             sum1 += x[j] * x[j];
      93           0 :             sum2 += x[j - t_min] * x[j - t_min];
      94             :         }
      95             :         
      96             :         /* Do first iteration outside of loop */
      97           0 :         sum = mac_loop(x, &x[-t_min], acflen);
      98             : 
      99           0 :         sum3      = LC3_SQRT(sum1 * sum2) + 1.00e-05;
     100           0 :         norm_corr = sum / sum3;
     101             :             
     102           0 :         norm_corr = MAX(0, norm_corr);
     103           0 :         cor[0] = norm_corr;
     104             : 
     105             :         /* Compute Cross-Correlation */
     106           0 :         for (i = t_min + 1; i <= t_max; i++) {
     107           0 :             sum = mac_loop(x, &x[-i], acflen);
     108             : 
     109           0 :             sum2 = sum2 + x[-i]*x[-i]
     110           0 :                             - x[acflen - 1 - ( i - 1 )]*x[acflen - 1 - ( i - 1 )];
     111             : 
     112           0 :             sum3      = LC3_SQRT(sum1 * sum2) + 1.00e-05;
     113           0 :             norm_corr = sum / sum3;
     114             :             
     115           0 :             norm_corr = MAX(0, norm_corr);
     116           0 :             cor[i - t_min] = norm_corr;
     117             : 
     118             :         }
     119             : 
     120             :         /* Find Integer Pitch-Lag */
     121           0 :         temp2 = searchMaxIndice(&cor[pitch_search_L_interpol1], t_max - t_min - pitch_search_L_interpol1 - pitch_search_L_interpol1 + 1);
     122             : 
     123           0 :         t1 = temp2 + t0_min;
     124           0 :         assert(t1 >= t0_min && t1 <= t0_max);
     125             : 
     126             :         /* Find Fractional Pitch-Lag */
     127           0 :         if (t1 >= RES2_PITCH_12K8) {
     128           0 :             pitch_int = t1;
     129           0 :             pitch_fr  = 0;
     130             :         } else {
     131           0 :             j = 0;
     132             :             
     133           0 :             for (i = 0; i < pitch_search_upsamp * (t_max - t_min) + 1; i = i + pitch_search_upsamp) {
     134           0 :                 cor_up[i] = cor[j];
     135           0 :                 j++;
     136             :             }
     137             : 
     138           0 :             for (i = 0; i < pitch_search_upsamp * (t0_max - t0_min + 1); i++) {
     139           0 :                 sum = mac_loop(&cor_up[i], (const LC3_FLOAT *)inter4_1, 32);
     140             : 
     141           0 :                 cor_int[i] = sum;
     142             :             }
     143             : 
     144           0 :             if (t1 >= RES4_PITCH_12K8) {
     145           0 :                 step = 2;
     146             :             } else {
     147           0 :                 step = 1;
     148             :             }
     149             : 
     150           0 :             midpoint = pitch_search_upsamp * (t1 - t0_min) + 1;
     151           0 :             delta_up = pitch_search_upsamp - step;
     152             : 
     153           0 :             if (t1 == t0_min) {
     154           0 :                 delta_down = 0;
     155             :             } else {
     156           0 :                 delta_down = pitch_search_upsamp - step;
     157             :             }
     158             :             
     159           0 :             j = 0;
     160           0 :             for (i = midpoint - delta_down - 1; i <= midpoint + delta_up; i = i + step) {
     161           0 :                 cor[j] = cor_int[i];
     162           0 :                 j++;
     163             :             }
     164             : 
     165             : 
     166           0 :             temp2    = searchMaxIndice(cor, ((midpoint + delta_up) - (midpoint - delta_down)) / step + 1);
     167           0 :             pitch_fr = temp2 * step - delta_down;
     168             : 
     169           0 :             if (pitch_fr >= 0) {
     170           0 :                 pitch_int = t1;
     171             :             } else {
     172           0 :                 pitch_int = t1 - 1;
     173           0 :                 pitch_fr  = pitch_search_upsamp + pitch_fr;
     174             :             }
     175             :         }
     176             : 
     177           0 :         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           0 :         if (pitch_int < RES4_PITCH_12K8) {
     183           0 :             pitch_index = pitch_int * 4 + pitch_fr - (MIN_PITCH_12K8 * 4);
     184           0 :         } else if (pitch_int < RES2_PITCH_12K8) {
     185           0 :             pitch_index = pitch_int * 2 + floor(pitch_fr / 2) - (RES4_PITCH_12K8 * 2) + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4);
     186             :         } else {
     187           0 :             pitch_index = pitch_int - RES2_PITCH_12K8 + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) + ((RES2_PITCH_12K8 - RES4_PITCH_12K8) * 2);
     188             :         }
     189             : 
     190           0 :         assert(pitch_index >= 0 && pitch_index < 512);
     191           0 :         pitch = (LC3_FLOAT) pitch_int + (LC3_FLOAT) pitch_fr / 4.0;
     192             :         
     193             : 
     194             :         /* Normalized Correlation */
     195           0 :         sum1 = sum2 = sum3 = 0;
     196           0 :         for (n = 0; n < acflen; n++)
     197             :         {
     198           0 :             cor_tmp = x[n + 1] * enc_inter_filter[0][0] +
     199           0 :                            x[n]     * enc_inter_filter[0][1] +
     200           0 :                            x[n - 1] * enc_inter_filter[0][2];
     201             : 
     202           0 :             cor_int_tmp = x[n - pitch_int + 1] * enc_inter_filter[pitch_fr][0] +
     203           0 :                            x[n - pitch_int]     * enc_inter_filter[pitch_fr][1] +
     204           0 :                            x[n - pitch_int - 1] * enc_inter_filter[pitch_fr][2] +
     205           0 :                            x[n - pitch_int - 2] * enc_inter_filter[pitch_fr][3];
     206             :             
     207           0 :             sum1 += cor_tmp * cor_int_tmp;
     208           0 :             sum2 += cor_tmp * cor_tmp;
     209           0 :             sum3 += cor_int_tmp * cor_int_tmp;
     210             :         }
     211             : 
     212           0 :         sum2      = LC3_SQRT(sum2 * sum3) + 1.00e-05;
     213           0 :         norm_corr = sum1 / sum2;
     214             : 
     215           0 :         assert(norm_corr >= -1.00001 && norm_corr <= 1.00001);
     216           0 :         norm_corr = MIN(1, MAX(-1, norm_corr));
     217           0 :         if (norm_corr < 0) {
     218           0 :             norm_corr = 0;
     219             :         }
     220             : 
     221           0 :         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           0 :         gain = 4;
     233             : 
     234             :     } else {
     235           0 :         gain      = 0;
     236           0 :         norm_corr = pitch_ol_norm_corr;
     237           0 :         pitch     = 0;
     238             :     }
     239             : 
     240           0 :     if (gain > 0) {
     241           0 :         param[0] = 1;
     242           0 :         param[1] = ltpf_active;
     243           0 :         param[2] = pitch_index;
     244           0 :         *bits    = 11;
     245             :     } else {
     246           0 :         zero_int(param, 3);
     247             : 
     248           0 :         *bits = 1;
     249             :     }
     250             : 
     251           0 :     if (frame_dms < 100) {
     252           0 :         *mem_norm_corr_past_past = *mem_norm_corr_past;
     253             :     }
     254             : 
     255           0 :     *mem_norm_corr_past = norm_corr;
     256           0 :     *mem_on             = ltpf_active;
     257           0 :     *mem_pitch          = pitch;
     258           0 : }

Generated by: LCOV version 1.14