Coverage Report

Created: 2026-01-16 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/silk/decode_core.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.h"
33
#include "stack_alloc.h"
34
35
/**********************************************************/
36
/* Core decoder. Performs inverse NSQ operation LTP + LPC */
37
/**********************************************************/
38
void silk_decode_core(
39
    silk_decoder_state          *psDec,                         /* I/O  Decoder state                               */
40
    silk_decoder_control        *psDecCtrl,                     /* I    Decoder control                             */
41
    opus_int16                  xq[],                           /* O    Decoded speech                              */
42
    const opus_int16            pulses[ MAX_FRAME_LENGTH ],     /* I    Pulse signal                                */
43
    int                         arch                            /* I    Run-time architecture                       */
44
)
45
220k
{
46
220k
    opus_int   i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
47
220k
    opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
48
220k
    VARDECL( opus_int16, sLTP );
49
220k
    VARDECL( opus_int32, sLTP_Q15 );
50
220k
    opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
51
220k
    opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14;
52
220k
    VARDECL( opus_int32, res_Q14 );
53
220k
    VARDECL( opus_int32, sLPC_Q14 );
54
220k
    SAVE_STACK;
55
56
220k
    silk_assert( psDec->prev_gain_Q16 != 0 );
57
58
220k
    ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
59
220k
    ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
60
220k
    ALLOC( res_Q14, psDec->subfr_length, opus_int32 );
61
    /* Work around a clang bug (verified with clang 6.0 through clang 20.1.0) that causes the last
62
       memset to be flagged as an invalid read by valgrind (not caught by asan). */
63
220k
#if defined(__clang__) && defined(VAR_ARRAYS)
64
220k
    ALLOC( sLPC_Q14, MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER, opus_int32 );
65
#else
66
    ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 );
67
#endif
68
69
220k
    offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ];
70
71
220k
    if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) {
72
26.0k
        NLSF_interpolation_flag = 1;
73
194k
    } else {
74
194k
        NLSF_interpolation_flag = 0;
75
194k
    }
76
77
    /* Decode excitation */
78
220k
    rand_seed = psDec->indices.Seed;
79
34.9M
    for( i = 0; i < psDec->frame_length; i++ ) {
80
34.7M
        rand_seed = silk_RAND( rand_seed );
81
34.7M
        psDec->exc_Q14[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 14 );
82
34.7M
        if( psDec->exc_Q14[ i ] > 0 ) {
83
1.91M
            psDec->exc_Q14[ i ] -= QUANT_LEVEL_ADJUST_Q10 << 4;
84
1.91M
        } else
85
32.8M
        if( psDec->exc_Q14[ i ] < 0 ) {
86
5.57M
            psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4;
87
5.57M
        }
88
34.7M
        psDec->exc_Q14[ i ] += offset_Q10 << 4;
89
34.7M
        if( rand_seed < 0 ) {
90
17.4M
           psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ];
91
17.4M
        }
92
93
34.7M
        rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] );
94
34.7M
    }
95
96
    /* Copy LPC state */
97
220k
    silk_memcpy( sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
98
99
220k
    pexc_Q14 = psDec->exc_Q14;
100
220k
    pxq      = xq;
101
220k
    sLTP_buf_idx = psDec->ltp_mem_length;
102
    /* Loop over subframes */
103
860k
    for( k = 0; k < psDec->nb_subfr; k++ ) {
104
640k
        pres_Q14 = res_Q14;
105
640k
        A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
106
107
        /* Preload LPC coefficients to array on stack. Gives small performance gain */
108
640k
        silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
109
640k
        B_Q14        = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
110
640k
        signalType   = psDec->indices.signalType;
111
112
640k
        Gain_Q10     = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 );
113
640k
        inv_gain_Q31 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 47 );
114
115
        /* Calculate gain adjustment factor */
116
640k
        if( psDecCtrl->Gains_Q16[ k ] != psDec->prev_gain_Q16 ) {
117
361k
            gain_adj_Q16 =  silk_DIV32_varQ( psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[ k ], 16 );
118
119
            /* Scale short term state */
120
6.15M
            for( i = 0; i < MAX_LPC_ORDER; i++ ) {
121
5.79M
                sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, sLPC_Q14[ i ] );
122
5.79M
            }
