Coverage Report

Created: 2026-11-12 07:36

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
224k
{
50
224k
    const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
51
52
    /****************************/
53
    /* Voice Activity Detection */
54
    /****************************/
55
224k
    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
224k
    if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
58
651
        psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
59
651
    }
60
61
    /**************************************************/
62
    /* Convert speech activity into VAD and DTX flags */
63
    /**************************************************/
64
224k
    if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
65
50.9k
        psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
66
50.9k
        psEnc->sCmn.noSpeechCounter++;
67
50.9k
        if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
68
50.9k
            psEnc->sCmn.inDTX = 0;
69
50.9k
        } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
70
0
            psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
71
0
            psEnc->sCmn.inDTX           = 0;
72
0
        }
73
50.9k
        psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0;
74
173k
    } else {
75
173k
        psEnc->sCmn.noSpeechCounter    = 0;
76
173k
        psEnc->sCmn.inDTX              = 0;
77
173k
        psEnc->sCmn.indices.signalType = TYPE_UNVOICED;
78
173k
        psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
79
173k
    }
80
224k
}
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
224k
{
94
224k
    silk_encoder_control_FIX sEncCtrl;
95
224k
    opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
96
224k
    opus_int16   *x_frame;
97
224k
    ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
98
224k
    VARDECL(silk_nsq_state, sNSQ_copy);
99
224k
    opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
100
224k
    opus_int32   gainsID, gainsID_lower, gainsID_upper;
101
224k
    opus_int16   gainMult_Q8;
102
224k
    opus_int16   ec_prevLagIndex_copy;
103
224k
    opus_int     ec_prevSignalType_copy;
104
224k
    opus_int8    LastGainIndex_copy2;
105
224k
    opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
106
224k
    opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
107
224k
    opus_int     best_sum[ MAX_NB_SUBFR ];
108
224k
    opus_int     bits_margin;
109
224k
    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
224k
    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
224k
    bits_margin = useCBR ? 5 : maxBits/4;
117
    /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
118
224k
    LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
119
120
224k
    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
224k
    x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;
127
128
    /***************************************/
129
    /* Ensure smooth bandwidth transitions */
130
    /***************************************/
131
224k
    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
224k
    silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
137
138
224k
    if( !psEnc->sCmn.prefillFlag ) {
139
224k
        VARDECL( opus_int16, res_pitch );
140
224k
        VARDECL( opus_uint8, ec_buf_copy );
141
224k
        opus_int16 *res_pitch_frame;
142
143
224k
        ALLOC( res_pitch,
144
224k
               psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length
145
224k
                   + psEnc->sCmn.ltp_mem_length, opus_int16 );
146
        /* start of pitch LPC residual frame */
147
224k
        res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length;
148
149
        /*****************************************/
150
        /* Find pitch lags, initial LPC analysis */
151
        /*****************************************/
152
224k
        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
224k
        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
224k
        silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
163
164
        /****************************************/
165
        /* Process gains                        */
166
        /****************************************/
167
224k
        silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
168
169
        /****************************************/
170
        /* Low Bitrate Redundant Encoding       */
171
        /****************************************/
172
224k
        silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
173
174
        /* Loop over quantizer and entropy coding to control bitrate */
175
224k
        maxIter = 6;
176
224k
        gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
177
224k
        found_lower = 0;
178
224k
        found_upper = 0;
179
224k
        gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
180
224k
        gainsID_lower = -1;
181
224k
        gainsID_upper = -1;
182
        /* Copy part of the input state */
183
224k
        silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) );
184
224k
        silk_memcpy( &sNSQ_copy[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
185
224k
        seed_copy = psEnc->sCmn.indices.Seed;
186
224k
        ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex;
187
224k
        ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType;
188
224k
        ALLOC( ec_buf_copy, 1275, opus_uint8 );
189
667k
        for( iter = 0; ; iter++ ) {
190
667k
            if( gainsID == gainsID_lower ) {
191
95.5k
                nBits = nBits_lower;
192
572k
            } else if( gainsID == gainsID_upper ) {
193
15.6k
                nBits = nBits_upper;
194
556k
            } else {
195
                /* Restore part of the input state */
196
556k
                if( iter > 0 ) {
197
332k
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) );
198
332k
                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[0], sizeof( silk_nsq_state ) );
199
332k
                    psEnc->sCmn.indices.Seed = seed_copy;
200
332k
                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
201
332k
                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
202
332k
                }
203
204
                /*****************************************/
205
                /* Noise shaping quantization            */
206
                /*****************************************/
207
556k
                if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
208
415k
                    silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
209
415k
                           sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
210
415k
                           sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
211
415k
                           psEnc->sCmn.arch );
