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