Coverage Report

Created: 2026-02-14 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/silk/A2NLSF.c
Line
Count
Source
1
/***********************************************************************
2
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3
Redistribution and use in source and binary forms, with or without
4
modification, are permitted provided that the following conditions
5
are met:
6
- Redistributions of source code must retain the above copyright notice,
7
this list of conditions and the following disclaimer.
8
- Redistributions in binary form must reproduce the above copyright
9
notice, this list of conditions and the following disclaimer in the
10
documentation and/or other materials provided with the distribution.
11
- Neither the name of Internet Society, IETF or IETF Trust, nor the
12
names of specific contributors, may be used to endorse or promote
13
products derived from this software without specific prior written
14
permission.
15
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
POSSIBILITY OF SUCH DAMAGE.
26
***********************************************************************/
27
28
/* Conversion between prediction filter coefficients and NLSFs  */
29
/* Requires the order to be an even number                      */
30
/* A piecewise linear approximation maps LSF <-> cos(LSF)       */
31
/* Therefore the result is not accurate NLSFs, but the two      */
32
/* functions are accurate inverses of each other                */
33
34
#ifdef HAVE_CONFIG_H
35
#include "config.h"
36
#endif
37
38
#include "SigProc_FIX.h"
39
#include "tables.h"
40
41
/* Number of binary divisions, when not in low complexity mode */
42
1.26G
#define BIN_DIV_STEPS_A2NLSF_FIX      3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
43
26.8k
#define MAX_ITERATIONS_A2NLSF_FIX    16
44
45
/* Helper function for A2NLSF(..)                    */
46
/* Transforms polynomials from cos(n*f) to cos(f)^n  */
47
static OPUS_INLINE void silk_A2NLSF_trans_poly(
48
    opus_int32          *p,                     /* I/O    Polynomial                                */
49
    const opus_int      dd                      /* I      Polynomial order (= filter order / 2 )    */
50
)
51
57.4M
{
52
57.4M
    opus_int k, n;
53
54
316M
    for( k = 2; k <= dd; k++ ) {
55
749M
        for( n = dd; n > k; n-- ) {
56
490M
            p[ n - 2 ] -= p[ n ];
57
490M
        }
58
259M
        p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
59
259M
    }
60
57.4M
}
61
/* Helper function for A2NLSF(..) */
62
/* Polynomial evaluation          */
63
static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16     */
64
    opus_int32          *p,                     /* I    Polynomial, Q16                         */
65
    const opus_int32    x,                      /* I    Evaluation point, Q12                   */
66
    const opus_int      dd                      /* I    Order                                   */
67
)
68
4.64G
{
69
4.64G
    opus_int   n;
70
4.64G
    opus_int32 x_Q16, y32;
71
72
4.64G
    y32 = p[ dd ];                                  /* Q16 */
73
4.64G
    x_Q16 = silk_LSHIFT( x, 4 );
74
75
4.64G
    if ( opus_likely( 8 == dd ) )
76
898M
    {
77
898M
        y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 );
78
898M
        y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 );
79
898M
        y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 );
80
898M
        y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 );
81
898M
        y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 );
82
898M
        y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 );
83
898M
        y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 );
84
898M
        y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 );
85
898M
    }
86
3.74G
    else
87
3.74G
    {
88
22.4G
        for( n = dd - 1; n >= 0; n-- ) {
89
18.7G
            y32 = silk_SMLAWW( p[ n ], y32, x_Q16 );    /* Q16 */
90
18.7G
        }
91
3.74G
    }
92
4.64G
    return y32;
93
4.64G
}
94
95
static OPUS_INLINE void silk_A2NLSF_init(
96
     const opus_int32    *a_Q16,
97
     opus_int32          *P,
98
     opus_int32          *Q,
99
     const opus_int      dd
100
)
101
28.7M
{
102
28.7M
    opus_int k;
103
104
    /* Convert filter coefs to even and odd polynomials */
105
28.7M
    P[dd] = silk_LSHIFT( 1, 16 );
106
28.7M
    Q[dd] = silk_LSHIFT( 1, 16 );
107
187M
    for( k = 0; k < dd; k++ ) {
108
158M
        P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ];    /* Q16 */
109
158M
        Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ];    /* Q16 */
110
158M
    }
111
112
    /* Divide out zeros as we have that for even filter orders, */
113
    /* z =  1 is always a root in Q, and                        */
114
    /* z = -1 is always a root in P                             */
115
187M
    for( k = dd; k > 0; k-- ) {
116
158M
        P[ k - 1 ] -= P[ k ];
117
158M
        Q[ k - 1 ] += Q[ k ];
118
158M
    }
119
120
    /* Transform polynomials from cos(n*f) to cos(f)^n */
121
28.7M
    silk_A2NLSF_trans_poly( P, dd );
122
28.7M
    silk_A2NLSF_trans_poly( Q, dd );