212
415k
                } else {
213
141k
                    silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
214
141k
                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
215
141k
                            sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
216
141k
                            psEnc->sCmn.arch);
217
141k
                }
218
219
556k
                if ( iter == maxIter && !found_lower ) {
220
13.1k
                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
221
13.1k
                }
222
223
                /****************************************/
224
                /* Encode Parameters                    */
225
                /****************************************/
226
556k
                silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
227
228
                /****************************************/
229
                /* Encode Excitation Signal             */
230
                /****************************************/
231
556k
                silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
232
556k
                    psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
233
234
556k
                nBits = ec_tell( psRangeEnc );
235
236
                /* If we still bust after the last iteration, do some damage control. */
237
556k
                if ( iter == maxIter && !found_lower && nBits > maxBits ) {
238
12.1k
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
239
240
                    /* Keep gains the same as the last frame. */
241
12.1k
                    psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
242
60.5k
                    for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
243
48.3k
                        psEnc->sCmn.indices.GainsIndices[ i ] = 4;
244
48.3k
                    }
245
12.1k
                    if (condCoding != CODE_CONDITIONALLY) {
246
10.0k
                       psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
247
10.0k
                    }
248
12.1k
                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
249
12.1k
                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
250
                    /* Clear all pulses. */
251
2.43M
                    for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
252
2.42M
                        psEnc->sCmn.pulses[ i ] = 0;
253
2.42M
                    }
254
255
12.1k
                    silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
256
257
12.1k
                    silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
258
12.1k
                        psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
259
260
12.1k
                    nBits = ec_tell( psRangeEnc );
261
12.1k
                }
262
263
556k
                if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
264
141k
                    break;
265
141k
                }
266
556k
            }
267
268
525k
            if( iter == maxIter ) {
269
68.5k
                if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
270
                    /* Restore output state from earlier iteration that did meet the bitrate budget */
271
25.7k
                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
272
25.7k
                    celt_assert( sRangeEnc_copy2.offs <= 1275 );
273
25.7k
                    silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
274
25.7k
                    silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy[1], sizeof( silk_nsq_state ) );
275
25.7k
                    psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
276
25.7k
                }
277
68.5k
                break;
278
68.5k
            }
279
280
457k
            if( nBits > maxBits ) {
281
123k
                if( found_lower == 0 && iter >= 2 ) {
282
                    /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
283
58.7k
                    sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 );
284
58.7k
                    found_upper = 0;
285
58.7k
                    gainsID_upper = -1;
286
65.0k
                } else {
287
65.0k
                    found_upper = 1;
288
65.0k
                    nBits_upper = nBits;
289
65.0k
                    gainMult_upper = gainMult_Q8;
290
65.0k
                    gainsID_upper = gainsID;
291
65.0k
                }
292
333k
            } else if( nBits < maxBits - bits_margin ) {
293
319k
                found_lower = 1;
294
319k
                nBits_lower = nBits;
295
319k
                gainMult_lower = gainMult_Q8;
296
319k
                if( gainsID != gainsID_lower ) {
297
243k
                    gainsID_lower = gainsID;
298
                    /* Copy part of the output state */
299
243k
                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
300
243k
                    celt_assert( psRangeEnc->offs <= 1275 );
301
243k
                    silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
302
243k
                    silk_memcpy( &sNSQ_copy[1], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
303
243k
                    LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
304
243k
                }
305
319k
            } else {
306
                /* Close enough */
307
13.5k
                break;
308
13.5k
            }
309
310
443k
            if ( !found_lower && nBits > maxBits ) {
311
103k
                int j;
312
514k
                for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
313
410k
                    int sum=0;
314
21.1M
                    for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
315
20.7M
                        sum += abs( psEnc->sCmn.pulses[j] );
316
20.7M
                    }
317
410k
                    if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
318
194k
                        best_sum[i] = sum;
319
194k
                        best_gain_mult[i] = gainMult_Q8;
320
216k
                    } else {
321
216k
                        gain_lock[i] = 1;
322
216k
                    }
