LCOV - code coverage report
Current view: top level - lib_lc3plus - ltpf_decoder_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 152 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 "functions.h"
      11             : 
      12             : static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, Word16 pitch_int, Word16 pitch_fr,
      13             :                               Word16 gain, Word16 scale_fac_idx, Word16 fs_idx,
      14             :                               Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */);
      15             : 
      16             : /*************************************************************************/
      17             : 
      18             : 
      19           0 : void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word16 fs_idx, Word16 old_y_len,
      20             :                              Word16 *old_e, Word16 *x_in, Word16 *old_x, Word16 *y_out, Word16 *old_y, Word16 ltpf,
      21             :                              Word16 ltpf_active, Word16 pitch_index, Word16 *old_pitch_int, Word16 *old_pitch_fr,
      22             :                              Word16 *old_gain, Word16 *mem_ltpf_active, Word16 scale_fac_idx, Word16 bfi,
      23             :                              Word16 concealMethod,
      24             :                              Word16 damping, Word16 *old_scale_fac_idx,                      
      25             :                              Word32 *rel_pitch_change, Word16 hrmode, Word16 frame_dms,
      26             :                              Word8 *scratchBuffer)
      27             : {
      28             :     Counter i;
      29             :     Word16  gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34;
      30             :     Word16 *x, *y;
      31             :     Word16 *z;                          
      32             :     Word32 tmp32, pitch_delta;
      33             : #ifdef DYNMEM_COUNT
      34             :     Dyn_Mem_In("process_ltpf_decoder_fx", sizeof(struct {
      35             :                    Counter i;
      36             :                    Word16  gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34;
      37             :                    Word16 *x, *y;
      38             :                    Word16 *z;                          
      39             :                    Word32 tmp32, pitch_delta;
      40             :                }));
      41             : #endif
      42             : 
      43           0 :     z = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = MAX_LEN / 4 + 10 */
      44             : 
      45             : 
      46           0 :     test();
      47           0 :     IF ((sub(bfi, 1) == 0) && (sub(concealMethod, LC3_CON_TEC_NS_STD) == 0))
      48             :     {
      49           0 :         ltpf        = 0; move16();
      50           0 :         ltpf_active = 0; move16();
      51           0 :         pitch_int = 0; move16();
      52           0 :         pitch_fr  = 0; move16();
      53           0 :         gain      = 0; move16();
      54             :     }
      55             : 
      56             :     /* Filter parameters */
      57           0 :     IF (sub(bfi, 1) != 0)
      58             :     {
      59           0 :         IF (ltpf == 0)
      60             :         {
      61           0 :             pitch_int = 0; move16();
      62           0 :             pitch_fr  = 0; move16();
      63             :         }
      64             :         ELSE
      65             :         {
      66             :             /* Decode pitch */
      67           0 :             IF (sub(pitch_index, 380) < 0)
      68             :             {
      69           0 :                 pitch_int = shr_pos(add(pitch_index, 64), 2);
      70           0 :                 pitch_fr  = add(sub(pitch_index, shl_pos(pitch_int, 2)), 128);
      71             :             }
      72           0 :             ELSE IF (sub(pitch_index, 440) < 0)
      73             :             {
      74           0 :                 pitch_int = shr_pos(sub(pitch_index, 126), 1);
      75           0 :                 pitch_fr  = sub(sub(shl_pos(pitch_index, 1), shl_pos(pitch_int, 2)), 252);
      76             :             }
      77             :             ELSE
      78             :             {
      79           0 :                 pitch_int = sub(pitch_index, 283);
      80           0 :                 pitch_fr  = 0; move16();
      81             :             }
      82           0 :             pitch     = add(shl_pos(pitch_int, 2), pitch_fr);
      83             : #ifdef ENABLE_HR_MODE
      84           0 :             IF (sub(fs_idx, 5) == 0)
      85             :             {
      86           0 :                 pitch = round_fx(L_shl_pos(L_mult(shl_pos(pitch, 2), pitch_scale[4]), 1));
      87             :             }
      88             :             ELSE
      89             : #endif
      90             :             {
      91           0 :                 pitch = mult_r(shl_pos(pitch, 2), pitch_scale[fs_idx]);
      92             :             }
      93           0 :             pitch_int = shr_pos(pitch, 2);
      94           0 :             pitch_fr  = sub(pitch, shl_pos(pitch_int, 2));
      95             :         }
      96             : 
      97             :         /* Decode gain */
      98           0 :         if (scale_fac_idx < 0)
      99             :         {
     100           0 :             ltpf_active = 0;
     101           0 :             ASSERT(!(*old_scale_fac_idx < 0 && *mem_ltpf_active == 1));
     102             :         }
     103           0 :         IF (ltpf_active == 0)
     104             :         {
     105           0 :             gain = 0; move16();
     106             :         }
     107             :         ELSE
     108             :         {
     109           0 :             ASSERT(scale_fac_idx >= 0);
     110           0 :             gain = gain_scale_fac[scale_fac_idx]; move16();
     111             :         }
     112             :     }
     113           0 :     ELSE IF (sub(concealMethod, LC3_CON_TEC_NS_STD) != 0)
     114             :     {
     115             :         /* fix to avoid not initialized filtering for concelament 
     116             :            might be necessary in case of bit errors or rate switching */
     117           0 :         if (scale_fac_idx < 0) {
     118           0 :             if (*mem_ltpf_active && *old_scale_fac_idx>=0)
     119             :             {
     120           0 :                 scale_fac_idx = *old_scale_fac_idx;
     121             :             }
     122             :         }
     123             :         
     124           0 :         ltpf_active = *mem_ltpf_active; move16();
     125             : 
     126           0 :         if ((sub(concealMethod, LC3_CON_TEC_PHASE_ECU) == 0))
     127             :         { /* always start fade off to save filtering WMOPS for the remaining 7.5 ms  */
     128           0 :             assert(bfi == 1);
     129           0 :             ltpf_active = 0; move16(); /*always start fade off , still maintain  *mem_ltpf_active */
     130             :         }
     131             : 
     132           0 :         pitch_int = *old_pitch_int;
     133           0 :         pitch_fr  = *old_pitch_fr;
     134           0 :         gain      = mult_r(*old_gain, damping);
     135             :     }
     136             : 
     137           0 :     test(); test();
     138           0 :     IF (ltpf_active == 0 && *mem_ltpf_active == 0)
     139             :     {
     140             :         /* LTPF inactive */
     141             : 
     142           0 :         basop_memmove(y_out, x_in, L_frame * sizeof(Word16));
     143             : 
     144             :         /* Update */
     145           0 :         s = sub(*old_e, *x_e);
     146           0 :         IF (s > 0)
     147             :         {
     148           0 :             basop_memmove(old_y, &old_y[L_frame], (old_y_len - L_frame) * sizeof(Word16));
     149             : 
     150           0 :             IF (sub(s, 15) > 0)
     151             :             {
     152           0 :                 basop_memset(&old_y[old_y_len - L_frame], 0, (L_frame) * sizeof(Word16));
     153             : 
     154           0 :                 basop_memset(old_x, 0, (old_x_len) * sizeof(Word16));
     155             :             }
     156             :             ELSE
     157             :             {
     158           0 :                 FOR (i = 0; i < L_frame; i++)
     159             :                 {
     160           0 :                     old_y[i + old_y_len - L_frame] = shr(x_in[i], s); move16();
     161             :                 }
     162           0 :                 FOR (i = 0; i < old_x_len; i++)
     163             :                 {
     164           0 :                     old_x[i] = shr(x_in[i + L_frame - old_x_len], s); move16();
     165             :                 }
     166             :             }
     167             :         }
     168             :         ELSE
     169             :         {
     170           0 :             IF (sub(s, -15) < 0)
     171             :             {
     172           0 :                 basop_memset(old_y, 0, (old_y_len - L_frame) * sizeof(Word16));
     173             :             }
     174             :             ELSE
     175             :             {
     176           0 :                 FOR (i = 0; i < old_y_len - L_frame; i++)
     177             :                 {
     178           0 :                     old_y[i] = shl(old_y[i + L_frame], s); move16();
     179             :                 }
     180             :             }
     181             : 
     182           0 :             basop_memmove(&old_y[old_y_len - L_frame], x_in, (L_frame) * sizeof(Word16));
     183             : 
     184           0 :             basop_memmove(old_x, &x_in[L_frame - old_x_len], (old_x_len) * sizeof(Word16));
     185             : 
     186           0 :             *old_e = *x_e; move16();
     187             :         }
     188             : 
     189           0 :     if (bfi == 0 && sub(hrmode,1) == 0 && (sub(frame_dms,50) == 0 || sub(frame_dms,25) == 0)){
     190           0 :         pitch_delta = abs_s(add(sub(*old_pitch_int,pitch_int) , shr_pos(sub(*old_pitch_fr, pitch_fr),2))); //int_old -int_new + (fr_old-fr_new) / 4.0));
     191           0 :         tmp32 = BASOP_Util_Divide3216_Scale_lc3plus(pitch_delta, MAX(add(*old_pitch_int, shr_pos(*old_pitch_fr,2)), 1),&s0);// = pitch_delta *2^15 / MAX(pitch_fl_c_old, 1);
     192           0 :         *rel_pitch_change = L_shl_pos(tmp32,s0+16);
     193             :     }
     194             : 
     195           0 :         *old_pitch_int   = pitch_int; move16();
     196           0 :         *old_pitch_fr    = pitch_fr;  move16();
     197           0 :         *old_gain        = 0;         move16();
     198           0 :         *mem_ltpf_active = 0;         move16();
     199             :     }
     200             :     ELSE
     201             :     {
     202             :         /* Input/Output buffers */
     203           0 :         x = old_x + old_x_len;
     204           0 :         y = old_y + old_y_len;
     205             :         
     206             : #ifdef ENABLE_HR_MODE
     207           0 :         assert(fs_idx < 5 && "Ltpf not supported for 96kHz!\n");
     208             : #endif
     209             :         
     210           0 :         N4  = ltpf_overlap_len[fs_idx]; move16();
     211           0 :         N34 = sub(L_frame, N4);         move16();
     212             : 
     213             :         /* Input */
     214           0 :         basop_memmove(x, x_in, (L_frame) * sizeof(Word16));
     215             : 
     216             :         /* Scaling */
     217           0 :         s0     = sub(s_min(getScaleFactor16_0(old_x, old_x_len), getScaleFactor16_0(old_y, old_y_len)), 1);
     218           0 :         *old_e = sub(*old_e, s0); move16();
     219           0 :         s1     = sub(getScaleFactor16(x, L_frame), 1);
     220           0 :         *x_e   = sub(*x_e, s1); move16();
     221           0 :         s      = sub(*old_e, *x_e);
     222           0 :         IF (s > 0)
     223             :         {
     224           0 :             Scale_sig(x, L_frame, sub(s1, s));
     225           0 :             Scale_sig(old_x, old_x_len, s0);
     226           0 :             Scale_sig(old_y, old_y_len, s0);
     227           0 :             *x_e = *old_e; move16();
     228             :         }
     229             :         ELSE
     230             :         {
     231           0 :             Scale_sig(x, L_frame, s1);
     232           0 :             Scale_sig(old_x, old_x_len, add(s0, s));
     233           0 :             Scale_sig(old_y, old_y_len, add(s0, s));
     234           0 :             *old_e = *x_e; move16();
     235             :         }
     236             : 
     237             :         /* Filtering */
     238           0 :         IF (ltpf_active == 0)
     239             :         {
     240           0 :             ltpf_synth_filter(y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx,
     241             :                               -1);
     242             :         }
     243           0 :         ELSE IF (*mem_ltpf_active == 0)
     244             :         {
     245           0 :             ltpf_synth_filter(y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 1);
     246             :         }
     247           0 :         ELSE IF (sub(pitch_int, *old_pitch_int) == 0 && sub(*old_pitch_fr, pitch_fr) == 0)
     248             :         {
     249           0 :             ltpf_synth_filter(y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 0);
     250             :         }
     251             :         ELSE
     252             :         {
     253           0 :             ltpf_synth_filter(y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx,
     254             :                               -1);
     255           0 :             basop_memmove(z, y - tilt_filter_len[fs_idx], (N4 + tilt_filter_len[fs_idx]) * sizeof(Word16));
     256           0 :             ltpf_synth_filter(y, z + tilt_filter_len[fs_idx], N4, pitch_int, pitch_fr, gain, scale_fac_idx,
     257             :                               fs_idx, 1);
     258             :         }
     259           0 :         IF (ltpf_active > 0)
     260             :         {
     261           0 :             ltpf_synth_filter(y + N4, x + N4, N34, pitch_int, pitch_fr, gain,
     262             :                               scale_fac_idx, fs_idx, 0);
     263             :         }
     264             :         ELSE
     265             :         {
     266           0 :             basop_memmove(&y[N4], &x[N4], N34 * sizeof(Word16));
     267             :         }
     268             : 
     269             :         /* Output */
     270           0 :         basop_memmove(y_out, y, (L_frame) * sizeof(Word16));
     271             : 
     272             :         /* Update */
     273           0 :         basop_memmove(old_x, &old_x[L_frame], (old_x_len) * sizeof(Word16));
     274             : 
     275           0 :         basop_memmove(old_y, &old_y[L_frame], (old_y_len) * sizeof(Word16));
     276             : 
     277           0 :         *old_pitch_int   = pitch_int;   move16();
     278           0 :         *old_pitch_fr    = pitch_fr;    move16();
     279           0 :         *old_gain        = gain;        move16();
     280           0 :         *mem_ltpf_active = ltpf_active; move16();
     281             :     }
     282             : 
     283           0 :     *old_scale_fac_idx = scale_fac_idx; move16();
     284             : 
     285             : #ifdef DYNMEM_COUNT
     286             :     Dyn_Mem_Out();
     287             : #endif
     288           0 : }
     289             : 
     290             : 
     291           0 : static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, Word16 pitch_int, Word16 pitch_fr,
     292             :                               Word16 gain, Word16 scale_fac_idx, Word16 fs_idx,
     293             :                               Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */)
     294             : {
     295             :     Word16 *x0;
     296             :     Word16 *y0;
     297             :     Word32  s;
     298             :     Word16  alpha, step;
     299             :     Word16  i, k;
     300             :     Counter j, l;
     301             : 
     302             : #ifdef DYNMEM_COUNT
     303             :     Dyn_Mem_In("ltpf_synth_filter", sizeof(struct {
     304             :                    Word16 *x0;
     305             :                    Word16 *y0;
     306             :                    Word32  s;
     307             :                    Word16  alpha, step;
     308             :                    Word16  i, k;
     309             :                    Counter j, l;
     310             :                }));
     311             : #endif
     312             : 
     313           0 :     ASSERT(scale_fac_idx >= 0);
     314             : 
     315           0 :     step  = 0; /* initialize just to avoid compiler warning */
     316           0 :     alpha = 0; /* initialize just to avoid compiler warning */
     317           0 :     x0    = &synth_ltp[-pitch_int + inter_filter_shift[fs_idx]];
     318           0 :     y0    = synth;
     319             : 
     320           0 :     alpha = 0; move16();
     321           0 :     IF (fade != 0)
     322             :     {
     323           0 :         if (fade < 0)
     324             :         {
     325           0 :             alpha = 0x7FFF; move16();
     326             :         }
     327             : 
     328             : /* step = 1.f/(float)(length); */
     329           0 :         if (sub(length, 20) == 0)
     330             :         {
     331           0 :             step = 1638 /*1.f/20.f Q15*/; move16();
     332             :         }
     333           0 :         if (sub(length, 40) == 0)
     334             :         {
     335           0 :             step = 819 /*1.f/40.f Q15*/; move16();
     336             :         }
     337           0 :         if (sub(length, 60) == 0)
     338             :         {
     339           0 :             step = 546 /*1.f/60.f Q15*/; move16();
     340             :         }
     341           0 :         if (sub(length, 80) == 0)
     342             :         {
     343           0 :             step = 409 /*1.f/80.f Q15*/; move16();
     344             :         }
     345           0 :         if (sub(length, 120) == 0)
     346             :         {
     347           0 :             step = 273 /*1.f/120.f Q15*/; move16();
     348             :         }
     349             : 
     350           0 :         if (fade < 0)
     351           0 :             step = negate(step);
     352             :     }
     353             : 
     354           0 :     FOR (j = 0; j < length; j++)
     355             :     {
     356           0 :         s = L_mult(x0[0], inter_filter[fs_idx][pitch_fr][0]);
     357           0 :         FOR (l = 1; l < inter_filter_len[fs_idx]; l++)
     358             :         {
     359           0 :             s = L_mac(s, x0[-l], inter_filter[fs_idx][pitch_fr][l]);
     360             :         }
     361           0 :         FOR (l = 0; l < tilt_filter_len[fs_idx]; l++)
     362             :         {
     363           0 :             s = L_msu(s, y0[-l], tilt_filter[fs_idx][scale_fac_idx][l]);
     364             :         }
     365             : 
     366           0 :         i = msu_r(s, y0[-l], tilt_filter[fs_idx][scale_fac_idx][l]);
     367             : 
     368           0 :         k = mult_r(gain, i);
     369             : 
     370           0 :         if (fade != 0)
     371           0 :             k = mult_r(k, alpha);
     372             : 
     373           0 :         synth_ltp[j] = add(synth[j], k); move16();
     374             : 
     375           0 :         if (fade != 0)
     376           0 :             alpha = add(alpha, step);
     377             : 
     378           0 :         x0++;
     379           0 :         y0++;
     380             :     }
     381             : 
     382             : #ifdef DYNMEM_COUNT
     383             :     Dyn_Mem_Out();
     384             : #endif
     385           0 : }
     386             : 

Generated by: LCOV version 1.14