Coverage Report

Created: 2026-04-01 07:42

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