123
361k
        } else {
124
278k
            gain_adj_Q16 = (opus_int32)1 << 16;
125
278k
        }
126
127
        /* Save inv_gain */
128
640k
        silk_assert( inv_gain_Q31 != 0 );
129
640k
        psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[ k ];
130
131
        /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
132
640k
        if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED &&
133
14.3k
            psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) {
134
135
7.22k
            silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
136
7.22k
            B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 );
137
138
7.22k
            signalType = TYPE_VOICED;
139
7.22k
            psDecCtrl->pitchL[ k ] = psDec->lagPrev;
140
7.22k
        }
141
142
640k
        if( signalType == TYPE_VOICED ) {
143
            /* Voiced */
144
116k
            lag = psDecCtrl->pitchL[ k ];
145
146
            /* Re-whitening */
147
116k
            if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
148
                /* Rewhiten with new A coefs */
149
43.0k
                start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
150
43.0k
                celt_assert( start_idx > 0 );
151
152
43.0k
                if( k == 2 ) {
153
4.70k
                    silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
154
4.70k
                }
155
156
43.0k
                silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
157
43.0k
                    A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order, arch );
158
159
                /* After rewhitening the LTP state is unscaled */
160
43.0k
                if( k == 0 ) {
161
                    /* Do LTP downscaling to reduce inter-packet dependency */
162
38.3k
                    inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 );
163
38.3k
                }
164
3.64M
                for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
165
3.60M
                    sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] );
166
3.60M
                }
167
73.2k
            } else {
168
                /* Update LTP state when Gain changes */
169
73.2k
                if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
170
2.79M
                    for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
171
2.75M
                        sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
172
2.75M
                    }
173
32.7k
                }
174
73.2k
            }
175
116k
        }
176
177
        /* Long-term prediction */
178
640k
        if( signalType == TYPE_VOICED ) {
179
            /* Set up pointer */
180
116k
            pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
181
7.12M
            for( i = 0; i < psDec->subfr_length; i++ ) {
182
                /* Unrolled loop */
183
                /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
184
7.01M
                LTP_pred_Q13 = 2;
185
7.01M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[  0 ], B_Q14[ 0 ] );
186
7.01M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
187
7.01M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
188
7.01M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
189
7.01M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
190
7.01M
                pred_lag_ptr++;
191
192
                /* Generate LPC excitation */
193
7.01M
                pres_Q14[ i ] = silk_ADD_LSHIFT32( pexc_Q14[ i ], LTP_pred_Q13, 1 );
194
195
                /* Update states */
196
7.01M
                sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q14[ i ], 1 );
197
7.01M
                sLTP_buf_idx++;
198
7.01M
            }
199
523k
        } else {
200
523k
            pres_Q14 = pexc_Q14;
201
523k
        }
202
203
35.4M
        for( i = 0; i < psDec->subfr_length; i++ ) {
204
            /* Short-term prediction */
205
34.7M
            celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
206
            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
207
34.7M
            LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
208
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
209
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
210
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
211
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12_tmp[ 3 ] );
212
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12_tmp[ 4 ] );
213
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12_tmp[ 5 ] );
214
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12_tmp[ 6 ] );
215
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
216
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
217
34.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
218
34.7M
            if( psDec->LPC_order == 16 ) {
219
16.1M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] );
220
16.1M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] );
221
16.1M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] );
222
16.1M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] );
223
16.1M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] );
224
16.1M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] );
225
16.1M
            }
226
227
            /* Add prediction to LPC excitation */
228
34.7M
            sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( pres_Q14[ i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
229
230
            /* Scale with gain */
231
34.7M
            pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
232
34.7M
        }
233
234
        /* Update LPC filter state */
235
640k
        silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
236
640k
        pexc_Q14 += psDec->subfr_length;
237
640k
        pxq      += psDec->subfr_length;
238
640k
    }
239
240
    /* Save LPC state */
241
220k
    silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) );
242
220k
    RESTORE_STACK;
243
220k
}