Coverage Report

Created: 2025-07-12 07:11

/src/opus/celt/celt.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (c) 2007-2008 CSIRO
2
   Copyright (c) 2007-2010 Xiph.Org Foundation
3
   Copyright (c) 2008 Gregory Maxwell
4
   Written by Jean-Marc Valin and Gregory Maxwell */
5
/*
6
   Redistribution and use in source and binary forms, with or without
7
   modification, are permitted provided that the following conditions
8
   are met:
9
10
   - Redistributions of source code must retain the above copyright
11
   notice, this list of conditions and the following disclaimer.
12
13
   - Redistributions in binary form must reproduce the above copyright
14
   notice, this list of conditions and the following disclaimer in the
15
   documentation and/or other materials provided with the distribution.
16
17
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21
   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#ifdef HAVE_CONFIG_H
31
#include "config.h"
32
#endif
33
34
#define CELT_C
35
36
#include "os_support.h"
37
#include "mdct.h"
38
#include <math.h>
39
#include "celt.h"
40
#include "pitch.h"
41
#include "bands.h"
42
#include "modes.h"
43
#include "entcode.h"
44
#include "quant_bands.h"
45
#include "rate.h"
46
#include "stack_alloc.h"
47
#include "mathops.h"
48
#include "float_cast.h"
49
#include <stdarg.h>
50
#include "celt_lpc.h"
51
#include "vq.h"
52
53
#ifndef PACKAGE_VERSION
54
#define PACKAGE_VERSION "unknown"
55
#endif
56
57
#if defined(MIPSr1_ASM)
58
#include "mips/celt_mipsr1.h"
59
#endif
60
61
62
int resampling_factor(opus_int32 rate)
63
6.72k
{
64
6.72k
   int ret;
65
6.72k
   switch (rate)
66
6.72k
   {
67
#ifdef ENABLE_QEXT
68
   case 96000:
69
#endif
70
1.67k
   case 48000:
71
1.67k
      ret = 1;
72
1.67k
      break;
73
1.24k
   case 24000:
74
1.24k
      ret = 2;
75
1.24k
      break;
76
1.18k
   case 16000:
77
1.18k
      ret = 3;
78
1.18k
      break;
79
885
   case 12000:
80
885
      ret = 4;
81
885
      break;
82
1.74k
   case 8000:
83
1.74k
      ret = 6;
84
1.74k
      break;
85
0
   default:
86
0
#ifndef CUSTOM_MODES
87
0
      celt_assert(0);
88
0
#endif
89
0
      ret = 0;
90
0
      break;
91
6.72k
   }
92
6.72k
   return ret;
93
6.72k
}
94
95
96
#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
97
/* This version should be faster on ARM */
98
#ifdef OPUS_ARM_ASM
99
#ifndef NON_STATIC_COMB_FILTER_CONST_C
100
static
101
#endif
102
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
103
      celt_coef g10, celt_coef g11, celt_coef g12)
104
{
105
   opus_val32 x0, x1, x2, x3, x4;
106
   int i;
107
   x4 = SHL32(x[-T-2], 1);
108
   x3 = SHL32(x[-T-1], 1);
109
   x2 = SHL32(x[-T], 1);
110
   x1 = SHL32(x[-T+1], 1);
111
   for (i=0;i<N-4;i+=5)
112
   {
113
      opus_val32 t;
114
      x0=SHL32(x[i-T+2],1);
115
      t = MAC_COEF_32_ARM(x[i], g10, x2);
116
      t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
117
      t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
118
      t = SATURATE(t, SIG_SAT);
119
      y[i] = t;
120
      x4=SHL32(x[i-T+3],1);
121
      t = MAC_COEF_32_ARM(x[i+1], g10, x1);
122
      t = MAC_COEF_32_ARM(t, g11, ADD32(x0,x2));
123
      t = MAC_COEF_32_ARM(t, g12, ADD32(x4,x3));
124
      t = SATURATE(t, SIG_SAT);
125
      y[i+1] = t;
126
      x3=SHL32(x[i-T+4],1);
127
      t = MAC_COEF_32_ARM(x[i+2], g10, x0);
128
      t = MAC_COEF_32_ARM(t, g11, ADD32(x4,x1));
129
      t = MAC_COEF_32_ARM(t, g12, ADD32(x3,x2));
130
      t = SATURATE(t, SIG_SAT);
131
      y[i+2] = t;
132
      x2=SHL32(x[i-T+5],1);
133
      t = MAC_COEF_32_ARM(x[i+3], g10, x4);
134
      t = MAC_COEF_32_ARM(t, g11, ADD32(x3,x0));
135
      t = MAC_COEF_32_ARM(t, g12, ADD32(x2,x1));
136
      t = SATURATE(t, SIG_SAT);
137
      y[i+3] = t;
138
      x1=SHL32(x[i-T+6],1);
139
      t = MAC_COEF_32_ARM(x[i+4], g10, x3);
140
      t = MAC_COEF_32_ARM(t, g11, ADD32(x2,x4));
141
      t = MAC_COEF_32_ARM(t, g12, ADD32(x1,x0));
142
      t = SATURATE(t, SIG_SAT);
143
      y[i+4] = t;
144
   }
145
#ifdef CUSTOM_MODES
146
   for (;i<N;i++)
147
   {
148
      opus_val32 t;
149
      x0=SHL32(x[i-T+2],1);
150
      t = MAC_COEF_32_ARM(x[i], g10, x2);
151
      t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3));
