LCOV - code coverage report
Current view: top level - lib_lc3plus - tns_coder.c (source / functions) Hit Total Coverage
Test: Coverage on main -- long test vectors @ a21f94bc6bac334fe001a5bad2f7b32b79038097 Lines: 0 195 0.0 %
Date: 2025-11-01 09:50:07 Functions: 0 5 0.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 void xcorr(LC3_FLOAT* in, LC3_FLOAT* out, LC3_INT lag, LC3_INT inLen);
      15             : static void levdown(LC3_FLOAT* anxt, LC3_FLOAT* out_a, LC3_INT* len);
      16             : static void poly2rc(LC3_FLOAT* a, LC3_FLOAT* out, LC3_INT len);
      17             : 
      18           0 : void xcorr(LC3_FLOAT* in, LC3_FLOAT* out, LC3_INT lag, LC3_INT inLen)
      19             : {
      20             :         LC3_INT32   m;
      21             : 
      22             : 
      23           0 :     for (m = 0; m <= lag; m++) {
      24             :         /* Calculate correlation */
      25           0 :         out[m] = mac_loop(in, &in[m], (inLen - m));
      26             :     }
      27           0 : }
      28             : 
      29           0 : void levinsonDurbin(LC3_FLOAT* r, LC3_FLOAT* out_lev, LC3_FLOAT* rc_unq, LC3_FLOAT* error, LC3_INT len)
      30             : {
      31             :     LC3_INT   t, i, j;
      32             :     LC3_FLOAT g, v, sum, buf_tmp[10];
      33             : 
      34           0 :     g          = r[1] / r[0];
      35           0 :     out_lev[0] = g;
      36             : 
      37           0 :     v         = (1.0 - g * g) * r[0];
      38           0 :     rc_unq[0] = -g;
      39             : 
      40           0 :     for (t = 1; t < len; t++) {
      41             : 
      42           0 :         sum = 0;
      43           0 :         for (i = 1; i <= t; i++) {
      44           0 :             sum += out_lev[i - 1] * r[i];
      45             :         }
      46             : 
      47           0 :         g = (r[t + 1] - sum) / v;
      48             : 
      49           0 :         j = 1;
      50           0 :         for (i = t - 1; i >= 0; i--) {
      51           0 :             buf_tmp[j] = out_lev[j - 1] - g * out_lev[i];
      52           0 :             j++;
      53             :         }
      54             : 
      55           0 :         move_float(&out_lev[1], &buf_tmp[1], len);
      56             : 
      57           0 :         out_lev[0] = g;
      58             : 
      59           0 :         v         = v * (1 - g * g);
      60           0 :         rc_unq[t] = -g;
      61             :     }
      62             : 
      63             :     /* Reorder out_lev */
      64           0 :     out_lev[0] = 1;
      65           0 :     j          = 1;
      66           0 :     for (i = len - 1; i >= 0; i--) {
      67           0 :         buf_tmp[j] = -out_lev[i];
      68           0 :         j++;
      69             :     }
      70             : 
      71           0 :     move_float(&out_lev[1], &buf_tmp[1], (len - 1));
      72             : 
      73           0 :     out_lev[len] = rc_unq[len - 1];
      74             : 
      75           0 :     *error = v;
      76           0 : }
      77             : 
      78           0 : void levdown(LC3_FLOAT* anxt, LC3_FLOAT* out_a, LC3_INT* len)
      79             : {
      80             :     LC3_INT32   i, j;
      81             :     LC3_FLOAT tmp_buf[8], knxt;
      82             :     LC3_FLOAT norm;
      83             : 
      84           0 :         memset(tmp_buf, 0, 8 * sizeof(LC3_FLOAT));
      85             :     /* Initial length = 9 */
      86             : 
      87             :     /* Drop the leading 1 */
      88             : 
      89           0 :     *len = *len - 1; /* Lenght = 8 */
      90             : 
      91             :     /* Last coefficient */
      92           0 :     knxt = anxt[*len]; /* At [7] */
      93             : 
      94           0 :     *len = *len - 1; /* Lenght = 7 */
      95             : 
      96           0 :     j = 0;
      97           0 :     for (i = *len - 1; i >= 0; i--) {
      98           0 :         tmp_buf[j] = knxt * anxt[i + 1];
      99           0 :         j++;
     100             :     }
     101             :     
     102           0 :     norm = 1.0 / (1.0 - (LC3_FABS(knxt)) * (LC3_FABS(knxt)));
     103             : 
     104           0 :     out_a[0] = 1;
     105           0 :     for (i = 0; i < *len; i++) {
     106           0 :         out_a[i + 1] = (anxt[i + 1] - tmp_buf[i]) * norm;
     107             :     }
     108             : 
     109           0 :     *len = *len + 1; /* Length = 8 */
     110           0 : }
     111             : 
     112           0 : void poly2rc(LC3_FLOAT* a, LC3_FLOAT* out, LC3_INT len)
     113             : {
     114             :     LC3_INT   k, i, len_old;
     115             :     LC3_FLOAT buf[9];
     116             : 
     117           0 :     len_old = len;
     118             : 
     119           0 :     zero_float(out, len - 1);
     120             : 
     121             :     /* Length = 9 */
     122             : 
     123             :     /* Normalize */
     124           0 :     for (i = 0; i < len; i++) {
     125           0 :         a[i] = a[i] / a[0];
     126             :     }
     127             : 
     128           0 :     out[len - 1] = a[len - 1];
     129             : 
     130             :     /* Process */
     131           0 :     for (k = len - 2; k >= 0; k--) {
     132           0 :         levdown(a, buf, &len);
     133           0 :         out[k] = buf[len - 1]; /* Store last value */
     134             : 
     135           0 :         move_float(a, buf, len);
     136             :     }
     137             : 
     138             :     /* Shift output array by one to the left to lose leading 1 */
     139           0 :     for (i = 0; i < len_old - 1; i++) {
     140           0 :         out[i] = out[i + 1];
     141             :     }
     142           0 : }
     143             : 
     144             : 
     145           0 : void processTnsCoder_fl(LC3_FLOAT* x, LC3_INT bw_cutoff_idx, LC3_INT bw_fcbin, LC3_INT fs, LC3_INT N, LC3PLUS_FrameDuration frame_dms, LC3_INT nBits,
     146             :                         LC3_INT* order_out, LC3_INT* rc_idx, LC3_INT* tns_numfilters, LC3_INT* bits_out
     147             :                         , LC3_INT16 near_nyquist_flag
     148             : )
     149             : {
     150             :     LC3_INT i, stopfreq[2], startfreq[2], f, numfilters, maxOrder, bits, sub,
     151             :         subdiv_startfreq, subdiv_stopfreq, j, rc_idx_tmp[MAXLAG], order_tmp, tmp, tns;
     152             :     LC3_FLOAT minPGfac, minPredictionGain, maxPG, xcorr_out[MAXLAG + 1], sum,
     153             :           subdiv_len, nSubdivisions, r[MAXLAG + 1], rc_unq[MAXLAG + 1], error_lev, predGain,
     154           0 :           alpha, rc[MAXLAG], st[MAXLAG + 1] = {0}, s, tmpSave, tmp_fl;
     155             :     const LC3_INT* order;
     156             :     LC3_FLOAT inv_sum, x_val;
     157             :     LC3_FLOAT alpha_loc;
     158             :     LC3_INT32 iIndex;
     159             : 
     160             :     /* Init */
     161             : 
     162           0 :     if (fs >= 32000 && frame_dms >= LC3PLUS_FRAME_DURATION_5MS) {
     163           0 :         numfilters = 2;
     164             :     } else {
     165           0 :         numfilters = 1;
     166             :     }
     167             : 
     168             :     /* 40 * frame_dms / 10 = 4 * frame_dms */
     169           0 :     if (N > 40 * ((LC3_FLOAT) (frame_dms*1.25*10) / 10.0)) {
     170           0 :         N  = 40 * ((LC3_FLOAT) (frame_dms*1.25*10) / 10.0);
     171           0 :         fs = 40000;
     172             :     }
     173             : 
     174           0 :     if (numfilters == 1) {
     175           0 :         startfreq[0] = floor(600 * N * 2 / fs) + 1;
     176           0 :         stopfreq[0]  = N;
     177             :     } else {
     178           0 :         startfreq[0] = floor(600 * N * 2 / fs) + 1;
     179           0 :         startfreq[1] = N / 2 + 1;
     180           0 :         stopfreq[0]  = N / 2;
     181           0 :         stopfreq[1]  = N;
     182             :     }
     183             :     
     184           0 :     switch (frame_dms)
     185             :     {
     186             : #ifdef CR9_C_ADD_1p25MS
     187           0 :         case LC3PLUS_FRAME_DURATION_1p25MS:
     188           0 :             maxOrder      = 4;
     189           0 :             nSubdivisions = 2.0;
     190           0 :             break;
     191             : #endif
     192           0 :         case LC3PLUS_FRAME_DURATION_2p5MS:
     193           0 :             maxOrder      = 4;
     194           0 :             nSubdivisions = 2.0;
     195           0 :             break;
     196           0 :         case LC3PLUS_FRAME_DURATION_5MS:
     197           0 :             maxOrder      = 4;
     198           0 :             nSubdivisions = 2.0;
     199           0 :             break;
     200           0 :         case LC3PLUS_FRAME_DURATION_7p5MS:
     201           0 :             maxOrder      = 8;
     202           0 :             nSubdivisions = 3;
     203           0 :             break;
     204           0 :         case LC3PLUS_FRAME_DURATION_10MS:
     205           0 :             maxOrder      = 8;
     206           0 :             nSubdivisions = 3.0;
     207           0 :             break;
     208           0 :         case LC3PLUS_FRAME_DURATION_UNDEFINED:
     209           0 :             assert(0);
     210             :     }
     211             : 
     212           0 :     minPredictionGain = 1.5;
     213             : 
     214           0 :     if (nBits >= 4.8 * ((LC3_FLOAT) frame_dms * 1.25 * 10)) {
     215           0 :         order = order1_tns;
     216             :     } else {
     217           0 :         order = order2_tns;
     218             :     }
     219             :     
     220             :     /* Processing */
     221           0 :     if (bw_cutoff_idx >= 3 && numfilters == 2) {
     222           0 :         numfilters   = 2;
     223           0 :         startfreq[1] = bw_fcbin / 2 + 1;
     224           0 :         stopfreq[0]  = bw_fcbin / 2;
     225           0 :         stopfreq[1]  = bw_fcbin;
     226             :     } else {
     227           0 :         numfilters  = 1;    
     228           0 :         stopfreq[0] = bw_fcbin;
     229             :     }
     230             : 
     231           0 :     bits = 0;
     232             : 
     233           0 :     for (f = 0; f < numfilters; f++) {
     234           0 :         subdiv_len = ((LC3_FLOAT)stopfreq[f] + 1.0 - (LC3_FLOAT)startfreq[f]) / nSubdivisions;
     235             : 
     236           0 :         zero_float(r, MAXLAG+1);
     237             : 
     238           0 :         for (sub = 1; sub <= nSubdivisions; sub++) {
     239           0 :             subdiv_startfreq = floor(subdiv_len * (sub - 1)) + startfreq[f] - 1;
     240           0 :             subdiv_stopfreq  = floor(subdiv_len * sub) + startfreq[f] - 1;
     241             :             
     242           0 :             if (fs == 32000 && frame_dms == 75)
     243             :             {
     244           0 :                 if (subdiv_startfreq == 83)
     245             :                 {
     246           0 :                     subdiv_startfreq = 82;
     247             :                 }
     248             :                 
     249           0 :                 if (subdiv_stopfreq == 83)
     250             :                 {
     251           0 :                     subdiv_stopfreq = 82;
     252             :                 }
     253             :                 
     254           0 :                 if (subdiv_startfreq == 160)
     255             :                 {
     256           0 :                     subdiv_startfreq = 159;
     257             :                 }
     258             :                 
     259           0 :                 if (subdiv_stopfreq == 160)
     260             :                 {
     261           0 :                     subdiv_stopfreq = 159;
     262             :                 }
     263             :             }
     264             : 
     265           0 :             sum = 0;
     266           0 :             for (i = subdiv_startfreq; i < subdiv_stopfreq; i++) {
     267           0 :                 sum += x[i] * x[i];
     268             :             }
     269             : 
     270           0 :             if (sum < LC3_EPS) {
     271           0 :                 zero_float(r, MAXLAG+1);
     272           0 :                 r[0] = 1;
     273           0 :                 break;
     274             :             }
     275             : 
     276           0 :             xcorr(&x[subdiv_startfreq], xcorr_out, maxOrder, subdiv_stopfreq - subdiv_startfreq);
     277             : 
     278           0 :             inv_sum = 1.0 / sum;
     279           0 :             for (i = 0; i <= maxOrder; i++) {
     280           0 :                 r[i] = r[i] + xcorr_out[i] * inv_sum;
     281             :             }
     282             :         }
     283             : 
     284           0 :         for (i = 0; i <= maxOrder; i++) {
     285           0 :             r[i] = r[i] * lagw_tns[i];
     286             :         }
     287             : 
     288           0 :         levinsonDurbin(r, xcorr_out, rc_unq, &error_lev, maxOrder);
     289             : 
     290           0 :         predGain = r[0] / error_lev;
     291             : 
     292           0 :         if (predGain > minPredictionGain && near_nyquist_flag == 0) {
     293           0 :             tns = 1;
     294             :         } else {
     295           0 :             tns = 0;
     296             :         }
     297             : 
     298           0 :         bits++;
     299             : 
     300           0 :         if (tns == 1) {
     301           0 :             minPGfac = 0.85;
     302           0 :             maxPG    = 2;
     303           0 :             if (nBits >= 4.8 * frame_dms*1.25*10) {
     304           0 :                 maxPG = minPredictionGain;
     305             :             }
     306             : 
     307             :             /* LPC weighting */
     308           0 :             if (predGain < maxPG) {
     309           0 :                 alpha = (maxPG - predGain) * (minPGfac - 1.0) / (maxPG - minPredictionGain) + 1.0;
     310             : 
     311           0 :                 alpha_loc = 1;
     312           0 :                 for (i = 0; i <= maxOrder; i++) {
     313           0 :                     xcorr_out[i] = xcorr_out[i] * alpha_loc;
     314           0 :                     alpha_loc *= alpha;
     315             :                 }
     316             : 
     317           0 :                 poly2rc(xcorr_out, rc_unq, maxOrder + 1);
     318             :             }
     319             : 
     320             :             /* PARCOR Quantization */
     321           0 :             for (i = 0; i < maxOrder; i++)
     322             :             {
     323           0 :                 iIndex = 1;
     324           0 :                 x_val  = rc_unq[i];
     325             : 
     326           0 :                 while ((iIndex < 17) && (x_val > quants_thr_tns[iIndex - 1]))
     327             :                 {
     328           0 :                     iIndex = (iIndex + 1);
     329             :                 }
     330           0 :                 rc_idx_tmp[i] = (iIndex - 2);
     331             :             }
     332             :             
     333             :             /* Filter Order */
     334           0 :             order_tmp = 0;
     335           0 :             for (i = 0; i < maxOrder; i++) {
     336           0 :                 rc[i] = quants_pts_tns[rc_idx_tmp[i]];
     337             : 
     338           0 :                 if (rc[i] != 0) {
     339           0 :                     order_tmp = i + 1;
     340             :                 }
     341             :             }
     342             : 
     343           0 :             order_out[f] = order_tmp;
     344             : 
     345             :             /* Disable TNS if order is 0: */
     346           0 :             if (order_out[f] == 0) {
     347           0 :                 tns = 0;
     348             : 
     349             :                 /* Jump to else statement */
     350           0 :                 goto tns_disabled;
     351             :             }
     352           0 :             tmp = order[order_out[f] - 1];
     353             : 
     354             :             /* Huffman Coding of PARCOR coefficients */
     355           0 :             for (i = 0; i <= order_out[f] - 1; i++) {
     356           0 :                 tmp += huff_bits_tns[i][rc_idx_tmp[i]];
     357             :             }
     358             : 
     359           0 :             bits = bits + ceil((LC3_FLOAT)tmp / 2048.0);
     360             : 
     361           0 :             j = 0;
     362           0 :             for (i = f * 8; i <= f * 8 + order_out[f] - 1; i++) {
     363           0 :                 rc_idx[i] = rc_idx_tmp[j];
     364           0 :                 j++;
     365             :             }
     366             :         } else {
     367           0 : tns_disabled:
     368           0 :             order_out[f] = 0;
     369             :         }
     370             : 
     371             :         /* Filtering */
     372           0 :         if (tns == 1) {
     373           0 :             for (i = startfreq[f]; i <= stopfreq[f]; i++) {
     374           0 :                 s       = x[i - 1];
     375           0 :                 tmpSave = s;
     376             : 
     377           0 :                 for (j = 0; j < order_out[f] - 1; j++) {
     378           0 :                     tmp_fl = rc[j] * s + st[j];
     379           0 :                     s += rc[j] * st[j];
     380             : 
     381           0 :                     st[j]   = tmpSave;
     382           0 :                     tmpSave = tmp_fl;
     383             :                 }
     384             : 
     385           0 :                 s += rc[order_out[f] - 1] * st[order_out[f] - 1];
     386             : 
     387           0 :                 st[order_out[f] - 1] = tmpSave;
     388           0 :                 x[i - 1]             = s;
     389             :             }
     390             :         }
     391             :     }
     392             : 
     393           0 :     *tns_numfilters = numfilters;
     394           0 :     *bits_out       = bits;
     395           0 : }

Generated by: LCOV version 1.14