LCOV - code coverage report
Current view: top level - lib_lc3plus - ltpf_coder.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ a21f94bc6bac334fe001a5bad2f7b32b79038097 Lines: 136 164 82.9 %
Date: 2025-11-01 08:50:45 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.6.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     2527583 : LC3_INT searchMaxIndice(LC3_FLOAT* in, LC3_INT len)
      17             : {
      18     2527583 :     LC3_INT   max_i = 0, i;
      19     2527583 :     LC3_FLOAT max = 0;
      20             : 
      21     2527583 :     if (len <= 0) {
      22           0 :         return -128;
      23             :     }
      24             : 
      25    22595326 :     for (i = 0; i < len; i++) {
      26    20067743 :         if (in[i] > max) {
      27    10747634 :             max   = in[i];
      28    10747634 :             max_i = i;
      29             :         }
      30             :     }
      31             : 
      32     2527583 :     return max_i;
      33             : }
      34             : 
      35     1779817 : 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, LC3PLUS_FrameDuration 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             : #ifdef CR9_C_ADD_1p25MS
      40             : #ifdef NEW_SIGNALLING_SCHEME_1p25
      41             :                             ,LC3_INT16* Tx_ltpf
      42             : #else
      43             :                             ,LC3_INT16 Tx_ltpf
      44             : #endif
      45             : #endif
      46             : )
      47             : {
      48     1779817 :     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;
      49             :     LC3_INT   i, j, n, step, N, ltpf_active, pitch_search_delta,
      50     1779817 :         pitch_search_upsamp = 0, pitch_search_L_interpol1 = 0,
      51     1779817 :         t0_min = 0, t0_max = 0, t_min = 0, t_max = 0, temp2 = 0, t1 = 0, pitch_int = 0, pitch_fr = 0, midpoint = 0,
      52     1779817 :         delta_up = 0, delta_down = 0, pitch_index = 0, gain = 0, acflen = 0;
      53     1779817 :     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;
      54     1779817 :     LC3_FLOAT pitch = 0;
      55     1779817 :     LC3_FLOAT normCorrTh = 0.0f;
      56             : #if defined (CR9_C_ADD_1p25MS)
      57             :     LC3_INT16 activation_due_to_past_corr, activation_due_to_stable_pitch, activation;
      58             : #endif
      59             : 
      60             :     UNUSED(mem_norm_corr_past_past);
      61             : 
      62     1779817 :     if (hrmode) {
      63           0 :         normCorrTh = 0.4;
      64             :     } else {
      65     1779817 :         normCorrTh = 0.6;
      66             :     }
      67             : 
      68             :     /* Signal Buffer */
      69     1779817 :     N = xLen - 1;
      70     1779817 :     acflen = N;
      71             : 
      72     1779817 :     if (frame_dms == LC3PLUS_FRAME_DURATION_5MS)
      73             :     {
      74     1697637 :         acflen = 2 * N;
      75             :     }
      76     1779817 :     if (frame_dms == LC3PLUS_FRAME_DURATION_2p5MS)
      77             :     {
      78          16 :         acflen = 4 * N;
      79             :     }
      80             : #ifdef CR9_C_ADD_1p25MS
      81     1779817 :     if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS)
      82             :     {
      83           0 :         acflen = 8 * N;
      84             :     }
      85             : #endif
      86             : 
      87     1779817 :     x = &buffer[memLen];
      88             : 
      89     1779817 :     move_float( buffer, mem_old_x, memLen );
      90     1779817 :     move_float( x, xin, xLen );
      91     1779817 :     move_float( mem_old_x, &buffer[N], xLen + memLen - N );
      92             : 
      93     1779817 :     ltpf_active = 0;
      94     1779817 :     norm_corr   = 0;
      95             : 
      96     1779817 :     pitch_search_delta       = 4;
      97     1779817 :     pitch_search_upsamp      = 4;
      98     1779817 :     pitch_search_L_interpol1 = 4;
      99             : 
     100     1779817 :     if (pitch_ol_norm_corr > normCorrTh) {
     101             :         /* Search Bounds */
     102     1379764 :         t0_min = pitch_ol - pitch_search_delta;
     103     1379764 :         t0_max = pitch_ol + pitch_search_delta;
     104     1379764 :         t0_min = MAX(t0_min, MIN_PITCH_12K8);
     105     1379764 :         t0_max = MIN(t0_max, MAX_PITCH_12K8);
     106             : 
     107             :         /* Cross-Correlation Bounds */
     108     1379764 :         t_min = t0_min - pitch_search_L_interpol1;
     109     1379764 :         t_max = t0_max + pitch_search_L_interpol1;
     110             : 
     111             : #ifndef FIX_LTPF_PITCH_MEM_LEN
     112             :         acflen = N;
     113             : 
     114             :         if ( frame_dms == LC3PLUS_FRAME_DURATION_2p5MS )
     115             :         {
     116             :             acflen = 2 * N;
     117             :             x = x - N;
     118             :         }
     119             : #ifdef CR9_C_ADD_1p25MS
     120             :         if ( frame_dms == LC3PLUS_FRAME_DURATION_1p25MS )
     121             :         {
     122             :             acflen = 4 * N;
     123             :             x = x - 80;
     124             :         }
     125             : #endif
     126             : #else
     127     1379764 :         x = x - (memLen - LTPF_MEMIN_LEN);
     128             : #endif
     129             : 
     130             :         /* Compute norm */
     131     1379764 :         sum1 = sum2 = 0;
     132   177989556 :         for (j = 0; j < acflen; j++) {
     133   176609792 :             sum1 += x[j] * x[j];
     134   176609792 :             sum2 += x[j - t_min] * x[j - t_min];
     135             :         }
     136             : 
     137             :         /* Do first iteration outside of loop */
     138     1379764 :         sum = mac_loop(x, &x[-t_min], acflen);
     139             : 
     140     1379764 :         sum3      = LC3_SQRT(sum1 * sum2) + 1.00e-05;
     141     1379764 :         norm_corr = sum / sum3;
     142             : 
     143     1379764 :         norm_corr = MAX(0, norm_corr);
     144     1379764 :         cor[0] = norm_corr;
     145             : 
     146             :         /* Compute Cross-Correlation */
     147    23363928 :         for (i = t_min + 1; i <= t_max; i++) {
     148    21984164 :             sum = mac_loop(x, &x[-i], acflen);
     149             : 
     150    21984164 :             sum2 = sum2 + x[-i]*x[-i]
     151    21984164 :                             - x[acflen - 1 - ( i - 1 )]*x[acflen - 1 - ( i - 1 )];
     152             : 
     153    21984164 :             sum3      = LC3_SQRT(sum1 * sum2) + 1.00e-05;
     154    21984164 :             norm_corr = sum / sum3;
     155             : 
     156    21984164 :             norm_corr = MAX(0, norm_corr);
     157    21984164 :             cor[i - t_min] = norm_corr;
     158             : 
     159             :         }
     160             : 
     161             :         /* Find Integer Pitch-Lag */
     162     1379764 :         temp2 = searchMaxIndice(&cor[pitch_search_L_interpol1], t_max - t_min - pitch_search_L_interpol1 - pitch_search_L_interpol1 + 1);
     163             : 
     164     1379764 :         t1 = temp2 + t0_min;
     165     1379764 :         assert(t1 >= t0_min && t1 <= t0_max);
     166             : 
     167             :         /* Find Fractional Pitch-Lag */
     168     1379764 :         if (t1 >= RES2_PITCH_12K8) {
     169      231945 :             pitch_int = t1;
     170      231945 :             pitch_fr  = 0;
     171             :         } else {
     172     1147819 :             j = 0;
     173             : 
     174    20607878 :             for (i = 0; i < pitch_search_upsamp * (t_max - t_min) + 1; i = i + pitch_search_upsamp) {
     175    19460059 :                 cor_up[i] = cor[j];
     176    19460059 :                 j++;
     177             :             }
     178             : 
     179    42257847 :             for (i = 0; i < pitch_search_upsamp * (t0_max - t0_min + 1); i++) {
     180    41110028 :                 sum = mac_loop(&cor_up[i], (const LC3_FLOAT *)inter4_1, 32);
     181             : 
     182    41110028 :                 cor_int[i] = sum;
     183             :             }
     184             : 
     185     1147819 :             if (t1 >= RES4_PITCH_12K8) {
     186       54346 :                 step = 2;
     187             :             } else {
     188     1093473 :                 step = 1;
     189             :             }
     190             : 
     191     1147819 :             midpoint = pitch_search_upsamp * (t1 - t0_min) + 1;
     192     1147819 :             delta_up = pitch_search_upsamp - step;
     193             : 
     194     1147819 :             if (t1 == t0_min) {
     195       25466 :                 delta_down = 0;
     196             :             } else {
     197     1122353 :                 delta_down = pitch_search_upsamp - step;
     198             :             }
     199             : 
     200     1147819 :             j = 0;
     201     9983219 :             for (i = midpoint - delta_down - 1; i <= midpoint + delta_up; i = i + step) {
     202     8835400 :                 cor[j] = cor_int[i];
     203     8835400 :                 j++;
     204             :             }
     205             : 
     206             : 
     207     1147819 :             temp2    = searchMaxIndice(cor, ((midpoint + delta_up) - (midpoint - delta_down)) / step + 1);
     208     1147819 :             pitch_fr = temp2 * step - delta_down;
     209             : 
     210     1147819 :             if (pitch_fr >= 0) {
     211     1019312 :                 pitch_int = t1;
     212             :             } else {
     213      128507 :                 pitch_int = t1 - 1;
     214      128507 :                 pitch_fr  = pitch_search_upsamp + pitch_fr;
     215             :             }
     216             :         }
     217             : 
     218     1379764 :         assert((pitch_int <= MAX_PITCH_12K8 && pitch_int >= RES2_PITCH_12K8 && pitch_fr == 0) ||
     219             :                (pitch_int < RES2_PITCH_12K8 && pitch_int >= RES4_PITCH_12K8 && (pitch_fr == 0 || pitch_fr == 2)) ||
     220             :                (pitch_int < RES4_PITCH_12K8 && pitch_int >= MIN_PITCH_12K8 &&
     221             :                 (pitch_fr == 0 || pitch_fr == 1 || pitch_fr == 2 || pitch_fr == 3)));
     222             : 
     223     1379764 :         if (pitch_int < RES4_PITCH_12K8) {
     224     1093650 :             pitch_index = pitch_int * 4 + pitch_fr - (MIN_PITCH_12K8 * 4);
     225      286114 :         } else if (pitch_int < RES2_PITCH_12K8) {
     226       54169 :             pitch_index = pitch_int * 2 + floor(pitch_fr / 2) - (RES4_PITCH_12K8 * 2) + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4);
     227             :         } else {
     228      231945 :             pitch_index = pitch_int - RES2_PITCH_12K8 + ((RES4_PITCH_12K8 - MIN_PITCH_12K8) * 4) + ((RES2_PITCH_12K8 - RES4_PITCH_12K8) * 2);
     229             :         }
     230             : 
     231     1379764 :         assert(pitch_index >= 0 && pitch_index < 512);
     232     1379764 :         pitch = (LC3_FLOAT) pitch_int + (LC3_FLOAT) pitch_fr / 4.0;
     233             : 
     234             : 
     235             :         /* Normalized Correlation */
     236     1379764 :         sum1 = sum2 = sum3 = 0;
     237   177989556 :         for (n = 0; n < acflen; n++)
     238             :         {
     239   176609792 :             cor_tmp = x[n + 1] * enc_inter_filter[0][0] +
     240   176609792 :                            x[n]     * enc_inter_filter[0][1] +
     241   176609792 :                            x[n - 1] * enc_inter_filter[0][2];
     242             : 
     243   176609792 :             cor_int_tmp = x[n - pitch_int + 1] * enc_inter_filter[pitch_fr][0] +
     244   176609792 :                            x[n - pitch_int]     * enc_inter_filter[pitch_fr][1] +
     245   176609792 :                            x[n - pitch_int - 1] * enc_inter_filter[pitch_fr][2] +
     246   176609792 :                            x[n - pitch_int - 2] * enc_inter_filter[pitch_fr][3];
     247             : 
     248   176609792 :             sum1 += cor_tmp * cor_int_tmp;
     249   176609792 :             sum2 += cor_tmp * cor_tmp;
     250   176609792 :             sum3 += cor_int_tmp * cor_int_tmp;
     251             :         }
     252             : 
     253     1379764 :         sum2      = LC3_SQRT(sum2 * sum3) + 1.00e-05;
     254     1379764 :         norm_corr = sum1 / sum2;
     255             : 
     256     1379764 :         assert(norm_corr >= -1.00001 && norm_corr <= 1.00001);
     257     1379764 :         norm_corr = MIN(1, MAX(-1, norm_corr));
     258     1379764 :         if (norm_corr < 0) {
     259          90 :             norm_corr = 0;
     260             :         }
     261             : 
     262     1379764 :         if (ltpf_enable == 1)
     263             :         {
     264             :             /* Decision if ltpf active */
     265             : #if defined (CR9_C_ADD_1p25MS)
     266           0 :             activation_due_to_past_corr = mem_norm_corr_past[1] > 0.94;
     267           0 :             activation_due_to_stable_pitch = 1;
     268           0 :             if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS)
     269             :             {
     270           0 :                 activation_due_to_past_corr &= (mem_norm_corr_past[2] > 0.94);
     271           0 :                 activation_due_to_past_corr &= (mem_norm_corr_past[3] > 0.94);
     272           0 :                 activation_due_to_past_corr &= (mem_norm_corr_past[4] > 0.94);
     273             : 
     274           0 :                 activation_due_to_stable_pitch =  LC3_FMAX(pitch, *mem_pitch) * 0.7f < LC3_FMIN(pitch, *mem_pitch);
     275             :             }
     276           0 :             activation = activation_due_to_past_corr && activation_due_to_stable_pitch;
     277           0 :             if ((*mem_on == 0 && (frame_dms == LC3PLUS_FRAME_DURATION_10MS || activation) && mem_norm_corr_past[0] > 0.94 &&
     278           0 :                  norm_corr > 0.94) ||
     279           0 :                 ((*mem_on == 1 && norm_corr > 0.9) && activation_due_to_stable_pitch) ||
     280           0 :                 (*mem_on == 1 && LC3_FABS(pitch - *mem_pitch) < 2 && (norm_corr - mem_norm_corr_past[0]) > -0.1 &&
     281           0 :                  norm_corr > 0.84))
     282             :             {
     283           0 :                 ltpf_active = 1;
     284             :             }
     285             : #else
     286             :             if ((*mem_on == 0 && (frame_dms == LC3PLUS_FRAME_DURATION_10MS || *mem_norm_corr_past_past > 0.94) && *mem_norm_corr_past > 0.94 &&
     287             :                  norm_corr > 0.94) ||
     288             :                 (*mem_on == 1 && norm_corr > 0.9) ||
     289             :                 (*mem_on == 1 && LC3_FABS(pitch - *mem_pitch) < 2 && (norm_corr - *mem_norm_corr_past) > -0.1 &&
     290             :                  norm_corr > 0.84))
     291             :             {
     292             :                 ltpf_active = 1;
     293             :             }
     294             : #endif
     295             :         }
     296             : 
     297     1379764 :         gain = 4;
     298             :     } else {
     299      400053 :         gain      = 0;
     300      400053 :         norm_corr = pitch_ol_norm_corr;
     301      400053 :         pitch     = 0;
     302             :     }
     303             : 
     304     1779817 :     if (gain > 0) {
     305     1379764 :         param[0] = 1;
     306     1379764 :         param[1] = ltpf_active;
     307     1379764 :         param[2] = pitch_index;
     308     1379764 :         *bits    = 11;
     309             :     } else {
     310      400053 :         zero_int(param, 3);
     311             : 
     312      400053 :         *bits = 1;
     313             :     }
     314             : 
     315             : 
     316             : #ifdef CR9_C_ADD_1p25MS
     317             : #ifdef NEW_SIGNALLING_SCHEME_1p25
     318     1779817 :     if (frame_dms == LC3PLUS_FRAME_DURATION_1p25MS)
     319             :     {
     320           0 :         LC3_INT32 tmp = MIN(*Tx_ltpf, 1);  /* 0 == phaseA, 1==PhaseB ) */
     321             :                                            /* tmp [0 or 1} will points to 2 ltp bits in any  case */
     322           0 :         if ( param[0] == 0 && tmp != 0 )
     323             :         {
     324             :             /* pitch correlation dropped from high(ltp active || ltpf_active) to low  (no ltp info at all ),
     325             :                we select to NOT transmit  the remaining phaseB lag info for potential use in a next possible PLC frame */
     326           0 :             *Tx_ltpf = 0;      /* kill the lag transmission state from the encoder side */
     327             :                                /* tmp  stays  0 or 1 */
     328             :         }
     329             : 
     330             :         /* 00      (ltp=0, ltpf=0, no Phase 2b),
     331             :            010     (ltp=1, ltpf=0, phaseA,   7b),
     332             :            011     (ltp=1, ltpf=0, phaseB ,  7b),  lowered lag res for PLC
     333             :            10x     (ltp=1, ltpf=1) phaseA    6b)
     334             :            11x     (ltp=1, ltpf=1) phaseB    7b)
     335             :         */
     336             : 
     337           0 :         if (param[0] != 0)
     338             :         {
     339           0 :             if (param[1] == 0)
     340             :             {  /* ltp active, PLC usage case LTPF inactive  01[PhaseA]=010=2, or 01[phaseB]=011=3
     341             :                  path ltp active  and ltpf inactive  */
     342           0 :                 tmp = (0x02 | tmp);    /* phase Info  in LSB b0, LTPFactive in b1, tmp becomes  2 or 3 */
     343             :             }
     344             :             else
     345             :             {   /*param[1] != 0*/  /* ltp active,  ltpf  active  */
     346           0 :                 assert(param[2] >= 0 && param[2] <= 511);
     347           0 :                 tmp = (0x04 | (tmp << 1));  /* LTPF in b2, phase b1,  always zero in b0 , tmp becomes  4 or 6 */
     348             :                 /* 100=4 for phase A */
     349             :                 /* 110=6 for phase B */
     350             :             }
     351             :         }
     352           0 :         assert(tmp >= 0 && tmp < 8);
     353           0 :         *bits = lrsns_ltp_bits[tmp];  /*      one of { 2,2,  7,7 , 6,6, 7,7} */
     354             :                                       /* tmp=idx  is   0,1   2,3   4,5, 6,7  */
     355             : 
     356           0 :         assert(*bits == 2 || *bits == 6 || *bits == 7);
     357             :     }
     358             : #endif
     359             : #else
     360             :         assert(*bits == 1  || *bits == 11);
     361             : #endif
     362             : 
     363     1779817 :     if (frame_dms < LC3PLUS_FRAME_DURATION_10MS) {
     364             : #if defined (CR9_C_ADD_1p25MS)
     365     1697653 :         move_float(&mem_norm_corr_past[1], &mem_norm_corr_past[0], LEN_MEM_NORMCORR-1);
     366             : #else
     367             :         *mem_norm_corr_past_past = *mem_norm_corr_past;
     368             : #endif
     369             :     }
     370             : 
     371     1779817 :     *mem_norm_corr_past = norm_corr;
     372     1779817 :     *mem_on             = ltpf_active;
     373     1779817 :     *mem_pitch          = pitch;
     374     1779817 : }

Generated by: LCOV version 1.14