152
      t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4));
153
      t = SATURATE(t, SIG_SAT);
154
      y[i] = t;
155
      x4=x3;
156
      x3=x2;
157
      x2=x1;
158
      x1=x0;
159
   }
160
#endif
161
}
162
#else
163
#ifndef NON_STATIC_COMB_FILTER_CONST_C
164
static
165
#endif
166
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
167
      celt_coef g10, celt_coef g11, celt_coef g12)
168
{
169
   opus_val32 x0, x1, x2, x3, x4;
170
   int i;
171
   x4 = x[-T-2];
172
   x3 = x[-T-1];
173
   x2 = x[-T];
174
   x1 = x[-T+1];
175
   for (i=0;i<N;i++)
176
   {
177
      x0=x[i-T+2];
178
      y[i] = x[i]
179
               + MULT_COEF_32(g10,x2)
180
               + MULT_COEF_32(g11,ADD32(x1,x3))
181
               + MULT_COEF_32(g12,ADD32(x0,x4));
182
#ifdef FIXED_POINT
183
      /* A bit of bias seems to help here. */
184
      y[i] = SUB32(y[i], 1);
185
#endif
186
      y[i] = SATURATE(y[i], SIG_SAT);
187
      x4=x3;
188
      x3=x2;
189
      x2=x1;
190
      x1=x0;
191
   }
192
193
}
194
#endif
195
#endif
196
197
#ifndef OVERRIDE_comb_filter
198
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
199
      opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
200
      const celt_coef *window, int overlap, int arch)
201
141M
{
202
141M
   int i;
203
   /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
204
141M
   celt_coef g00, g01, g02, g10, g11, g12;
205
141M
   opus_val32 x0, x1, x2, x3, x4;
206
141M
   static const opus_val16 gains[3][3] = {
207
141M
         {QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
208
141M
         {QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)},
209
141M
         {QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}};
210
#ifdef ENABLE_QEXT
211
   if (overlap==240) {
212
      opus_val32 mem_buf[COMBFILTER_MAXPERIOD+960];
213
      opus_val32 buf[COMBFILTER_MAXPERIOD+960];
214
      celt_coef new_window[120];
215
      int s;
216
      int N2;
217
      int overlap2;
218
      N2 = N/2;
219
      overlap2=overlap/2;
220
      /* At 96 kHz, we double the period and the spacing between taps, which is equivalent
221
         to creating a mirror image of the filter around 24 kHz. It also means we can process
222
         the even and odd samples completely independently. */
223
      for (s=0;s<2;s++) {
224
         opus_val32 *yptr;
225
         for (i=0;i<overlap2;i++) new_window[i] = window[2*i+s];
226
         for (i=0;i<COMBFILTER_MAXPERIOD+N2;i++) mem_buf[i] = x[2*i+s-2*COMBFILTER_MAXPERIOD];
227
         if (x==y) {
228
            yptr = mem_buf+COMBFILTER_MAXPERIOD;
229
         } else {
230
            for (i=0;i<N2;i++) buf[i] = y[2*i+s];
231
            yptr = buf;
232
         }
233
         comb_filter(yptr, mem_buf+COMBFILTER_MAXPERIOD, T0, T1, N2, g0, g1, tapset0, tapset1, new_window, overlap2, arch);
234
         for (i=0;i<N2;i++) y[2*i+s] = yptr[i];
235
      }
236
      return;
237
   }
238
#endif
239
141M
   if (g0==0 && g1==0)
240
141M
   {
241
      /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
242
141M
      if (x!=y)
243
141M
         OPUS_MOVE(y, x, N);
244
141M
      return;
245
141M
   }
246
   /* When the gain is zero, T0 and/or T1 is set to zero. We need
247
      to have then be at least 2 to avoid processing garbage data. */
248
113k
   T0 = IMAX(T0, COMBFILTER_MINPERIOD);
249
113k
   T1 = IMAX(T1, COMBFILTER_MINPERIOD);
250
113k
   g00 = MULT_COEF_TAPS(g0, gains[tapset0][0]);
251
113k
   g01 = MULT_COEF_TAPS(g0, gains[tapset0][1]);
252
113k
   g02 = MULT_COEF_TAPS(g0, gains[tapset0][2]);
253
113k
   g10 = MULT_COEF_TAPS(g1, gains[tapset1][0]);
254
113k
   g11 = MULT_COEF_TAPS(g1, gains[tapset1][1]);
255
113k
   g12 = MULT_COEF_TAPS(g1, gains[tapset1][2]);
256
113k
   x1 = x[-T1+1];
257
113k
   x2 = x[-T1  ];
258
113k
   x3 = x[-T1-1];
259
113k
   x4 = x[-T1-2];
260
   /* If the filter didn't change, we don't need the overlap */
261
113k
   if (g0==g1 && T0==T1 && tapset0==tapset1)
262
29.7k
      overlap=0;
263
10.1M
   for (i=0;i<overlap;i++)
264
10.0M
   {
265
10.0M
      celt_coef f;
266
10.0M
      x0=x[i-T1+2];
267
10.0M
      f = MULT_COEF(window[i],window[i]);
268
10.0M
      y[i] = x[i]
269
10.0M
               + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g00),x[i-T0])
