Coverage Report

Created: 2026-04-12 08:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/silk/fixed/encode_frame_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 <stdlib.h>
33
#include "main_FIX.h"
34
#include "stack_alloc.h"
35
#include "tuning_parameters.h"
36
37
/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate           */
38
static OPUS_INLINE void silk_LBRR_encode_FIX(
39
    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
40
    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
41
    const opus_int16                x16[],                                  /* I    Input signal                                                                */
42
    opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
43
);
44
45
void silk_encode_do_VAD_FIX(
46
    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
47
    opus_int                        activity                                /* I    Decision of Opus voice activity detector                                    */
48
)
49
44.7M
{
50
44.7M
    const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
51
52
    /****************************/
53
    /* Voice Activity Detection */
54
    /****************************/
55
44.7M
    silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
56
    /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
57
44.7M
    if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
58
7.09k
        psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
59
7.09k
    }
60
61
    /**************************************************/
62
    /* Convert speech activity into VAD and DTX flags */
63
    /**************************************************/
64
44.7M
    if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
65
43.7M
        psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
66
43.7M
        psEnc->sCmn.noSpeechCounter++;
67
43.7M
        if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
68
252k
            psEnc->sCmn.inDTX = 0;
69
43.5M
        } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
70
2.06M
            psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
71
2.06M
            psEnc->sCmn.inDTX           = 0;
72
2.06M
        }
73
43.7M
        psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0;
74
43.7M
    } else {
75
1.03M
        psEnc->sCmn.noSpeechCounter    = 0;
76
1.03M
        psEnc->sCmn.inDTX              = 0;
77
1.03M
        psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
78
1.03M
        psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
79
1.03M
    }
80
44.7M
}
81
82
/****************/
83
/* Encode frame */
84
/****************/
85
opus_int silk_encode_frame_FIX(
86
    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
87
    opus_int32                      *pnBytesOut,                            /* O    Pointer to number of payload bytes;                                         */
88
    ec_enc                          *psRangeEnc,                            /* I/O  compressor data structure                                                   */
89
    opus_int                        condCoding,                             /* I    The type of conditional coding to use                                       */
90
    opus_int                        maxBits,                                /* I    If > 0: maximum number of output bits                                       */
91
    opus_int                        useCBR                                  /* I    Flag to force constant-bitrate operation                                    */
92
)
93
44.7M
{
94
44.7M
    silk_encoder_control_FIX sEncCtrl;
95
44.7M
    opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
96
44.7M
    opus_int16   *x_frame;
97
44.7M
    ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
98
44.7M
    VARDECL(silk_nsq_state, sNSQ_copy);
99
44.7M
    opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
100
44.7M
    opus_int32   gainsID, gainsID_lower, gainsID_upper;
101
44.7M
    opus_int16   gainMult_Q8;
102
44.7M
    opus_int16   ec_prevLagIndex_copy;
103
44.7M
    opus_int     ec_prevSignalType_copy;
104
44.7M
    opus_int8    LastGainIndex_copy2;
105
44.7M
    opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
106
44.7M
    opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
107
44.7M
    opus_int     best_sum[ MAX_NB_SUBFR ];
108
44.7M
    opus_int     bits_margin;
109
44.7M
    SAVE_STACK;
110
111
    /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
112
       This is useful on some embedded systems. */
113
44.7M
    ALLOC(sNSQ_copy, 2, silk_nsq_state);
114
115
    /* For CBR, 5 bits below budget is close enough. For VBR, allow up to 25% below the cap if we initially busted the budget. */
116
44.7M
    bits_margin = useCBR ? 5 : maxBits/4;
117
    /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
118
44.7M
    LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
119
120
44.7M
    psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
121
122
    /**************************************************************/
123
    /* Set up Input Pointers, and insert frame in input buffer   */
124
    /*************************************************************/
125
    /* start of frame to encode */
126
44.7M
    x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;
127
128
    /***************************************/
129
    /* Ensure smooth bandwidth transitions */
130
    /***************************************/
131
44.7M
    silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
132
133
    /*******************************************/
134
    /* Copy new frame to front of input buffer */
135
    /*******************************************/
136
44.7M
    silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
137
138
44.7M
    if( !psEnc->sCmn.prefillFlag ) {
139
44.7M
        VARDECL( opus_int16, res_pitch );
140
44.7M
        VARDECL( opus_uint8, ec_buf_copy );
141
44.7M
        opus_int16 *res_pitch_frame;
142
143
44.7M
        ALLOC( res_pitch,
144
44.7M
               psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length
145
44.7M
                   + psEnc->sCmn.ltp_mem_length, opus_int16 );
146
        /* start of pitch LPC residual frame */
147
44.7M
        res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length;
148
149
        /*****************************************/
150
        /* Find pitch lags, initial LPC analysis */
151
        /*****************************************/
152
44.7M
        silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
153
154
        /************************/
155
        /* Noise shape analysis */
156
        /************************/
157
44.7M
        silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch );
158
159
        /***************************************************/
160
        /* Find linear prediction coefficients (LPC + LTP) */
161
        /***************************************************/
162
44.7M
        silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
163
164
        /****************************************/
165
        /* Process gains                        */
166
        /****************************************/
167
44.7M
        silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
168
169
        /****************************************/
170
        /* Low Bitrate Redundant Encoding       */
171
        /****************************************/
172
44.7M
        silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
173
174
        /* Loop over quantizer and entropy coding to control bitrate */
175
44.7M
        maxIter = 6;
176
44.7M
        gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
177
44.7M
        found_lower = 0;
178
44.7M
        found_upper = 0;
179
44.7M
        gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
180
44.7M
        gainsID_lower = -1;
181
44.7M
        gainsID_upper = -1;
182
        /* Copy part of the input state */
183
44.7M
        silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
184
44.7M
        silk_memcpy( &sNSQ_copy[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
185
44.7M
        seed_copy = psEnc->sCmn.indices.Seed;
186
44.7M
        ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
187
44.7M
        ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
188
44.7M
        ALLOC( ec_buf_copy, 1275, opus_uint8 );
189
172M
        for( iter = 0; ; iter++ ) {
190
172M
            if( gainsID == gainsID_lower ) {
191
125M
                nBits = nBits_lower;
192
125M
            } else if( gainsID == gainsID_upper ) {
193
214k
                nBits = nBits_upper;
194
46.5M
            } else {
195
                /* Restore part of the input state */
196
46.5M
                if( iter > 0 ) {
197
1.73M
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
198
1.73M
                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[0], sizeof( silk_nsq_state ) );
199
1.73M
                    psEnc->sCmn.indices.Seed = seed_copy;
200
1.73M
                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
201
1.73M
                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
202
1.73M
                }
203
204
                /*****************************************/
205
                /* Noise shaping quantization            */
206
                /*****************************************/
207
46.5M
                if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
208
19.1M
                    silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
209
19.1M
                           sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
210
19.1M
                           sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
211
19.1M
                           psEnc->sCmn.arch );
212
27.4M
                } else {
213
27.4M
                    silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
214
27.4M
                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
215
27.4M
                            sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
216
27.4M
                            psEnc->sCmn.arch);
217
27.4M
                }
218
219
46.5M
                if ( iter == maxIter && !found_lower ) {
220
41.2k
                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
221
41.2k
                }
222
223
                /****************************************/
224
                /* Encode Parameters                    */
225
                /****************************************/
226
46.5M
                silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
227
228
                /****************************************/
229
                /* Encode Excitation Signal             */
230
                /****************************************/
231
46.5M
                silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
232
46.5M
                    psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
233
234
46.5M
                nBits = ec_tell( psRangeEnc );
235
236
                /* If we still bust after the last iteration, do some damage control. */
237
46.5M
                if ( iter == maxIter && !found_lower && nBits > maxBits ) {
238
35.1k
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
239
240
                    /* Keep gains the same as the last frame. */
241
35.1k
                    psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
242
170k
                    for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
243
135k
                        psEnc->sCmn.indices.GainsIndices[ i ] = 4;
244
135k
                    }
245
35.1k
                    if (condCoding != CODE_CONDITIONALLY) {
246
25.2k
                       psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
247
25.2k
                    }
248
35.1k
                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
249
35.1k
                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
250
                    /* Clear all pulses. */
251
6.44M
                    for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
252
6.40M
                        psEnc->sCmn.pulses[ i ] = 0;
253
6.40M
                    }