323
410k
                }
324
103k
            }
325
443k
            if( ( found_lower & found_upper ) == 0 ) {
326
                /* Adjust gain according to high-rate rate/distortion curve */
327
409k
                if( nBits > maxBits ) {
328
103k
                    gainMult_Q8 = silk_min_32( 1024, gainMult_Q8*3/2 );
329
305k
                } else {
330
305k
                    gainMult_Q8 = silk_max_32( 64, gainMult_Q8*4/5 );
331
305k
                }
332
409k
            } else {
333
                /* Adjust gain by interpolating */
334
34.2k
                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
34.2k
                if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
337
5.52k
                    gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
338
5.52k
                } else
339
28.7k
                if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
340
8.91k
                    gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
341
8.91k
                }
342
34.2k
            }
343
344
1.91M
            for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
345
1.47M
                opus_int16 tmp;
346
1.47M
                if ( gain_lock[i] ) {
347
220k
                    tmp = best_gain_mult[i];
348
1.25M
                } else {
349
1.25M
                    tmp = gainMult_Q8;
350
1.25M
                }
351
1.47M
                sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
352
1.47M
            }
353
354
            /* Quantize gains */
355
443k
            psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
356
443k
            silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16,
357
443k
                  &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
358
359
            /* Unique identifier of gains vector */
360
443k
            gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
361
443k
        }
362
224k
    }
363
364
    /* Update input buffer */
365
224k
    silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
366
224k
        ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) );
367
368
    /* Exit without entropy coding */
369
224k
    if( psEnc->sCmn.prefillFlag ) {
370
        /* No payload */
371
0
        *pnBytesOut = 0;
372
0
        RESTORE_STACK;
373
0
        return ret;
374
0
    }
375
376
    /* Parameters needed for next frame */
377
224k
    psEnc->sCmn.prevLag        = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ];
378
224k
    psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType;
379
380
    /****************************************/
381
    /* Finalize payload                     */
382
    /****************************************/
383
224k
    psEnc->sCmn.first_frame_after_reset = 0;
384
    /* Payload size */
385
224k
    *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 );
386
387
224k
    RESTORE_STACK;
388
224k
    return ret;
389
224k
}
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
224k
{
399
224k
    opus_int32   TempGains_Q16[ MAX_NB_SUBFR ];
400
224k
    SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
401
224k
    VARDECL(silk_nsq_state, sNSQ_LBRR);
402
224k
    SAVE_STACK;
403
404
    /*******************************************/
405
    /* Control use of inband LBRR              */
406
    /*******************************************/
407
224k
    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
98.3k
        ALLOC(sNSQ_LBRR, 1, silk_nsq_state);
411
412
98.3k
        psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1;
413
414
        /* Copy noise shaping quantizer state and quantization indices from regular encoding */
415
98.3k
        silk_memcpy( &sNSQ_LBRR[0], &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
416
98.3k
        silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) );
417
418
        /* Save original gains */
419
98.3k
        silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
420
421
98.3k
        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
77.8k
            psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
424
425
            /* Increase Gains to get target LBRR rate */
426
77.8k
            psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases;
427
77.8k
            psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 );
428
77.8k
        }
429
430
        /* Decode to get gains in sync with decoder         */
431
        /* Overwrite unquantized gains with quantized gains */
432
98.3k
        silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices,
433
98.3k
            &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
434
435
        /*****************************************/
436
        /* Noise shaping quantization            */
437
        /*****************************************/
438
98.3k
        if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
439
78.9k
            silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR[0], psIndices_LBRR, x16,
440
78.9k
                psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
441
78.9k
                psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
442
78.9k
                psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
443
78.9k
        } else {
444
19.3k
            silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR[0], psIndices_LBRR, x16,
445
19.3k
                psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
446
19.3k
                psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
447
19.3k
                psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
448
19.3k
        }
449
450
        /* Restore original gains */
451
98.3k
        silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
452
98.3k
    }
453
224k
    RESTORE_STACK;
454
224k
}