123
28.7M
}
124
125
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients      */
126
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
127
void silk_A2NLSF(
128
    opus_int16                  *NLSF,              /* O    Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
129
    opus_int32                  *a_Q16,             /* I/O  Monic whitening filter coefficients in Q16 [d]              */
130
    const opus_int              d                   /* I    Filter order (must be even)                                 */
131
)
132
28.7M
{
133
28.7M
    opus_int   i, k, m, dd, root_ix, ffrac;
134
28.7M
    opus_int32 xlo, xhi, xmid;
135
28.7M
    opus_int32 ylo, yhi, ymid, thr;
136
28.7M
    opus_int32 nom, den;
137
28.7M
    opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
138
28.7M
    opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
139
28.7M
    opus_int32 *PQ[ 2 ];
140
28.7M
    opus_int32 *p;
141
142
    /* Store pointers to array */
143
28.7M
    PQ[ 0 ] = P;
144
28.7M
    PQ[ 1 ] = Q;
145
146
28.7M
    dd = silk_RSHIFT( d, 1 );
147
148
28.7M
    silk_A2NLSF_init( a_Q16, P, Q, dd );
149
150
    /* Find roots, alternating between P and Q */
151
28.7M
    p = P;                          /* Pointer to polynomial */
152
153
28.7M
    xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
154
28.7M
    ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
155
156
28.7M
    if( ylo < 0 ) {
157
        /* Set the first NLSF to zero and move on to the next */
158
43
        NLSF[ 0 ] = 0;
159
43
        p = Q;                      /* Pointer to polynomial */
160
43
        ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
161
43
        root_ix = 1;                /* Index of current root */
162
28.7M
    } else {
163
28.7M
        root_ix = 0;                /* Index of current root */
164
28.7M
    }
165
28.7M
    k = 1;                          /* Loop counter */
166
28.7M
    i = 0;                          /* Counter for bandwidth expansions applied */
167
28.7M
    thr = 0;
168
3.66G
    while( 1 ) {
169
        /* Evaluate polynomial */
170
3.66G
        xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
171
3.66G
        yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
172
173
        /* Detect zero crossing */
174
3.66G
        if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) {
175
316M
            if( yhi == 0 ) {
176
                /* If the root lies exactly at the end of the current       */
177
                /* interval, look for the next root in the next interval    */
178
1.92k
                thr = 1;
179
316M
            } else {
180
316M
                thr = 0;
181
316M
            }
182
            /* Binary division */
183
316M
            ffrac = -256;
184
1.26G
            for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
185
                /* Evaluate polynomial */
186
949M
                xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
187
949M
                ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
188
189
                /* Detect zero crossing */
190
949M
                if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
191
                    /* Reduce frequency */
192
474M
                    xhi = xmid;
193
474M
                    yhi = ymid;
194
474M
                } else {
195
                    /* Increase frequency */
196
474M
                    xlo = xmid;
197
474M
                    ylo = ymid;
198
474M
                    ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
199
474M
                }
200
949M
            }
201
202
            /* Interpolate */
203
316M
            if( silk_abs( ylo ) < 65536 ) {
204
                /* Avoid dividing by zero */
205
316M
                den = ylo - yhi;
206
316M
                nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
207
316M
                if( den != 0 ) {
208
316M
                    ffrac += silk_DIV32( nom, den );
209
316M
                }
210
316M
            } else {
211
                /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
212
6
                ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
213
6
            }
214
316M
            NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
215
216
316M
            silk_assert( NLSF[ root_ix ] >= 0 );
217
218
316M
            root_ix++;        /* Next root */
219
316M
            if( root_ix >= d ) {
220
                /* Found all roots */
221
28.7M
                break;
222
28.7M
            }
223
            /* Alternate pointer to polynomial */
224
287M
            p = PQ[ root_ix & 1 ];
225
226
            /* Evaluate polynomial */
227
287M
            xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
228
287M
            ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
229
3.35G
        } else {
230
            /* Increment loop counter */
231
3.35G
            k++;
232
3.35G
            xlo = xhi;
233
3.35G
            ylo = yhi;
234
3.35G
            thr = 0;
235
236
3.35G
            if( k > LSF_COS_TAB_SZ_FIX ) {
237
26.8k
                i++;
238
26.8k
                if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
239
                    /* Set NLSFs to white spectrum and exit */
240
0
                    NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
241
0
                    for( k = 1; k < d; k++ ) {
242
0
                        NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
243
0
                    }
244
0
                    return;
245
0
                }
246
247
                /* Error: Apply progressively more bandwidth expansion and run again */
248
26.8k
                silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
249
250
26.8k
                silk_A2NLSF_init( a_Q16, P, Q, dd );
251
26.8k
                p = P;                            /* Pointer to polynomial */
252
26.8k
                xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
253
26.8k
                ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
254
26.8k
                if( ylo < 0 ) {
255
                    /* Set the first NLSF to zero and move on to the next */
256
0
                    NLSF[ 0 ] = 0;
257
0
                    p = Q;                        /* Pointer to polynomial */
258
0
                    ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
259
0
                    root_ix = 1;                  /* Index of current root */
260
26.8k
                } else {
261
26.8k
                    root_ix = 0;                  /* Index of current root */
262
26.8k
                }
263
26.8k
                k = 1;                            /* Reset loop counter */
264
26.8k
            }
265
3.35G
        }
266
3.66G
    }
267
28.7M
}