LCOV - code coverage report
Current view: top level - lib_lc3plus - tns_coder.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 189 0.0 %
Date: 2025-05-23 08:37:30 Functions: 0 5 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 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, LC3_INT 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 >= 50) {
     163           0 :         numfilters = 2;
     164             :     } else {
     165           0 :         numfilters = 1;
     166             :     }
     167             : 
     168             :     /* 40 * frame_dms / 10 = 4 * frame_dms */
     169           0 :     if (N > 4 * frame_dms)
     170             :     {
     171           0 :         N = 4 * frame_dms;
     172           0 :         fs = 40000;
     173             :     }
     174             : 
     175           0 :     if (numfilters == 1) {
     176           0 :         startfreq[0] = floor(600 * N * 2 / fs) + 1;
     177           0 :         stopfreq[0]  = N;
     178             :     } else {
     179           0 :         startfreq[0] = floor(600 * N * 2 / fs) + 1;
     180           0 :         startfreq[1] = N / 2 + 1;
     181           0 :         stopfreq[0]  = N / 2;
     182           0 :         stopfreq[1]  = N;
     183             :     }
     184             :     
     185           0 :     switch (frame_dms)
     186             :     {
     187           0 :         case 25:
     188           0 :             maxOrder      = 4;
     189           0 :             nSubdivisions = 2.0;
     190           0 :             break;
     191           0 :         case 50:
     192           0 :             maxOrder      = 4;
     193           0 :             nSubdivisions = 2.0;
     194           0 :             break;
     195           0 :         case 75:
     196           0 :             maxOrder      = 8;
     197           0 :             nSubdivisions = 3;
     198           0 :             break;
     199           0 :         case 100:
     200           0 :             maxOrder      = 8;
     201           0 :             nSubdivisions = 3.0;
     202           0 :             break;
     203             :     }
     204             : 
     205           0 :     minPredictionGain = 1.5;
     206             : 
     207           0 :     if (nBits >= 4.8 * frame_dms) {
     208           0 :         order = order1_tns;
     209             :     } else {
     210           0 :         order = order2_tns;
     211             :     }
     212             :     
     213             :     /* Processing */
     214           0 :     if (bw_cutoff_idx >= 3 && numfilters == 2) {
     215           0 :         numfilters   = 2;
     216           0 :         startfreq[1] = bw_fcbin / 2 + 1;
     217           0 :         stopfreq[0]  = bw_fcbin / 2;
     218           0 :         stopfreq[1]  = bw_fcbin;
     219             :     } else {
     220           0 :         numfilters  = 1;    
     221           0 :         stopfreq[0] = bw_fcbin;
     222             :     }
     223             : 
     224           0 :     bits = 0;
     225             : 
     226           0 :     for (f = 0; f < numfilters; f++) {
     227           0 :         subdiv_len = ((LC3_FLOAT)stopfreq[f] + 1.0 - (LC3_FLOAT)startfreq[f]) / nSubdivisions;
     228             : 
     229           0 :         zero_float(r, MAXLAG+1);
     230             : 
     231           0 :         for (sub = 1; sub <= nSubdivisions; sub++) {
     232           0 :             subdiv_startfreq = floor(subdiv_len * (sub - 1)) + startfreq[f] - 1;
     233           0 :             subdiv_stopfreq  = floor(subdiv_len * sub) + startfreq[f] - 1;
     234             :             
     235           0 :             if (fs == 32000 && frame_dms == 75)
     236             :             {
     237           0 :                 if (subdiv_startfreq == 83)
     238             :                 {
     239           0 :                     subdiv_startfreq = 82;
     240             :                 }
     241             :                 
     242           0 :                 if (subdiv_stopfreq == 83)
     243             :                 {
     244           0 :                     subdiv_stopfreq = 82;
     245             :                 }
     246             :                 
     247           0 :                 if (subdiv_startfreq == 160)
     248             :                 {
     249           0 :                     subdiv_startfreq = 159;
     250             :                 }
     251             :                 
     252           0 :                 if (subdiv_stopfreq == 160)
     253             :                 {
     254           0 :                     subdiv_stopfreq = 159;
     255             :                 }
     256             :             }
     257             : 
     258           0 :             sum = 0;
     259           0 :             for (i = subdiv_startfreq; i < subdiv_stopfreq; i++) {
     260           0 :                 sum += x[i] * x[i];
     261             :             }
     262             : 
     263           0 :             if (sum < LC3_EPS) {
     264           0 :                 zero_float(r, MAXLAG+1);
     265           0 :                 r[0] = 1;
     266           0 :                 break;
     267             :             }
     268             : 
     269           0 :             xcorr(&x[subdiv_startfreq], xcorr_out, maxOrder, subdiv_stopfreq - subdiv_startfreq);
     270             : 
     271           0 :             inv_sum = 1.0 / sum;
     272           0 :             for (i = 0; i <= maxOrder; i++) {
     273           0 :                 r[i] = r[i] + xcorr_out[i] * inv_sum;
     274             :             }
     275             :         }
     276             : 
     277           0 :         for (i = 0; i <= maxOrder; i++) {
     278           0 :             r[i] = r[i] * lagw_tns[i];
     279             :         }
     280             : 
     281           0 :         levinsonDurbin(r, xcorr_out, rc_unq, &error_lev, maxOrder);
     282             : 
     283           0 :         predGain = r[0] / error_lev;
     284             : 
     285           0 :         if (predGain > minPredictionGain && near_nyquist_flag == 0) {
     286           0 :             tns = 1;
     287             :         } else {
     288           0 :             tns = 0;
     289             :         }
     290             : 
     291           0 :         bits++;
     292             : 
     293           0 :         if (tns == 1) {
     294           0 :             minPGfac = 0.85;
     295           0 :             maxPG    = 2;
     296           0 :             if (nBits >= 4.8 * frame_dms) {
     297           0 :                 maxPG = minPredictionGain;
     298             :             }
     299             : 
     300             :             /* LPC weighting */
     301           0 :             if (predGain < maxPG) {
     302           0 :                 alpha = (maxPG - predGain) * (minPGfac - 1.0) / (maxPG - minPredictionGain) + 1.0;
     303             : 
     304           0 :                 alpha_loc = 1;
     305           0 :                 for (i = 0; i <= maxOrder; i++) {
     306           0 :                     xcorr_out[i] = xcorr_out[i] * alpha_loc;
     307           0 :                     alpha_loc *= alpha;
     308             :                 }
     309             : 
     310           0 :                 poly2rc(xcorr_out, rc_unq, maxOrder + 1);
     311             :             }
     312             : 
     313             :             /* PARCOR Quantization */
     314           0 :             for (i = 0; i < maxOrder; i++)
     315             :             {
     316           0 :                 iIndex = 1;
     317           0 :                 x_val  = rc_unq[i];
     318             : 
     319           0 :                 while ((iIndex < 17) && (x_val > quants_thr_tns[iIndex - 1]))
     320             :                 {
     321           0 :                     iIndex = (iIndex + 1);
     322             :                 }
     323           0 :                 rc_idx_tmp[i] = (iIndex - 2);
     324             :             }
     325             :             
     326             :             /* Filter Order */
     327           0 :             order_tmp = 0;
     328           0 :             for (i = 0; i < maxOrder; i++) {
     329           0 :                 rc[i] = quants_pts_tns[rc_idx_tmp[i]];
     330             : 
     331           0 :                 if (rc[i] != 0) {
     332           0 :                     order_tmp = i + 1;
     333             :                 }
     334             :             }
     335             : 
     336           0 :             order_out[f] = order_tmp;
     337             : 
     338             :             // Disable TNS if order is 0:
     339           0 :             if (order_out[f] == 0) {
     340           0 :                 tns = 0;
     341             : 
     342             :                 // Jump to else statement
     343           0 :                 goto tns_disabled;
     344             :             }
     345           0 :             tmp = order[order_out[f] - 1];
     346             : 
     347             :             /* Huffman Coding of PARCOR coefficients */
     348           0 :             for (i = 0; i <= order_out[f] - 1; i++) {
     349           0 :                 tmp += huff_bits_tns[i][rc_idx_tmp[i]];
     350             :             }
     351             : 
     352           0 :             bits = bits + ceil((LC3_FLOAT)tmp / 2048.0);
     353             : 
     354           0 :             j = 0;
     355           0 :             for (i = f * 8; i <= f * 8 + order_out[f] - 1; i++) {
     356           0 :                 rc_idx[i] = rc_idx_tmp[j];
     357           0 :                 j++;
     358             :             }
     359             :         } else {
     360           0 : tns_disabled:
     361           0 :             order_out[f] = 0;
     362             :         }
     363             : 
     364             :         /* Filtering */
     365           0 :         if (tns == 1) {
     366           0 :             for (i = startfreq[f]; i <= stopfreq[f]; i++) {
     367           0 :                 s       = x[i - 1];
     368           0 :                 tmpSave = s;
     369             : 
     370           0 :                 for (j = 0; j < order_out[f] - 1; j++) {
     371           0 :                     tmp_fl = rc[j] * s + st[j];
     372           0 :                     s += rc[j] * st[j];
     373             : 
     374           0 :                     st[j]   = tmpSave;
     375           0 :                     tmpSave = tmp_fl;
     376             :                 }
     377             : 
     378           0 :                 s += rc[order_out[f] - 1] * st[order_out[f] - 1];
     379             : 
     380           0 :                 st[order_out[f] - 1] = tmpSave;
     381           0 :                 x[i - 1]             = s;
     382             :             }
     383             :         }
     384             :     }
     385             : 
     386           0 :     *tns_numfilters = numfilters;
     387           0 :     *bits_out       = bits;
     388           0 : }

Generated by: LCOV version 1.14