Coverage Report

Created: 2025-08-28 07:12

/src/opus/celt/celt_lpc.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2009-2010 Xiph.Org Foundation
2
   Written by Jean-Marc Valin */
3
/*
4
   Redistribution and use in source and binary forms, with or without
5
   modification, are permitted provided that the following conditions
6
   are met:
7
8
   - Redistributions of source code must retain the above copyright
9
   notice, this list of conditions and the following disclaimer.
10
11
   - Redistributions in binary form must reproduce the above copyright
12
   notice, this list of conditions and the following disclaimer in the
13
   documentation and/or other materials provided with the distribution.
14
15
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19
   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*/
27
28
#ifdef HAVE_CONFIG_H
29
#include "config.h"
30
#endif
31
32
#include "celt_lpc.h"
33
#include "stack_alloc.h"
34
#include "mathops.h"
35
#include "pitch.h"
36
37
void _celt_lpc(
38
      opus_val16       *_lpc, /* out: [0...p-1] LPC coefficients      */
39
const opus_val32 *ac,  /* in:  [0...p] autocorrelation values  */
40
int          p
41
)
42
52.1k
{
43
52.1k
   int i, j;
44
52.1k
   opus_val32 r;
45
52.1k
   opus_val32 error = ac[0];
46
#ifdef FIXED_POINT
47
   opus_val32 lpc[CELT_LPC_ORDER];
48
#else
49
52.1k
   float *lpc = _lpc;
50
52.1k
#endif
51
52
52.1k
   OPUS_CLEAR(lpc, p);
53
#ifdef FIXED_POINT
54
   if (ac[0] != 0)
55
#else
56
52.1k
   if (ac[0] > 1e-10f)
57
50.9k
#endif
58
50.9k
   {
59
360k
      for (i = 0; i < p; i++) {
60
         /* Sum up this iteration's reflection coefficient */
61
336k
         opus_val32 rr = 0;
62
2.48M
         for (j = 0; j < i; j++)
63
2.14M
            rr += MULT32_32_Q31(lpc[j],ac[i - j]);
64
336k
         rr += SHR32(ac[i + 1],6);
65
336k
         r = -frac_div32(SHL32(rr,6), error);
66
         /*  Update LPC coefficients and total error */
67
336k
         lpc[i] = SHR32(r,6);
68
1.49M
         for (j = 0; j < (i+1)>>1; j++)
69
1.15M
         {
70
1.15M
            opus_val32 tmp1, tmp2;
71
1.15M
            tmp1 = lpc[j];
72
1.15M
            tmp2 = lpc[i-1-j];
73
1.15M
            lpc[j]     = tmp1 + MULT32_32_Q31(r,tmp2);
74
1.15M
            lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
75
1.15M
         }
76
77
336k
         error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
78
         /* Bail out once we get 30 dB gain */
79
#ifdef FIXED_POINT
80
         if (error<=SHR32(ac[0],10))
81
            break;
82
#else
83
336k
         if (error<=.001f*ac[0])
84
26.5k
            break;
85
336k
#endif
86
336k
      }
87
50.9k
   }
88
#ifdef FIXED_POINT
89
   {
90
      /* Convert the int32 lpcs to int16 and ensure there are no wrap-arounds.
91
         This reuses the logic in silk_LPC_fit() and silk_bwexpander_32(). Any bug
92
         fixes should also be applied there. */
93
      int iter, idx = 0;
94
      opus_val32 maxabs, absval, chirp_Q16, chirp_minus_one_Q16;
95
96
      for (iter = 0; iter < 10; iter++) {
97
         maxabs = 0;
98
         for (i = 0; i < p; i++) {
99
            absval = ABS32(lpc[i]);
100
            if (absval > maxabs) {
101
               maxabs = absval;
102
               idx = i;
103
            }
104
         }
105
         maxabs = PSHR32(maxabs, 13);  /* Q25->Q12 */
106
107
         if (maxabs > 32767) {
108
            maxabs = MIN32(maxabs, 163838);
109
            chirp_Q16 = QCONST32(0.999, 16) - DIV32(SHL32(maxabs - 32767, 14),
110
                                                    SHR32(MULT32_32_32(maxabs, idx + 1), 2));
111
            chirp_minus_one_Q16 = chirp_Q16 - 65536;
112
113
            /* Apply bandwidth expansion. */
114
            for (i = 0; i < p - 1; i++) {
115
               lpc[i] = MULT32_32_Q16(chirp_Q16, lpc[i]);
116
               chirp_Q16 += PSHR32(MULT32_32_32(chirp_Q16, chirp_minus_one_Q16), 16);
117
            }
118
            lpc[p - 1] = MULT32_32_Q16(chirp_Q16, lpc[p - 1]);
119
         } else {
120
            break;
121
         }
122
      }
123
124
      if (iter == 10) {
125
         /* If the coeffs still do not fit into the 16 bit range after 10 iterations,
126
            fall back to the A(z)=1 filter. */
127
         OPUS_CLEAR(lpc, p);
128
         _lpc[0] = 4096;  /* Q12 */
129
      } else {
130
         for (i = 0; i < p; i++) {
131
            _lpc[i] = EXTRACT16(PSHR32(lpc[i], 13));  /* Q25->Q12 */
132
         }
133
      }
134
   }
135
#endif
136
52.1k
}
137
138
139
void celt_fir_c(
140
         const opus_val16 *x,
141
         const opus_val16 *num,
142
         opus_val16 *y,
143
         int N,
144
         int ord,
145
         int arch)
