Coverage Report

Created: 2025-11-24 07:40

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