Coverage Report

Created: 2025-11-11 07:47

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
457k
{
46
457k
    opus_int   i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
47
457k
    opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
48
457k
    VARDECL( opus_int16, sLTP );
49
457k
    VARDECL( opus_int32, sLTP_Q15 );
50
457k
    opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
51
457k
    opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14;
52
457k
    VARDECL( opus_int32, res_Q14 );
53
457k
    VARDECL( opus_int32, sLPC_Q14 );
54
457k
    SAVE_STACK;
55
56
457k
    silk_assert( psDec->prev_gain_Q16 != 0 );
57
58
457k
    ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
59
457k
    ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
60
457k
    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
457k
#if defined(__clang__) && defined(VAR_ARRAYS)
64
457k
    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
457k
    offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ];
70
71
457k
    if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) {
72
83.3k
        NLSF_interpolation_flag = 1;
73
373k
    } else {
74
373k
        NLSF_interpolation_flag = 0;
75
373k
    }
76
77
    /* Decode excitation */
78
457k
    rand_seed = psDec->indices.Seed;
79
95.2M
    for( i = 0; i < psDec->frame_length; i++ ) {
80
94.7M
        rand_seed = silk_RAND( rand_seed );
81
94.7M
        psDec->exc_Q14[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 14 );
82
94.7M
        if( psDec->exc_Q14[ i ] > 0 ) {
83
5.62M
            psDec->exc_Q14[ i ] -= QUANT_LEVEL_ADJUST_Q10 << 4;
84
5.62M
        } else
85
89.1M
        if( psDec->exc_Q14[ i ] < 0 ) {
86
14.4M
            psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4;
87
14.4M
        }
88
94.7M
        psDec->exc_Q14[ i ] += offset_Q10 << 4;
89
94.7M
        if( rand_seed < 0 ) {
90
47.1M
           psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ];
91
47.1M
        }
92
93
94.7M
        rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] );
94
94.7M
    }
95
96
    /* Copy LPC state */
97
457k
    silk_memcpy( sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
98
99
457k
    pexc_Q14 = psDec->exc_Q14;
100
457k
    pxq      = xq;
101
457k
    sLTP_buf_idx = psDec->ltp_mem_length;
102
    /* Loop over subframes */
103
2.01M
    for( k = 0; k < psDec->nb_subfr; k++ ) {
104
1.56M
        pres_Q14 = res_Q14;
105
1.56M
        A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
106
107
        /* Preload LPC coefficients to array on stack. Gives small performance gain */
108
1.56M
        silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
109
1.56M
        B_Q14        = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
110
1.56M
        signalType   = psDec->indices.signalType;
111
112
1.56M
        Gain_Q10     = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 );
113
1.56M
        inv_gain_Q31 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 47 );
114
115
        /* Calculate gain adjustment factor */
116
1.56M
        if( psDecCtrl->Gains_Q16[ k ] != psDec->prev_gain_Q16 ) {
117
828k
            gain_adj_Q16 =  silk_DIV32_varQ( psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[ k ], 16 );
118
119
            /* Scale short term state */
120
14.0M
            for( i = 0; i < MAX_LPC_ORDER; i++ ) {
121
13.2M
                sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, sLPC_Q14[ i ] );
122
13.2M
            }
123
828k
        } else {
124
733k
            gain_adj_Q16 = (opus_int32)1 << 16;
125
733k
        }
126
127
        /* Save inv_gain */
128
1.56M
        silk_assert( inv_gain_Q31 != 0 );
129
1.56M
        psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[ k ];
130
131
        /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
132
1.56M
        if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED &&
133
21.0k
            psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) {
134
135
7.00k
            silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
136
7.00k
            B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 );
137
138
7.00k
            signalType = TYPE_VOICED;
139
7.00k
            psDecCtrl->pitchL[ k ] = psDec->lagPrev;
140
7.00k
        }
141
142
1.56M
        if( signalType == TYPE_VOICED ) {
143
            /* Voiced */
144
466k
            lag = psDecCtrl->pitchL[ k ];
145
146
            /* Re-whitening */
147
466k
            if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
148
                /* Rewhiten with new A coefs */
149
150k
                start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
150
150k
                celt_assert( start_idx > 0 );
151
152
150k
                if( k == 2 ) {
153
21.3k
                    silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
154
21.3k
                }
155
156
150k
                silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
157
150k
                    A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order, arch );
158
159
                /* After rewhitening the LTP state is unscaled */
160
150k
                if( k == 0 ) {
161
                    /* Do LTP downscaling to reduce inter-packet dependency */
162
129k
                    inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 );
163
129k
                }
164
13.6M
                for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
165
13.5M
                    sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] );
166
13.5M
                }
167
316k
            } else {
168
                /* Update LTP state when Gain changes */
169
316k
                if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
170
12.5M
                    for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
171
12.3M
                        sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
172
12.3M
                    }
173
141k
                }
174
316k
            }
175
466k
        }
176
177
        /* Long-term prediction */
178
1.56M
        if( signalType == TYPE_VOICED ) {
179
            /* Set up pointer */
180
466k
            pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
181
29.3M
            for( i = 0; i < psDec->subfr_length; i++ ) {
182
                /* Unrolled loop */
183
                /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
184
28.9M
                LTP_pred_Q13 = 2;
185
28.9M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[  0 ], B_Q14[ 0 ] );
186
28.9M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
187
28.9M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
188
28.9M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
189
28.9M
                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
190
28.9M
                pred_lag_ptr++;
191
192
                /* Generate LPC excitation */
193
28.9M
                pres_Q14[ i ] = silk_ADD_LSHIFT32( pexc_Q14[ i ], LTP_pred_Q13, 1 );
194
195
                /* Update states */
196
28.9M
                sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q14[ i ], 1 );
197
28.9M
                sLTP_buf_idx++;
198
28.9M
            }
199
1.09M
        } else {
200
1.09M
            pres_Q14 = pexc_Q14;
201
1.09M
        }
202
203
96.3M
        for( i = 0; i < psDec->subfr_length; i++ ) {
204
            /* Short-term prediction */
205
94.7M
            celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
206
            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
207
94.7M
            LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
208
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
209
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
210
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
211
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12_tmp[ 3 ] );
212
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12_tmp[ 4 ] );
213
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12_tmp[ 5 ] );
214
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12_tmp[ 6 ] );
215
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
216
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
217
94.7M
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
218
94.7M
            if( psDec->LPC_order == 16 ) {
219
47.8M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] );
220
47.8M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] );
221
47.8M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] );
222
47.8M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] );
223
47.8M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] );
224
47.8M
                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] );
225
47.8M
            }
226
227
            /* Add prediction to LPC excitation */
228
94.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
94.7M
            pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
232
94.7M
        }
233
234
        /* Update LPC filter state */
235
1.56M
        silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
236
1.56M
        pexc_Q14 += psDec->subfr_length;
237
1.56M
        pxq      += psDec->subfr_length;
238
1.56M
    }
239
240
    /* Save LPC state */
241
457k
    silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) );
242
457k
    RESTORE_STACK;
243
457k
}