146
104k
{
147
104k
   int i,j;
148
104k
   VARDECL(opus_val16, rnum);
149
104k
   SAVE_STACK;
150
104k
   celt_assert(x != y);
151
104k
   ALLOC(rnum, ord, opus_val16);
152
2.60M
   for(i=0;i<ord;i++)
153
2.50M
      rnum[i] = num[ord-i-1];
154
12.7M
   for (i=0;i<N-3;i+=4)
155
12.6M
   {
156
12.6M
      opus_val32 sum[4];
157
12.6M
      sum[0] = SHL32(EXTEND32(x[i  ]), SIG_SHIFT);
158
12.6M
      sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
159
12.6M
      sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
160
12.6M
      sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
161
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
162
      {
163
         opus_val32 sum_c[4];
164
         memcpy(sum_c, sum, sizeof(sum_c));
165
         xcorr_kernel_c(rnum, x+i-ord, sum_c, ord);
166
#endif
167
12.6M
         xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
168
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
169
         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
170
      }
171
#endif
172
12.6M
      y[i  ] = SROUND16(sum[0], SIG_SHIFT);
173
12.6M
      y[i+1] = SROUND16(sum[1], SIG_SHIFT);
174
12.6M
      y[i+2] = SROUND16(sum[2], SIG_SHIFT);
175
12.6M
      y[i+3] = SROUND16(sum[3], SIG_SHIFT);
176
12.6M
   }
177
188k
   for (;i<N;i++)
178
84.0k
   {
179
84.0k
      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
180
2.10M
      for (j=0;j<ord;j++)
181
2.01M
         sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
182
84.0k
      y[i] = SROUND16(sum, SIG_SHIFT);
183
84.0k
   }
184
104k
   RESTORE_STACK;
185
104k
}
186
187
void celt_iir(const opus_val32 *_x,
188
         const opus_val16 *den,
189
         opus_val32 *_y,
190
         int N,
191
         int ord,
192
         opus_val16 *mem,
193
         int arch)
194
104k
{
195
#ifdef SMALL_FOOTPRINT
196
   int i,j;
197
   (void)arch;
198
   for (i=0;i<N;i++)
199
   {
200
      opus_val32 sum = _x[i];
201
      for (j=0;j<ord;j++)
202
      {
203
         sum -= MULT16_16(den[j],mem[j]);
204
      }
205
      for (j=ord-1;j>=1;j--)
206
      {
207
         mem[j]=mem[j-1];
208
      }
209
      mem[0] = SROUND16(sum, SIG_SHIFT);
210
      _y[i] = sum;
211
   }
212
#else
213
104k
   int i,j;
214
104k
   VARDECL(opus_val16, rden);
215
104k
   VARDECL(opus_val16, y);
216
104k
   SAVE_STACK;
217
218
104k
   celt_assert((ord&3)==0);
219
104k
   ALLOC(rden, ord, opus_val16);
220
104k
   ALLOC(y, N+ord, opus_val16);
221
2.60M
   for(i=0;i<ord;i++)
222
2.50M
      rden[i] = den[ord-i-1];
223
2.60M
   for(i=0;i<ord;i++)
224
2.50M
      y[i] = -mem[ord-i-1];
225
62.1M
   for(;i<N+ord;i++)
226
62.0M
      y[i]=0;
227
15.6M
   for (i=0;i<N-3;i+=4)
228
15.5M
   {
229
      /* Unroll by 4 as if it were an FIR filter */
230
15.5M
      opus_val32 sum[4];
231
15.5M
      sum[0]=_x[i];
232
15.5M
      sum[1]=_x[i+1];
233
15.5M
      sum[2]=_x[i+2];
234
15.5M
      sum[3]=_x[i+3];
235
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
236
      {
237
         opus_val32 sum_c[4];
238
         memcpy(sum_c, sum, sizeof(sum_c));
239
         xcorr_kernel_c(rden, y+i, sum_c, ord);
240
#endif
241
15.5M
         xcorr_kernel(rden, y+i, sum, ord, arch);
242
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
243
         celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
244
      }
245
#endif
246
      /* Patch up the result to compensate for the fact that this is an IIR */
247
15.5M
      y[i+ord  ] = -SROUND16(sum[0],SIG_SHIFT);
248
15.5M
      _y[i  ] = sum[0];
249
15.5M
      sum[1] = MAC16_16(sum[1], y[i+ord  ], den[0]);
250
15.5M
      y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
251
15.5M
      _y[i+1] = sum[1];
252
15.5M
      sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
253
15.5M
      sum[2] = MAC16_16(sum[2], y[i+ord  ], den[1]);
254
15.5M
      y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
255
15.5M
      _y[i+2] = sum[2];
256
257
15.5M
      sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
258
15.5M
      sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
259
15.5M
      sum[3] = MAC16_16(sum[3], y[i+ord  ], den[2]);
260
15.5M
      y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
261
15.5M
      _y[i+3] = sum[3];
262
15.5M
   }
263
104k
   for (;i<N;i++)
264
0
   {
265
0
      opus_val32 sum = _x[i];
266
0
      for (j=0;j<ord;j++)
267
0
         sum -= MULT16_16(rden[j],y[i+j]);
268
0
      y[i+ord] = SROUND16(sum,SIG_SHIFT);
269
0
      _y[i] = sum;
270
0
   }
271
2.60M
   for(i=0;i<ord;i++)
272
2.50M
      mem[i] = _y[N-i-1];
273
104k
   RESTORE_STACK;
274
104k
#endif
275
104k
}
276
277
int _celt_autocorr(
278
                   const opus_val16 *x,   /*  in: [0...n-1] samples x   */
279
                   opus_val32       *ac,  /* out: [0...lag-1] ac values */
280
                   const celt_coef  *window,
281
                   int          overlap,
282
                   int          lag,
283
                   int          n,
284
                   int          arch
285
                  )