254
255
35.1k
                    silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
256
257
35.1k
                    silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
258
35.1k
                        psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
259
260
35.1k
                    nBits = ec_tell( psRangeEnc );
261
35.1k
                }
262
263
46.5M
                if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
264
23.3M
                    break;
265
23.3M
                }
266
46.5M
            }
267
268
149M
            if( iter == maxIter ) {
269
21.2M
                if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
270
                    /* Restore output state from earlier iteration that did meet the bitrate budget */
271
21.1M
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
272
21.1M
                    celt_assert( sRangeEnc_copy2.offs <= 1275 );
273
21.1M
                    silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
274
21.1M
                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[1], sizeof( silk_nsq_state ) );
275
21.1M
                    psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
276
21.1M
                }
277
21.2M
                break;
278
21.2M
            }
279
280
128M
            if( nBits > maxBits ) {
281
988k
                if( found_lower == 0 && iter >= 2 ) {
282
                    /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
283
259k
                    sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 );
284
259k
                    found_upper = 0;
285
259k
                    gainsID_upper = -1;
286
729k
                } else {
287
729k
                    found_upper = 1;
288
729k
                    nBits_upper = nBits;
289
729k
                    gainMult_upper = gainMult_Q8;
290
729k
                    gainsID_upper = gainsID;
291
729k
                }