270
10.0M
               + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
271
10.0M
               + MULT_COEF_32(MULT_COEF((COEF_ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
272
10.0M
               + MULT_COEF_32(MULT_COEF(f,g10),x2)
273
10.0M
               + MULT_COEF_32(MULT_COEF(f,g11),ADD32(x1,x3))
274
10.0M
               + MULT_COEF_32(MULT_COEF(f,g12),ADD32(x0,x4));
275
#ifdef FIXED_POINT
276
      /* A bit of bias seems to help here. */
277
      y[i] = SUB32(y[i], 3);
278
#endif
279
10.0M
      y[i] = SATURATE(y[i], SIG_SAT);
280
10.0M
      x4=x3;
281
10.0M
      x3=x2;
282
10.0M
      x2=x1;
283
10.0M
      x1=x0;
284
285
10.0M
   }
286
113k
   if (g1==0)
287
6.58k
   {
288
      /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
289
6.58k
      if (x!=y)
290
6.58k
         OPUS_MOVE(y+overlap, x+overlap, N-overlap);
291
6.58k
      return;
292
6.58k
   }
293
294
   /* Compute the part with the constant filter. */
295
107k
   comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
296
107k
}
297
#endif /* OVERRIDE_comb_filter */
298
299
/* TF change table. Positive values mean better frequency resolution (longer
300
   effective window), whereas negative values mean better time resolution
301
   (shorter effective window). The second index is computed as:
302
   4*isTransient + 2*tf_select + per_band_flag */
303
const signed char tf_select_table[4][8] = {
304
    /*isTransient=0     isTransient=1 */
305
      {0, -1, 0, -1,    0,-1, 0,-1}, /* 2.5 ms */
306
      {0, -1, 0, -2,    1, 0, 1,-1}, /* 5 ms */
307
      {0, -2, 0, -3,    2, 0, 1,-1}, /* 10 ms */
308
      {0, -2, 0, -3,    3, 0, 1,-1}, /* 20 ms */
309
};
310
311
312
void init_caps(const CELTMode *m,int *cap,int LM,int C)
313
62.5M
{
314
62.5M
   int i;
315
1.37G
   for (i=0;i<m->nbEBands;i++)
316
1.31G
   {
317
1.31G
      int N;
318
1.31G
      N=(m->eBands[i+1]-m->eBands[i])<<LM;
319
1.31G
      cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2;
320
1.31G
   }
321
62.5M
}
322
323
324
325
const char *opus_strerror(int error)
326
0
{
327
0
   static const char * const error_strings[8] = {
328
0
      "success",
329
0
      "invalid argument",
330
0
      "buffer too small",
331
0
      "internal error",
332
0
      "corrupted stream",
333
0
      "request not implemented",
334
0
      "invalid state",
335
0
      "memory allocation failed"
336
0
   };
337
0
   if (error > 0 || error < -7)
338
0
      return "unknown error";
339
0
   else
340
0
      return error_strings[-error];
341
0
}
342
343
const char *opus_get_version_string(void)
344
0
{
345
0
    return "libopus " PACKAGE_VERSION
346
    /* Applications may rely on the presence of this substring in the version
347
       string to determine if they have a fixed-point or floating-point build
348
       at runtime. */
349
#ifdef FIXED_POINT
350
          "-fixed"
351
#endif
352
#ifdef FUZZING
353
          "-fuzzing"
354
#endif
355
0
          ;
356
0
}