LCOV - code coverage report
Current view: top level - lib_lc3plus - pc_classify_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 119 0.0 %
Date: 2025-08-23 01:22:27 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 "defines.h"
      11             : #include "constants.h"
      12             : #include "functions.h"
      13             : 
      14             : #define BLOCK_SIZE 3
      15             : #define THR1 8
      16             : #define FAC 9830 /* 0.3 */
      17             : 
      18             : void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover);
      19             : 
      20           0 : void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[],
      21             :                           Word16 yLen, Word16 spec_inv_idx, Word16 stab_fac, Word16 *bfi)
      22             : {
      23             :     Dyn_Mem_Deluxe_In(
      24             :         Word16  maxPitchBin, xover;
      25             :         Counter i;
      26             :         Word16  s, tmp16, full_nrg16, part_nrg16;
      27             :         Word32  full_nrg, part_nrg;
      28             :     );
      29             : 
      30             :     /* Apply classifier only if lower than 2kHz signal */
      31           0 :     IF (sub(DEPR_i_mult(spec_inv_idx, 10), shl_pos(frame_dms, 2)) < 0 )
      32             :     {
      33           0 :         IF (sub(stab_fac, 16384 /* 0.5 */) < 0)
      34             :         {
      35           0 :             *bfi = 1;
      36             :         }
      37           0 :         ELSE IF (sub(pitch_present, 1) == 0)
      38             :         {
      39           0 :             maxPitchBin = 8;  move16();
      40           0 :             IF (sub(frame_dms, 50) == 0)
      41             :             {
      42           0 :                 maxPitchBin = 4;  move16();
      43             :             }
      44             : 
      45             :             /* avoid phase discontinuity in low frequencies */
      46           0 :             peakDetector_fx(q_old_d_fx, yLen, &xover);
      47           0 :             test();
      48           0 :             IF (sub(spec_inv_idx, xover) < 0 || sub(spec_inv_idx, maxPitchBin) < 0)
      49             :             {
      50           0 :                 *bfi = 1;
      51             :             }
      52             :         }
      53             :         ELSE
      54             :         {
      55           0 :             s = getScaleFactor16(q_old_res_fx, yLen);
      56             : 
      57           0 :             part_nrg = 0;  move32();
      58           0 :             FOR (i = 0; i < spec_inv_idx; i++)
      59             :             {
      60           0 :                 tmp16    = shl_sat(q_old_res_fx[i], sub(s, 4));
      61           0 :                 part_nrg = L_mac0(part_nrg, tmp16, tmp16); /* exp = 2s - 8 */
      62             :             }
      63             : 
      64           0 :             full_nrg = part_nrg;  move32();
      65           0 :             FOR (i = spec_inv_idx; i < yLen; i++)
      66             :             {
      67           0 :                 tmp16    = shl_sat(q_old_res_fx[i], sub(s, 4));
      68           0 :                 full_nrg = L_mac0(full_nrg, tmp16, tmp16); /* exp = 2s - 8 */
      69             :             }
      70             : 
      71           0 :             s          = getScaleFactor32_lc3plus(&full_nrg, 1);
      72           0 :             full_nrg16 = extract_h(L_shl(full_nrg, s));
      73           0 :             part_nrg16 = extract_h(L_shl(part_nrg, s));
      74             : 
      75           0 :             tmp16 = mult(full_nrg16, 9830 /* 0.3 */);
      76             : 
      77           0 :             IF (part_nrg16 < tmp16)
      78             :             {
      79           0 :                 *bfi = 1;
      80             :             }
      81             :         }
      82             :     }
      83             : 
      84             :     Dyn_Mem_Deluxe_Out();
      85           0 : }
      86             : 
      87           0 : void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover)
      88             : {
      89             :     Dyn_Mem_Deluxe_In(
      90             :         Counter i, j;
      91             :         Word16  tmp16, c, s, s2, mean_block_nrg16;
      92             :         Word32  maxPeak, tmp32;
      93             :         Word32  mean_block_nrg, block_cent;
      94             :         Word16  cur_max, prev_max, next_max;
      95             :     );
      96             : 
      97           0 :     *xover = 0;
      98             : 
      99           0 :     s = getScaleFactor16(in_sig, yLen);
     100             : 
     101           0 :     mean_block_nrg = 0;  move32();
     102           0 :     FOR (i = 0; i < yLen; i++)
     103             :     {
     104           0 :         tmp16          = shl_sat(in_sig[i], sub(s, 4));
     105           0 :         mean_block_nrg = L_mac0(mean_block_nrg, tmp16, tmp16); /* exp = 2s - 8 */
     106             :     }
     107             : 
     108           0 :     s2               = getScaleFactor16(&yLen, 1);
     109           0 :     c                = shl(yLen, s2);
     110           0 :     mean_block_nrg16 = div_l(mean_block_nrg, c);                                        /* exp = 2s - 8 - s2 - 1 */
     111           0 :     mean_block_nrg   = L_shl(L_mult0(mean_block_nrg16, BLOCK_SIZE * THR1), add(4, s2)); /* exp = 2s - 5 */
     112             : 
     113           0 :     maxPeak = 0;  move32();
     114           0 :     c = sub(yLen, 2 * BLOCK_SIZE);
     115             : 
     116           0 :     test();
     117           0 :     IF (abs_s(in_sig[0]) >= abs_s(in_sig[1]))
     118             :     {
     119           0 :         block_cent = 0;  move32();
     120           0 :         FOR (j = 0; j <= 1; j++)
     121             :         {
     122           0 :             tmp16      = shl_sat(in_sig[j], sub(s, 2));
     123           0 :             block_cent = L_mac0(block_cent, tmp16, tmp16); /* -> exp = 2s - 4 */
     124             :         }
     125           0 :         block_cent = L_shr(block_cent, 1); /* exp = 2s - 5 */
     126             : 
     127           0 :         IF (L_sub(block_cent, mean_block_nrg) > 0)
     128             :         {
     129           0 :             cur_max = abs_s(in_sig[0]);
     130           0 :             cur_max = MAX(abs_s(in_sig[1]), cur_max);
     131             : 
     132           0 :             next_max = abs_s(in_sig[-1 + BLOCK_SIZE]);
     133           0 :             next_max = MAX(abs_s(in_sig[-1 + BLOCK_SIZE + 1]), next_max);
     134           0 :             next_max = MAX(abs_s(in_sig[-1 + BLOCK_SIZE + 2]), next_max);
     135             : 
     136           0 :             IF (sub(cur_max, next_max) > 0)
     137             :             {
     138           0 :                 maxPeak = block_cent;  move32();
     139           0 :                 *xover = 1;
     140             :             }
     141             :         }
     142             :     }
     143             : 
     144           0 :     FOR (i = 0; i < BLOCK_SIZE; i++)
     145             :     {
     146           0 :         test();
     147           0 :         IF (abs_s(in_sig[i + 1]) >= abs_s(in_sig[i]) && abs_s(in_sig[i + 1]) >= abs_s(in_sig[i + 2]))
     148             :         {
     149           0 :             block_cent = 0;  move32();
     150           0 :             FOR (j = 0; j < BLOCK_SIZE; j++)
     151             :             {
     152           0 :                 tmp16      = shl_sat(in_sig[i + j], sub(s, 2));
     153           0 :                 block_cent = L_mac0(block_cent, tmp16, tmp16); /* -> exp = 2s - 4 */
     154             :             }
     155           0 :             block_cent = L_shr(block_cent, 1); /* exp = 2s - 5 */
     156             : 
     157           0 :             IF (L_sub(block_cent, mean_block_nrg) > 0)
     158             :             {
     159           0 :                 cur_max = abs_s(in_sig[i]);
     160           0 :                 cur_max = MAX(abs_s(in_sig[i + 1]), cur_max);
     161           0 :                 cur_max = MAX(abs_s(in_sig[i + 2]), cur_max);
     162             : 
     163           0 :                 prev_max = 0;  move16();
     164           0 :                 FOR (j = i - BLOCK_SIZE; j <= i - 1; j++)
     165             :                 {
     166           0 :                     IF (j > 0)
     167             :                     {
     168           0 :                         prev_max = MAX(abs_s(in_sig[j]), prev_max);
     169             :                     }
     170             :                 }
     171             : 
     172           0 :                 next_max = abs_s(in_sig[i + BLOCK_SIZE]);
     173           0 :                 next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 1]), next_max);
     174           0 :                 next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 2]), next_max);
     175             : 
     176           0 :                 test();
     177           0 :                 IF (sub(cur_max, prev_max) >= 0 && sub(cur_max, next_max) > 0)
     178             :                 {
     179           0 :                     IF (L_sub(block_cent, maxPeak) >= 0)
     180             :                     {
     181           0 :                         maxPeak = block_cent;  move32();
     182           0 :                         *xover = sub(add(i, BLOCK_SIZE), 1);
     183             :                     }
     184             :                     ELSE
     185             :                     {
     186           0 :                         tmp32 = L_mult(FAC, extract_h(maxPeak));
     187             : 
     188           0 :                         tmp16 = extract_l(L_shr(maxPeak, 1));
     189           0 :                         tmp16 = s_and(tmp16, 0x7fff);
     190           0 :                         tmp16 = mult(FAC, tmp16);
     191           0 :                         tmp32 = L_add_sat(tmp32, tmp16);
     192             : 
     193           0 :                         IF (L_sub(block_cent, tmp32) > 0)
     194             :                         {
     195           0 :                             *xover = sub(add(i, BLOCK_SIZE), 1);
     196             :                         }
     197             :                     }
     198             :                 }
     199             :             }
     200             :         }
     201             :     }
     202             : 
     203           0 :     FOR (i = BLOCK_SIZE; i <= c; i++)
     204             :     {
     205           0 :         test();
     206           0 :         IF (abs_s(in_sig[i + 1]) >= abs_s(in_sig[i]) && abs_s(in_sig[i + 1]) >= abs_s(in_sig[i + 2]))
     207             :         {
     208           0 :             block_cent = 0;  move32();
     209           0 :             FOR (j = 0; j < BLOCK_SIZE; j++)
     210             :             {
     211           0 :                 tmp16      = shl_sat(in_sig[i + j], sub(s, 2));
     212           0 :                 block_cent = L_mac0(block_cent, tmp16, tmp16); /* -> exp = 2s - 4 */
     213             :             }
     214           0 :             block_cent = L_shr(block_cent, 1); /* exp = 2s - 5 */
     215             : 
     216           0 :             IF (L_sub(block_cent, mean_block_nrg) > 0)
     217             :             {
     218           0 :                 cur_max = abs_s(in_sig[i]);
     219           0 :                 cur_max = MAX(abs_s(in_sig[i + 1]), cur_max);
     220           0 :                 cur_max = MAX(abs_s(in_sig[i + 2]), cur_max);
     221             : 
     222           0 :                 prev_max = abs_s(in_sig[i - BLOCK_SIZE]);
     223           0 :                 prev_max = MAX(abs_s(in_sig[i - BLOCK_SIZE + 1]), prev_max);
     224           0 :                 prev_max = MAX(abs_s(in_sig[i - BLOCK_SIZE + 2]), prev_max);
     225             : 
     226           0 :                 next_max = abs_s(in_sig[i + BLOCK_SIZE]);
     227           0 :                 next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 1]), next_max);
     228           0 :                 next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 2]), next_max);
     229             : 
     230           0 :                 test();
     231           0 :                 IF (sub(cur_max, prev_max) >= 0 && sub(cur_max, next_max) > 0)
     232             :                 {
     233           0 :                     IF (L_sub(block_cent, maxPeak) >= 0)
     234             :                     {
     235           0 :                         maxPeak = block_cent;  move32();
     236           0 :                         *xover = sub(add(i, BLOCK_SIZE), 1);
     237             :                     }
     238             :                     ELSE
     239             :                     {
     240           0 :                         tmp32 = L_mult(FAC, extract_h(maxPeak));
     241             : 
     242           0 :                         tmp16 = extract_l(L_shr(maxPeak, 1));
     243           0 :                         tmp16 = s_and(tmp16, 0x7fff);
     244           0 :                         tmp16 = mult(FAC, tmp16);
     245           0 :                         tmp32 = L_add_sat(tmp32, tmp16);
     246             : 
     247           0 :                         IF (L_sub(block_cent, tmp32) > 0)
     248             :                         {
     249           0 :                             *xover = sub(add(i, BLOCK_SIZE), 1);
     250             :                         }
     251             :                     }
     252             :                 }
     253             :             }
     254             :         }
     255             :     }
     256             : 
     257             :     Dyn_Mem_Deluxe_Out();
     258           0 : }
     259             : 
     260             : 

Generated by: LCOV version 1.14