286
52.1k
{
287
52.1k
   opus_val32 d;
288
52.1k
   int i, k;
289
52.1k
   int fastN=n-lag;
290
52.1k
   int shift;
291
52.1k
   const opus_val16 *xptr;
292
52.1k
   VARDECL(opus_val16, xx);
293
52.1k
   SAVE_STACK;
294
52.1k
   ALLOC(xx, n, opus_val16);
295
52.1k
   celt_assert(n>0);
296
52.1k
   celt_assert(overlap>=0);
297
52.1k
   if (overlap == 0)
298
18.4k
   {
299
18.4k
      xptr = x;
300
33.6k
   } else {
301
34.4M
      for (i=0;i<n;i++)
302
34.4M
         xx[i] = x[i];
303
4.07M
      for (i=0;i<overlap;i++)
304
4.03M
      {
305
4.03M
         opus_val16 w = COEF2VAL16(window[i]);
306
4.03M
         xx[i] = MULT16_16_Q15(x[i],w);
307
4.03M
         xx[n-i-1] = MULT16_16_Q15(x[n-i-1],w);
308
4.03M
      }
309
33.6k
      xptr = xx;
310
33.6k
   }
311
52.1k
   shift=0;
312
#ifdef FIXED_POINT
313
   {
314
      opus_val32 ac0;
315
      ac0 = 1+(n<<7);
316
      if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9);
317
      for(i=(n&1);i<n;i+=2)
318
      {
319
         ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9);
320
         ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9);
321
      }
322
323
      shift = celt_ilog2(ac0)-30+10;
324
      shift = (shift)/2;
325
      if (shift>0)
326
      {
327
         for(i=0;i<n;i++)
328
            xx[i] = PSHR32(xptr[i], shift);
329
         xptr = xx;
330
      } else
331
         shift = 0;
332
   }
333
#endif
334
52.1k
   celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
335
985k
   for (k=0;k<=lag;k++)
336
933k
   {
337
11.2M
      for (i = k+fastN, d = 0; i < n; i++)
338
10.2M
         d = MAC16_16(d, xptr[i], xptr[i-k]);
339
933k
      ac[k] += d;
340
933k
   }
341
#ifdef FIXED_POINT
342
   shift = 2*shift;
343
   if (shift<=0)
344
      ac[0] += SHL32((opus_int32)1, -shift);
345
   if (ac[0] < 268435456)
346
   {
347
      int shift2 = 29 - EC_ILOG(ac[0]);
348
      for (i=0;i<=lag;i++)
349
         ac[i] = SHL32(ac[i], shift2);
350
      shift -= shift2;
351
   } else if (ac[0] >= 536870912)
352
   {
353
      int shift2=1;
354
      if (ac[0] >= 1073741824)
355
         shift2++;
356
      for (i=0;i<=lag;i++)
357
         ac[i] = SHR32(ac[i], shift2);
358
      shift += shift2;
359
   }
360
#endif
361
362
52.1k
   RESTORE_STACK;
363
52.1k
   return shift;
364
52.1k
}