Coverage Report

Created: 2026-01-09 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/silk/fixed/find_LPC_FIX.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
#ifdef HAVE_CONFIG_H
29
#include "config.h"
30
#endif
31
32
#include "main_FIX.h"
33
#include "stack_alloc.h"
34
#include "tuning_parameters.h"
35
36
/* Finds LPC vector from correlations, and converts to NLSF */
37
void silk_find_LPC_FIX(
38
    silk_encoder_state              *psEncC,                                /* I/O  Encoder state                                                               */
39
    opus_int16                      NLSF_Q15[],                             /* O    NLSFs                                                                       */
40
    const opus_int16                x[],                                    /* I    Input signal                                                                */
41
    const opus_int32                minInvGain_Q30                          /* I    Inverse of max prediction gain                                              */
42
)
43
237k
{
44
237k
    opus_int     k, subfr_length;
45
237k
    opus_int32   a_Q16[ MAX_LPC_ORDER ];
46
237k
    opus_int     isInterpLower, shift;
47
237k
    opus_int32   res_nrg0, res_nrg1;
48
237k
    opus_int     rshift0, rshift1;
49
50
    /* Used only for LSF interpolation */
51
237k
    opus_int32   a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg;
52
237k
    opus_int     res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q;
53
237k
    opus_int16   a_tmp_Q12[ MAX_LPC_ORDER ];
54
237k
    opus_int16   NLSF0_Q15[ MAX_LPC_ORDER ];
55
237k
    SAVE_STACK;
56
57
237k
    subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder;
58
59
    /* Default: no interpolation */
60
237k
    psEncC->indices.NLSFInterpCoef_Q2 = 4;
61
62
    /* Burg AR analysis for the full frame */
63
237k
    silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, psEncC->arch );
64
65
237k
    if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) {
66
75.0k
        VARDECL( opus_int16, LPC_res );
67
68
        /* Optimal solution for last 10 ms */
69
75.0k
        silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder, psEncC->arch );
70
71
        /* subtract residual energy here, as that's easier than adding it to the    */
72
        /* residual energy of the first 10 ms in each iteration of the search below */
73
75.0k
        shift = res_tmp_nrg_Q - res_nrg_Q;
74
75.0k
        if( shift >= 0 ) {
75
75.0k
            if( shift < 32 ) {
76
75.0k
                res_nrg = res_nrg - silk_RSHIFT( res_tmp_nrg, shift );
77
75.0k
            }
78
75.0k
        } else {
79
0
            silk_assert( shift > -32 );
80
0
            res_nrg   = silk_RSHIFT( res_nrg, -shift ) - res_tmp_nrg;
81
0
            res_nrg_Q = res_tmp_nrg_Q;
82
0
        }
83
84
        /* Convert to NLSFs */
85
75.0k
        silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder );
86
87
75.0k
        ALLOC( LPC_res, 2 * subfr_length, opus_int16 );
88
89
        /* Search over interpolation indices to find the one with lowest residual energy */
90
375k
        for( k = 3; k >= 0; k-- ) {
91
            /* Interpolate NLSFs for first half */
92
300k
            silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
93
94
            /* Convert to LPC for residual energy evaluation */
95
300k
            silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
96
97
            /* Calculate residual energy with NLSF interpolation */
98
300k
            silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch );
99
100
300k
            silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder,                subfr_length - psEncC->predictLPCOrder );
101
300k
            silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder );
102
103
            /* Add subframe energies from first half frame */
104
300k
            shift = rshift0 - rshift1;
105
300k
            if( shift >= 0 ) {
106
300k
                res_nrg1         = silk_RSHIFT( res_nrg1, shift );
107
300k
                res_nrg_interp_Q = -rshift0;
108
300k
            } else {
109
227
                res_nrg0         = silk_RSHIFT( res_nrg0, -shift );
110
227
                res_nrg_interp_Q = -rshift1;
111
227
            }
112
300k
            res_nrg_interp = silk_ADD32( res_nrg0, res_nrg1 );
113
114
            /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */
115
300k
            shift = res_nrg_interp_Q - res_nrg_Q;
116
300k
            if( shift >= 0 ) {
117
77.4k
                if( silk_RSHIFT( res_nrg_interp, shift ) < res_nrg ) {
118
23.8k
                    isInterpLower = silk_TRUE;
119
53.6k
                } else {
120
53.6k
                    isInterpLower = silk_FALSE;
121
53.6k
                }
122
222k
            } else {
123
222k
                if( -shift < 32 ) {
124
222k
                    if( res_nrg_interp < silk_RSHIFT( res_nrg, -shift ) ) {
125
18.0k
                        isInterpLower = silk_TRUE;
126
204k
                    } else {
127
204k
                        isInterpLower = silk_FALSE;
128
204k
                    }
129
222k
                } else {
130
0
                    isInterpLower = silk_FALSE;
131
0
                }
132
222k
            }
133
134
            /* Determine whether current interpolated NLSFs are best so far */
135
300k
            if( isInterpLower == silk_TRUE ) {
136
                /* Interpolation has lower residual energy */
137
41.8k
                res_nrg   = res_nrg_interp;
138
41.8k
                res_nrg_Q = res_nrg_interp_Q;
139
41.8k
                psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k;
140
41.8k
            }
141
300k
        }
142
75.0k
    }
143
144
237k
    if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) {
145
        /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
146
215k
        silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder );
147
215k
    }
148
149
237k
    celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
150
237k
    RESTORE_STACK;
151
237k
}