292
127M
            } else if( nBits < maxBits - bits_margin ) {
293
126M
                found_lower = 1;
294
126M
                nBits_lower = nBits;
295
126M
                gainMult_lower = gainMult_Q8;
296
126M
                if( gainsID != gainsID_lower ) {
297
22.0M
                    gainsID_lower = gainsID;
298
                    /* Copy part of the output state */
299
22.0M
                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
300
22.0M
                    celt_assert( psRangeEnc->offs <= 1275 );
301
22.0M
                    silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
302
22.0M
                    silk_memcpy( &sNSQ_copy[1], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
303
22.0M
                    LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
304
22.0M
                }
305
126M
            } else {
306
                /* Close enough */
307
184k
                break;
308
184k
            }
309
310
127M
            if ( !found_lower && nBits > maxBits ) {
311
684k
                int j;
312
3.26M
                for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
313
2.58M
                    int sum=0;
314
122M
                    for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
315
119M
                        sum += abs( psEnc->sCmn.pulses[j] );
316
119M
                    }
317
2.58M
                    if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
318
1.63M
                        best_sum[i] = sum;
319
1.63M
                        best_gain_mult[i] = gainMult_Q8;
320
1.63M
                    } else {
321
942k
                        gain_lock[i] = 1;
322
942k
                    }
323
2.58M
                }
324
684k
            }
325
127M
            if( ( found_lower & found_upper ) == 0 ) {
326
                /* Adjust gain according to high-rate rate/distortion curve */
327
127M
                if( nBits > maxBits ) {
328
684k
                    gainMult_Q8 = silk_min_32( 1024, gainMult_Q8*3/2 );
329
126M
                } else {
330
126M
                    gainMult_Q8 = silk_max_32( 64, gainMult_Q8*4/5 );
331
126M
                }
332
127M
            } else {
333
                /* Adjust gain by interpolating */
334
630k
                gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
335
                /* New gain multiplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
336
630k
                if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
337
96.6k
                    gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
338
96.6k
                } else
339
533k
                if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
340
154k
                    gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
341
154k
                }
342
630k
            }
343
344
532M
            for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
345
404M
                opus_int16 tmp;
346
404M
                if ( gain_lock[i] ) {
347
1.07M
                    tmp = best_gain_mult[i];
348
403M
                } else {
349
403M
                    tmp = gainMult_Q8;
350
403M
                }
351
404M
                sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
352
404M
            }
353
354
            /* Quantize gains */
355
127M
            psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
356
127M
            silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16,
357
127M
                  &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
358
359
            /* Unique identifier of gains vector */
360
127M
            gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
361
127M
        }
362
44.7M
    }
363
364
    /* Update input buffer */
365
44.7M
    silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
366
44.7M
        ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) );
367
368
    /* Exit without entropy coding */
369
44.7M
    if( psEnc->sCmn.prefillFlag ) {
370
        /* No payload */
371
362
        *pnBytesOut = 0;
372
362
        RESTORE_STACK;
373
362
        return ret;
374
362
    }
375
376
    /* Parameters needed for next frame */
377
44.7M
    psEnc->sCmn.prevLag        = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
378
44.7M
    psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;
379
380
    /****************************************/
381
    /* Finalize payload                     */
382
    /****************************************/
383
44.7M
    psEnc->sCmn.first_frame_after_reset = 0;
384
    /* Payload size */
385
44.7M
    *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
386
387
44.7M
    RESTORE_STACK;
388
44.7M
    return ret;
389
44.7M
}
390
391
/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate  */
392
static OPUS_INLINE void silk_LBRR_encode_FIX(
393
    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
394
    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
395
    const opus_int16                x16[],                                  /* I    Input signal                                                                */
396
    opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
397
)
398
44.7M
{
399
44.7M
    opus_int32   TempGains_Q16[ MAX_NB_SUBFR ];
400
44.7M
    SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
401
44.7M
    VARDECL(silk_nsq_state, sNSQ_LBRR);
402
44.7M
    SAVE_STACK;
403
404
    /*******************************************/
405
    /* Control use of inband LBRR              */
406
    /*******************************************/
407
44.7M
    if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) {
408
        /* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
409
           This is useful on some embedded systems. */
410
280k
        ALLOC(sNSQ_LBRR, 1, silk_nsq_state);
411
412
280k
        psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
413
414
        /* Copy noise shaping quantizer state and quantization indices from regular encoding */
415
280k
        silk_memcpy( &sNSQ_LBRR[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
416
280k
        silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
417
418
        /* Save original gains */
419
280k
        silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
420
421
280k
        if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) {
422
            /* First frame in packet or previous frame not LBRR coded */
423
216k
            psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
424
425
            /* Increase Gains to get target LBRR rate */
426
216k
            psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases;
427
216k
            psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
428
216k
        }
429
430
        /* Decode to get gains in sync with decoder         */
431
        /* Overwrite unquantized gains with quantized gains */
432
280k
        silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices,
433
280k
            &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
434
435
        /*****************************************/
436
        /* Noise shaping quantization            */
437
        /*****************************************/
438
280k
        if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
439
147k
            silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR[0], psIndices_LBRR, x16,
440
147k
                psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
441
147k
                psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
442
147k
                psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
443
147k
        } else {
444
132k
            silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR[0], psIndices_LBRR, x16,
445
132k
                psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
446
132k
                psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
447
132k
                psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
448
132k
        }
449
450
        /* Restore original gains */
451
280k
        silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
452
280k
    }
453
44.7M
    RESTORE_STACK;
454
44.7M
}