/*******************************************************************************************************************************************************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
  distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor the names of specific contributors, may be used to endorse or promote products derived from this software without specific prior written
  permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************************************************************************************************************************************/

#include "silk.h"
#include <stdint.h>

#define __malloc_heap_psram(size) \
    heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL)
#define __calloc_heap_psram(ch, size) \
    heap_caps_calloc_prefer(ch, size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL)


silk_decoder_state s_channel_state[2];
silk_decoder       s_decState;
extern ec_ctx_t    s_ec;

uint8_t  s_channelsInternal = 0;
uint8_t  s_payloadSize_ms = 0;
uint8_t  s_API_channels = 0;
uint32_t s_silk_internalSampleRate = 0;
uint32_t s_API_sampleRate = 0;
uint32_t s_prevPitchLag = 0;

/* Coefficients for 2-band filter bank based on first-order allpass filters */
int16_t A_fb1_20 = 5394 << 1;
int16_t A_fb1_21 = -24290; /* (int16_t)(20623 << 1) */

const int16_t HARM_ATT_Q15[NB_ATT] = {32440, 31130};              /* 0.99, 0.95 */
const int16_t PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = {31130, 26214};  /* 0.95, 0.8 */
const int16_t PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = {32440, 29491}; /* 0.99, 0.9 */

/* Cosine approximation table for LSF conversion */
/* Q12 values (even) */
const int16_t silk_LSFCosTab_FIX_Q12[LSF_COS_TAB_SZ_FIX + 1] = {
    8192,  8190,  8182,  8170,  8152,  8130,  8104,  8072,  8034,  7994,  7946,  7896,  7840,  7778,  7714,  7644,  7568,  7490,  7406,  7318,  7226,  7128,  7026,  6922,  6812,  6698,
    6580,  6458,  6332,  6204,  6070,  5934,  5792,  5648,  5502,  5352,  5198,  5040,  4880,  4718,  4552,  4382,  4212,  4038,  3862,  3684,  3502,  3320,  3136,  2948,  2760,  2570,
    2378,  2186,  1990,  1794,  1598,  1400,  1202,  1002,  802,   602,   402,   202,   0,     -202,  -402,  -602,  -802,  -1002, -1202, -1400, -1598, -1794, -1990, -2186, -2378, -2570,
    -2760, -2948, -3136, -3320, -3502, -3684, -3862, -4038, -4212, -4382, -4552, -4718, -4880, -5040, -5198, -5352, -5502, -5648, -5792, -5934, -6070, -6204, -6332, -6458, -6580, -6698,
    -6812, -6922, -7026, -7128, -7226, -7318, -7406, -7490, -7568, -7644, -7714, -7778, -7840, -7896, -7946, -7994, -8034, -8072, -8104, -8130, -8152, -8170, -8182, -8190, -8192};

/* Tables for stereo predictor coding */
const int16_t silk_stereo_pred_quant_Q13[STEREO_QUANT_TAB_SIZE] = {-13732, -10050, -8266, -7526, -6500, -5000, -2950, -820, 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732};
const uint8_t silk_stereo_pred_joint_iCDF[25] = {249, 247, 246, 245, 244, 234, 210, 202, 201, 200, 197, 174, 82, 59, 56, 55, 54, 46, 22, 12, 11, 10, 9, 7, 0};
const uint8_t silk_stereo_only_code_mid_iCDF[2] = {64, 0};

/* Tables for LBRR flags */
static const uint8_t silk_LBRR_flags_2_iCDF[3] = {203, 150, 0};
static const uint8_t silk_LBRR_flags_3_iCDF[7] = {215, 195, 166, 125, 110, 82, 0};
const uint8_t* const silk_LBRR_flags_iCDF_ptr[2] = {silk_LBRR_flags_2_iCDF, silk_LBRR_flags_3_iCDF};

/* Table for LSB coding */
const uint8_t silk_lsb_iCDF[2] = {120, 0};

/* Tables for LTPScale */
const uint8_t silk_LTPscale_iCDF[3] = {128, 64, 0};

/* Tables for signal type and offset coding */
const uint8_t silk_type_offset_VAD_iCDF[4] = {232, 158, 10, 0};
const uint8_t silk_type_offset_no_VAD_iCDF[2] = {230, 0};

/* Tables for NLSF interpolation factor */
const uint8_t silk_NLSF_interpolation_factor_iCDF[5] = {243, 221, 192, 181, 0};

/* Quantization offsets */
const int16_t silk_Quantization_Offsets_Q10[2][2] = {{OFFSET_UVL_Q10, OFFSET_UVH_Q10}, {OFFSET_VL_Q10, OFFSET_VH_Q10}};

/* Table for LTPScale */
const int16_t silk_LTPScales_table_Q14[3] = {15565, 12288, 8192};

/* Uniform entropy tables */
const uint8_t silk_uniform3_iCDF[3] = {171, 85, 0};
const uint8_t silk_uniform4_iCDF[4] = {192, 128, 64, 0};
const uint8_t silk_uniform5_iCDF[5] = {205, 154, 102, 51, 0};
const uint8_t silk_uniform6_iCDF[6] = {213, 171, 128, 85, 43, 0};
const uint8_t silk_uniform8_iCDF[8] = {224, 192, 160, 128, 96, 64, 32, 0};

const uint8_t silk_NLSF_EXT_iCDF[7] = {100, 40, 16, 7, 3, 1, 0};

/*  Elliptic/Cauer filters designed with 0.1 dB passband ripple,
        80 dB minimum stopband attenuation, and
        [0.95 : 0.15 : 0.35] normalized cut off frequencies. */

/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
const int32_t silk_Transition_LP_B_Q28[TRANSITION_INT_NUM][TRANSITION_NB] = {{250767114, 501534038, 250767114},
                                                                             {209867381, 419732057, 209867381},
                                                                             {170987846, 341967853, 170987846},
                                                                             {131531482, 263046905, 131531482},
                                                                             {89306658, 178584282, 89306658}};

/* Interpolation points for filter coefficients used in the bandwidth transition smoother */
const int32_t silk_Transition_LP_A_Q28[TRANSITION_INT_NUM][TRANSITION_NA] = {{506393414, 239854379}, {411067935, 169683996}, {306733530, 116694253}, {185807084, 77959395}, {35497197, 57401098}};

const uint8_t silk_max_pulses_table[4] = {8, 10, 12, 16};

const uint8_t silk_pulses_per_block_iCDF[10][18] = {{125, 51, 26, 18, 15, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
                                                    {198, 105, 45, 22, 15, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
                                                    {213, 162, 116, 83, 59, 43, 32, 24, 18, 15, 12, 9, 7, 6, 5, 3, 2, 0},
                                                    {239, 187, 116, 59, 28, 16, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
                                                    {250, 229, 188, 135, 86, 51, 30, 19, 13, 10, 8, 6, 5, 4, 3, 2, 1, 0},
                                                    {249, 235, 213, 185, 156, 128, 103, 83, 66, 53, 42, 33, 26, 21, 17, 13, 10, 0},
                                                    {254, 249, 235, 206, 164, 118, 77, 46, 27, 16, 10, 7, 5, 4, 3, 2, 1, 0},
                                                    {255, 253, 249, 239, 220, 191, 156, 119, 85, 57, 37, 23, 15, 10, 6, 4, 2, 0},
                                                    {255, 253, 251, 246, 237, 223, 203, 179, 152, 124, 98, 75, 55, 40, 29, 21, 15, 0},
                                                    {255, 254, 253, 247, 220, 162, 106, 67, 42, 28, 18, 12, 9, 6, 4, 3, 2, 0}};

const uint8_t silk_rate_levels_iCDF[2][9] = {{241, 190, 178, 132, 87, 74, 41, 14, 0}, {223, 193, 157, 140, 106, 57, 39, 18, 0}};

const uint8_t silk_rate_levels_BITS_Q5[2][9] = {{131, 74, 141, 79, 80, 138, 95, 104, 134}, {95, 99, 91, 125, 93, 76, 123, 115, 123}};

const uint8_t silk_shell_code_table0[152] = {128, 0,   214, 42,  0,   235, 128, 21,  0,   244, 184, 72,  11,  0,   248, 214, 128, 42,  7,   0,   248, 225, 170, 80,  25,  5,   0,   251, 236, 198, 126,
                                             54,  18,  3,   0,   250, 238, 211, 159, 82,  35,  15,  5,   0,   250, 231, 203, 168, 128, 88,  53,  25,  6,   0,   252, 238, 216, 185, 148, 108, 71,  40,
                                             18,  4,   0,   253, 243, 225, 199, 166, 128, 90,  57,  31,  13,  3,   0,   254, 246, 233, 212, 183, 147, 109, 73,  44,  23,  10,  2,   0,   255, 250, 240,
                                             223, 198, 166, 128, 90,  58,  33,  16,  6,   1,   0,   255, 251, 244, 231, 210, 181, 146, 110, 75,  46,  25,  12,  5,   1,   0,   255, 253, 248, 238, 221,
                                             196, 164, 128, 92,  60,  35,  18,  8,   3,   1,   0,   255, 253, 249, 242, 229, 208, 180, 146, 110, 76,  48,  27,  14,  7,   3,   1,   0};

const uint8_t silk_shell_code_table1[152] = {129, 0,   207, 50,  0,   236, 129, 20,  0,   245, 185, 72,  10,  0,   249, 213, 129, 42,  6,   0,   250, 226, 169, 87,  27,  4,   0,   251, 233, 194, 130,
                                             62,  20,  4,   0,   250, 236, 207, 160, 99,  47,  17,  3,   0,   255, 240, 217, 182, 131, 81,  41,  11,  1,   0,   255, 254, 233, 201, 159, 107, 61,  20,
                                             2,   1,   0,   255, 249, 233, 206, 170, 128, 86,  50,  23,  7,   1,   0,   255, 250, 238, 217, 186, 148, 108, 70,  39,  18,  6,   1,   0,   255, 252, 243,
                                             226, 200, 166, 128, 90,  56,  30,  13,  4,   1,   0,   255, 252, 245, 231, 209, 180, 146, 110, 76,  47,  25,  11,  4,   1,   0,   255, 253, 248, 237, 219,
                                             194, 163, 128, 93,  62,  37,  19,  8,   3,   1,   0,   255, 254, 250, 241, 226, 205, 177, 145, 111, 79,  51,  30,  15,  6,   2,   1,   0};

const uint8_t silk_shell_code_table2[152] = {129, 0,   203, 54,  0,   234, 129, 23,  0,   245, 184, 73,  10,  0,   250, 215, 129, 41,  5,   0,   252, 232, 173, 86,  24,  3,   0,   253, 240, 200, 129,
                                             56,  15,  2,   0,   253, 244, 217, 164, 94,  38,  10,  1,   0,   253, 245, 226, 189, 132, 71,  27,  7,   1,   0,   253, 246, 231, 203, 159, 105, 56,  23,
                                             6,   1,   0,   255, 248, 235, 213, 179, 133, 85,  47,  19,  5,   1,   0,   255, 254, 243, 221, 194, 159, 117, 70,  37,  12,  2,   1,   0,   255, 254, 248,
                                             234, 208, 171, 128, 85,  48,  22,  8,   2,   1,   0,   255, 254, 250, 240, 220, 189, 149, 107, 67,  36,  16,  6,   2,   1,   0,   255, 254, 251, 243, 227,
                                             201, 166, 128, 90,  55,  29,  13,  5,   2,   1,   0,   255, 254, 252, 246, 234, 213, 183, 147, 109, 73,  43,  22,  10,  4,   2,   1,   0};

const uint8_t silk_shell_code_table3[152] = {130, 0,   200, 58,  0,   231, 130, 26,  0,   244, 184, 76,  12,  0,   249, 214, 130, 43,  6,   0,   252, 232, 173, 87,  24,  3,   0,   253, 241, 203, 131,
                                             56,  14,  2,   0,   254, 246, 221, 167, 94,  35,  8,   1,   0,   254, 249, 232, 193, 130, 65,  23,  5,   1,   0,   255, 251, 239, 211, 162, 99,  45,  15,
                                             4,   1,   0,   255, 251, 243, 223, 186, 131, 74,  33,  11,  3,   1,   0,   255, 252, 245, 230, 202, 158, 105, 57,  24,  8,   2,   1,   0,   255, 253, 247,
                                             235, 214, 179, 132, 84,  44,  19,  7,   2,   1,   0,   255, 254, 250, 240, 223, 196, 159, 112, 69,  36,  15,  6,   2,   1,   0,   255, 254, 253, 245, 231,
                                             209, 176, 136, 93,  55,  27,  11,  3,   2,   1,   0,   255, 254, 253, 252, 239, 221, 194, 158, 117, 76,  42,  18,  4,   3,   2,   1,   0};

const uint8_t silk_shell_code_table_offsets[17] = {0, 0, 2, 5, 9, 14, 20, 27, 35, 44, 54, 65, 77, 90, 104, 119, 135};

const uint8_t silk_sign_iCDF[42] = {254, 49, 67, 77, 82, 93, 99, 198, 11, 18,  24,  31,  36,  45,  255, 46, 66, 78, 87, 94, 104,
                                    208, 14, 21, 32, 42, 51, 66, 255, 94, 104, 109, 112, 115, 118, 248, 53, 69, 80, 88, 95, 102};

static const uint8_t silk_NLSF_CB1_NB_MB_Q8[320] = {
    12, 35, 60, 83, 108, 132, 157, 180, 206, 228, 15, 32, 55, 77,  101, 125, 151, 175, 201, 225, 19, 42, 66, 89,  114, 137, 162, 184, 209, 230, 12, 25, 50, 72, 97,  120, 147, 172, 200, 223,
    26, 44, 69, 90, 114, 135, 159, 180, 205, 225, 13, 22, 53, 80,  106, 130, 156, 180, 205, 228, 15, 25, 44, 64,  90,  115, 142, 168, 196, 222, 19, 24, 62, 82, 100, 120, 145, 168, 190, 214,
    22, 31, 50, 79, 103, 120, 151, 170, 203, 227, 21, 29, 45, 65,  106, 124, 150, 171, 196, 224, 30, 49, 75, 97,  121, 142, 165, 186, 209, 229, 19, 25, 52, 70, 93,  116, 143, 166, 192, 219,
    26, 34, 62, 75, 97,  118, 145, 167, 194, 217, 25, 33, 56, 70,  91,  113, 143, 165, 196, 223, 21, 34, 51, 72,  97,  117, 145, 171, 196, 222, 20, 29, 50, 67, 90,  117, 144, 168, 197, 221,
    22, 31, 48, 66, 95,  117, 146, 168, 196, 222, 24, 33, 51, 77,  116, 134, 158, 180, 200, 224, 21, 28, 70, 87,  106, 124, 149, 170, 194, 217, 26, 33, 53, 64, 83,  117, 152, 173, 204, 225,
    27, 34, 65, 95, 108, 129, 155, 174, 210, 225, 20, 26, 72, 99,  113, 131, 154, 176, 200, 219, 34, 43, 61, 78,  93,  114, 155, 177, 205, 229, 23, 29, 54, 97, 124, 138, 163, 179, 209, 229,
    30, 38, 56, 89, 118, 129, 158, 178, 200, 231, 21, 29, 49, 63,  85,  111, 142, 163, 193, 222, 27, 48, 77, 103, 133, 158, 179, 196, 215, 232, 29, 47, 74, 99, 124, 151, 176, 198, 220, 237,
    33, 42, 61, 76, 93,  121, 155, 174, 207, 225, 29, 53, 87, 112, 136, 154, 170, 188, 208, 227, 24, 30, 52, 84,  131, 150, 166, 186, 203, 229, 37, 48, 64, 84, 104, 118, 156, 177, 201, 230};

static const int16_t silk_NLSF_CB1_Wght_Q9[320] = {
    2897, 2314, 2314, 2314, 2287, 2287, 2314, 2300, 2327, 2287, 2888, 2580, 2394, 2367, 2314, 2274, 2274, 2274, 2274, 2194, 2487, 2340, 2340, 2314, 2314, 2314, 2340, 2340, 2367, 2354, 3216, 2766,
    2340, 2340, 2314, 2274, 2221, 2207, 2261, 2194, 2460, 2474, 2367, 2394, 2394, 2394, 2394, 2367, 2407, 2314, 3479, 3056, 2127, 2207, 2274, 2274, 2274, 2287, 2314, 2261, 3282, 3141, 2580, 2394,
    2247, 2221, 2207, 2194, 2194, 2114, 4096, 3845, 2221, 2620, 2620, 2407, 2314, 2394, 2367, 2074, 3178, 3244, 2367, 2221, 2553, 2434, 2340, 2314, 2167, 2221, 3338, 3488, 2726, 2194, 2261, 2460,
    2354, 2367, 2207, 2101, 2354, 2420, 2327, 2367, 2394, 2420, 2420, 2420, 2460, 2367, 3779, 3629, 2434, 2527, 2367, 2274, 2274, 2300, 2207, 2048, 3254, 3225, 2713, 2846, 2447, 2327, 2300, 2300,
    2274, 2127, 3263, 3300, 2753, 2806, 2447, 2261, 2261, 2247, 2127, 2101, 2873, 2981, 2633, 2367, 2407, 2354, 2194, 2247, 2247, 2114, 3225, 3197, 2633, 2580, 2274, 2181, 2247, 2221, 2221, 2141,
    3178, 3310, 2740, 2407, 2274, 2274, 2274, 2287, 2194, 2114, 3141, 3272, 2460, 2061, 2287, 2500, 2367, 2487, 2434, 2181, 3507, 3282, 2314, 2700, 2647, 2474, 2367, 2394, 2340, 2127, 3423, 3535,
    3038, 3056, 2300, 1950, 2221, 2274, 2274, 2274, 3404, 3366, 2087, 2687, 2873, 2354, 2420, 2274, 2474, 2540, 3760, 3488, 1950, 2660, 2897, 2527, 2394, 2367, 2460, 2261, 3028, 3272, 2740, 2888,
    2740, 2154, 2127, 2287, 2234, 2247, 3695, 3657, 2025, 1969, 2660, 2700, 2580, 2500, 2327, 2367, 3207, 3413, 2354, 2074, 2888, 2888, 2340, 2487, 2247, 2167, 3338, 3366, 2846, 2780, 2327, 2154,
    2274, 2287, 2114, 2061, 2327, 2300, 2181, 2167, 2181, 2367, 2633, 2700, 2700, 2553, 2407, 2434, 2221, 2261, 2221, 2221, 2340, 2420, 2607, 2700, 3038, 3244, 2806, 2888, 2474, 2074, 2300, 2314,
    2354, 2380, 2221, 2154, 2127, 2287, 2500, 2793, 2793, 2620, 2580, 2367, 3676, 3713, 2234, 1838, 2181, 2753, 2726, 2673, 2513, 2207, 2793, 3160, 2726, 2553, 2846, 2513, 2181, 2394, 2221, 2181};

static const uint8_t silk_NLSF_CB1_iCDF_NB_MB[64] = {212, 178, 148, 129, 108, 96,  85,  82,  79,  77,  61,  59,  57,  56,  51,  49,  48,  45, 42, 41, 40, 38, 36, 34, 31, 30, 21, 12, 10, 3,  1, 0,
                                                     255, 245, 244, 236, 233, 225, 217, 203, 190, 176, 175, 161, 149, 136, 125, 114, 102, 91, 81, 71, 60, 52, 43, 35, 28, 20, 19, 18, 12, 11, 5, 0};

static const uint8_t silk_NLSF_CB2_SELECT_NB_MB[160] = {16,  0,   0,   0,   0,   99,  66,  36,  36,  34,  36,  34,  34,  34,  34,  83,  69,  36,  52,  34,  116, 102, 70,  68,  68,  176, 102,
                                                        68,  68,  34,  65,  85,  68,  84,  36,  116, 141, 152, 139, 170, 132, 187, 184, 216, 137, 132, 249, 168, 185, 139, 104, 102, 100, 68,
                                                        68,  178, 218, 185, 185, 170, 244, 216, 187, 187, 170, 244, 187, 187, 219, 138, 103, 155, 184, 185, 137, 116, 183, 155, 152, 136, 132,
                                                        217, 184, 184, 170, 164, 217, 171, 155, 139, 244, 169, 184, 185, 170, 164, 216, 223, 218, 138, 214, 143, 188, 218, 168, 244, 141, 136,
                                                        155, 170, 168, 138, 220, 219, 139, 164, 219, 202, 216, 137, 168, 186, 246, 185, 139, 116, 185, 219, 185, 138, 100, 100, 134, 100, 102,
                                                        34,  68,  68,  100, 68,  168, 203, 221, 218, 168, 167, 154, 136, 104, 70,  164, 246, 171, 137, 139, 137, 155, 218, 219, 139};

static const uint8_t silk_NLSF_CB2_iCDF_NB_MB[72] = {255, 254, 253, 238, 14, 3, 2, 1, 0, 255, 254, 252, 218, 35, 3,  2, 1, 0, 255, 254, 250, 208, 59, 4,  2, 1, 0, 255, 254, 246, 194, 71, 10, 2, 1, 0,
                                                     255, 252, 236, 183, 82, 8, 2, 1, 0, 255, 252, 235, 180, 90, 17, 2, 1, 0, 255, 248, 224, 171, 97, 30, 4, 1, 0, 255, 254, 236, 173, 95, 37, 7, 1, 0};

static const uint8_t silk_NLSF_CB2_BITS_NB_MB_Q5[72] = {255, 255, 255, 131, 6,   145, 255, 255, 255, 255, 255, 236, 93,  15,  96,  255, 255, 255, 255, 255, 194, 83,  25,  71,
                                                        221, 255, 255, 255, 255, 162, 73,  34,  66,  162, 255, 255, 255, 210, 126, 73,  43,  57,  173, 255, 255, 255, 201, 125,
                                                        71,  48,  58,  130, 255, 255, 255, 166, 110, 73,  57,  62,  104, 210, 255, 255, 251, 123, 65,  55,  68,  100, 171, 255};

static const uint8_t silk_NLSF_PRED_NB_MB_Q8[18] = {179, 138, 140, 148, 151, 149, 153, 151, 163, 116, 67, 82, 59, 92, 72, 100, 89, 92};

static const int16_t silk_NLSF_DELTA_MIN_NB_MB_Q15[11] = {250, 3, 6, 3, 3, 3, 4, 3, 3, 3, 461};

const uint8_t silk_gain_iCDF[3][N_LEVELS_QGAIN / 8] = {{224, 112, 44, 15, 3, 2, 1, 0}, {254, 237, 192, 132, 70, 23, 4, 0}, {255, 252, 226, 155, 61, 11, 2, 0}};

const uint8_t silk_delta_gain_iCDF[MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1] = {250, 245, 234, 203, 71, 50, 42, 38, 35, 33, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20,
                                                                                       19,  18,  17,  16,  15, 14, 13, 12, 11, 10, 9,  8,  7,  6,  5,  4,  3,  2,  1,  0};

const uint8_t silk_pitch_lag_iCDF[2 * (PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS)] = {253, 250, 244, 233, 212, 182, 150, 131, 120, 110, 98, 85, 72, 60, 49, 40,
                                                                                        32,  25,  19,  15,  13,  11,  9,   8,   7,   6,   5,  4,  3,  2,  1,  0};

const uint8_t silk_pitch_delta_iCDF[21] = {210, 208, 206, 203, 199, 193, 183, 168, 142, 104, 74, 52, 37, 27, 20, 14, 10, 6, 4, 2, 0};

const uint8_t silk_pitch_contour_iCDF[34] = {223, 201, 183, 167, 152, 138, 124, 111, 98, 88, 79, 70, 62, 56, 50, 44, 39, 35, 31, 27, 24, 21, 18, 16, 14, 12, 10, 8, 6, 4, 3, 2, 1, 0};

const uint8_t silk_pitch_contour_NB_iCDF[11] = {188, 176, 155, 138, 119, 97, 67, 43, 26, 10, 0};

const uint8_t silk_pitch_contour_10_ms_iCDF[12] = {165, 119, 80, 61, 47, 35, 27, 20, 14, 9, 4, 0};

const uint8_t silk_pitch_contour_10_ms_NB_iCDF[3] = {113, 63, 0};

const uint8_t silk_LTP_per_index_iCDF[3] = {179, 99, 0};

static const uint8_t silk_LTP_gain_iCDF_0[8] = {71, 56, 43, 30, 21, 12, 6, 0};

static const uint8_t silk_LTP_gain_iCDF_1[16] = {199, 165, 144, 124, 109, 96, 84, 71, 61, 51, 42, 32, 23, 15, 8, 0};

static const uint8_t silk_LTP_gain_iCDF_2[32] = {241, 225, 211, 199, 187, 175, 164, 153, 142, 132, 123, 114, 105, 96, 88, 80, 72, 64, 57, 50, 44, 38, 33, 29, 24, 20, 16, 12, 9, 5, 2, 0};

static const uint8_t silk_LTP_gain_BITS_Q5_0[8] = {15, 131, 138, 138, 155, 155, 173, 173};

static const uint8_t silk_LTP_gain_BITS_Q5_1[16] = {69, 93, 115, 118, 131, 138, 141, 138, 150, 150, 155, 150, 155, 160, 166, 160};

static const uint8_t silk_LTP_gain_BITS_Q5_2[32] = {131, 128, 134, 141, 141, 141, 145, 145, 145, 150, 155, 155, 155, 155, 160, 160,
                                                    160, 160, 166, 166, 173, 173, 182, 192, 182, 192, 192, 192, 205, 192, 205, 224};

const uint8_t* const silk_LTP_gain_iCDF_ptrs[NB_LTP_CBKS] = {silk_LTP_gain_iCDF_0, silk_LTP_gain_iCDF_1, silk_LTP_gain_iCDF_2};

const uint8_t* const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = {silk_LTP_gain_BITS_Q5_0, silk_LTP_gain_BITS_Q5_1, silk_LTP_gain_BITS_Q5_2};

static const int8_t silk_LTP_gain_vq_0[8][5] = {{4, 6, 24, 7, 5},    {0, 0, 2, 0, 0},      {12, 28, 41, 13, -4}, {-9, 15, 42, 25, 14},
                                                {1, -2, 62, 41, -9}, {-10, 37, 65, -4, 3}, {-6, 4, 66, 7, -8},   {16, 14, 38, -3, 33}};

static const int8_t silk_LTP_gain_vq_1[16][5] = {{13, 22, 39, 23, 12}, {-1, 36, 64, 27, -6}, {-7, 10, 55, 43, 17}, {1, 1, 8, 1, 1},     {6, -11, 74, 53, -9}, {-12, 55, 76, -12, 8},
                                                 {-3, 3, 93, 27, -4},  {26, 39, 59, 3, -8},  {2, 0, 77, 11, 9},    {-8, 22, 44, -6, 7}, {40, 9, 26, 3, 9},    {-7, 20, 101, -7, 4},
                                                 {3, -8, 42, 26, 0},   {-15, 33, 68, 2, 23}, {-2, 55, 46, -2, 15}, {3, -1, 21, 16, 41}};

static const int8_t silk_LTP_gain_vq_2[32][5] = {
    {-6, 27, 61, 39, 5},   {-11, 42, 88, 4, 1},    {-2, 60, 65, 6, -4},  {-1, -5, 73, 56, 1},    {-9, 19, 94, 29, -9},  {0, 12, 99, 6, 4},      {8, -19, 102, 46, -13}, {3, 2, 13, 3, 2},
    {9, -21, 84, 72, -18}, {-11, 46, 104, -22, 8}, {18, 38, 48, 23, 0},  {-16, 70, 83, -21, 11}, {5, -11, 117, 22, -8}, {-6, 23, 117, -12, 3},  {3, -8, 95, 28, 4},     {-10, 15, 77, 60, -15},
    {-1, 4, 124, 2, -4},   {3, 38, 84, 24, -25},   {2, 13, 42, 13, 31},  {21, -4, 56, 46, -1},   {-1, 35, 79, -13, 19}, {-7, 65, 88, -9, -14},  {20, 4, 81, 49, -29},   {20, 0, 75, 3, -17},
    {5, -9, 44, 92, -8},   {1, -3, 22, 69, 31},    {-6, 95, 41, -12, 5}, {39, 67, 16, -4, 1},    {0, -6, 120, 55, -36}, {-13, 44, 122, 4, -24}, {81, 5, 11, 3, 7},      {2, 0, 9, 10, 88}};

static const uint8_t silk_NLSF_CB1_WB_Q8[512] = {
    7,   23,  38,  54,  69,  85,  100, 116, 131, 147, 162, 178, 193, 208, 223, 239, 13,  25,  41,  55,  69,  83,  98,  112, 127, 142, 157, 171, 187, 203, 220, 236, 15,  21,  34,  51,  61,
    78,  92,  106, 126, 136, 152, 167, 185, 205, 225, 240, 10,  21,  36,  50,  63,  79,  95,  110, 126, 141, 157, 173, 189, 205, 221, 237, 17,  20,  37,  51,  59,  78,  89,  107, 123, 134,
    150, 164, 184, 205, 224, 240, 10,  15,  32,  51,  67,  81,  96,  112, 129, 142, 158, 173, 189, 204, 220, 236, 8,   21,  37,  51,  65,  79,  98,  113, 126, 138, 155, 168, 179, 192, 209,
    218, 12,  15,  34,  55,  63,  78,  87,  108, 118, 131, 148, 167, 185, 203, 219, 236, 16,  19,  32,  36,  56,  79,  91,  108, 118, 136, 154, 171, 186, 204, 220, 237, 11,  28,  43,  58,
    74,  89,  105, 120, 135, 150, 165, 180, 196, 211, 226, 241, 6,   16,  33,  46,  60,  75,  92,  107, 123, 137, 156, 169, 185, 199, 214, 225, 11,  19,  30,  44,  57,  74,  89,  105, 121,
    135, 152, 169, 186, 202, 218, 234, 12,  19,  29,  46,  57,  71,  88,  100, 120, 132, 148, 165, 182, 199, 216, 233, 17,  23,  35,  46,  56,  77,  92,  106, 123, 134, 152, 167, 185, 204,
    222, 237, 14,  17,  45,  53,  63,  75,  89,  107, 115, 132, 151, 171, 188, 206, 221, 240, 9,   16,  29,  40,  56,  71,  88,  103, 119, 137, 154, 171, 189, 205, 222, 237, 16,  19,  36,
    48,  57,  76,  87,  105, 118, 132, 150, 167, 185, 202, 218, 236, 12,  17,  29,  54,  71,  81,  94,  104, 126, 136, 149, 164, 182, 201, 221, 237, 15,  28,  47,  62,  79,  97,  115, 129,
    142, 155, 168, 180, 194, 208, 223, 238, 8,   14,  30,  45,  62,  78,  94,  111, 127, 143, 159, 175, 192, 207, 223, 239, 17,  30,  49,  62,  79,  92,  107, 119, 132, 145, 160, 174, 190,
    204, 220, 235, 14,  19,  36,  45,  61,  76,  91,  108, 121, 138, 154, 172, 189, 205, 222, 238, 12,  18,  31,  45,  60,  76,  91,  107, 123, 138, 154, 171, 187, 204, 221, 236, 13,  17,
    31,  43,  53,  70,  83,  103, 114, 131, 149, 167, 185, 203, 220, 237, 17,  22,  35,  42,  58,  78,  93,  110, 125, 139, 155, 170, 188, 206, 224, 240, 8,   15,  34,  50,  67,  83,  99,
    115, 131, 146, 162, 178, 193, 209, 224, 239, 13,  16,  41,  66,  73,  86,  95,  111, 128, 137, 150, 163, 183, 206, 225, 241, 17,  25,  37,  52,  63,  75,  92,  102, 119, 132, 144, 160,
    175, 191, 212, 231, 19,  31,  49,  65,  83,  100, 117, 133, 147, 161, 174, 187, 200, 213, 227, 242, 18,  31,  52,  68,  88,  103, 117, 126, 138, 149, 163, 177, 192, 207, 223, 239, 16,
    29,  47,  61,  76,  90,  106, 119, 133, 147, 161, 176, 193, 209, 224, 240, 15,  21,  35,  50,  61,  73,  86,  97,  110, 119, 129, 141, 175, 198, 218, 237};

static const int16_t silk_NLSF_CB1_WB_Wght_Q9[512] = {
    3657, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2963, 2963, 2925, 2846, 3216, 3085, 2972, 3056, 3056, 3010, 3010, 3010, 2963, 2963, 3010, 2972, 2888, 2846, 2846, 2726,
    3920, 4014, 2981, 3207, 3207, 2934, 3056, 2846, 3122, 3244, 2925, 2846, 2620, 2553, 2780, 2925, 3516, 3197, 3010, 3103, 3019, 2888, 2925, 2925, 2925, 2925, 2888, 2888, 2888, 2888, 2888, 2753,
    5054, 5054, 2934, 3573, 3385, 3056, 3085, 2793, 3160, 3160, 2972, 2846, 2513, 2540, 2753, 2888, 4428, 4149, 2700, 2753, 2972, 3010, 2925, 2846, 2981, 3019, 2925, 2925, 2925, 2925, 2888, 2726,
    3620, 3019, 2972, 3056, 3056, 2873, 2806, 3056, 3216, 3047, 2981, 3291, 3291, 2981, 3310, 2991, 5227, 5014, 2540, 3338, 3526, 3385, 3197, 3094, 3376, 2981, 2700, 2647, 2687, 2793, 2846, 2673,
    5081, 5174, 4615, 4428, 2460, 2897, 3047, 3207, 3169, 2687, 2740, 2888, 2846, 2793, 2846, 2700, 3122, 2888, 2963, 2925, 2925, 2925, 2925, 2963, 2963, 2963, 2963, 2925, 2925, 2963, 2963, 2963,
    4202, 3207, 2981, 3103, 3010, 2888, 2888, 2925, 2972, 2873, 2916, 3019, 2972, 3010, 3197, 2873, 3760, 3760, 3244, 3103, 2981, 2888, 2925, 2888, 2972, 2934, 2793, 2793, 2846, 2888, 2888, 2660,
    3854, 4014, 3207, 3122, 3244, 2934, 3047, 2963, 2963, 3085, 2846, 2793, 2793, 2793, 2793, 2580, 3845, 4080, 3357, 3516, 3094, 2740, 3010, 2934, 3122, 3085, 2846, 2846, 2647, 2647, 2846, 2806,
    5147, 4894, 3225, 3845, 3441, 3169, 2897, 3413, 3451, 2700, 2580, 2673, 2740, 2846, 2806, 2753, 4109, 3789, 3291, 3160, 2925, 2888, 2888, 2925, 2793, 2740, 2793, 2740, 2793, 2846, 2888, 2806,
    5081, 5054, 3047, 3545, 3244, 3056, 3085, 2944, 3103, 2897, 2740, 2740, 2740, 2846, 2793, 2620, 4309, 4309, 2860, 2527, 3207, 3376, 3376, 3075, 3075, 3376, 3056, 2846, 2647, 2580, 2726, 2753,
    3056, 2916, 2806, 2888, 2740, 2687, 2897, 3103, 3150, 3150, 3216, 3169, 3056, 3010, 2963, 2846, 4375, 3882, 2925, 2888, 2846, 2888, 2846, 2846, 2888, 2888, 2888, 2846, 2888, 2925, 2888, 2846,
    2981, 2916, 2916, 2981, 2981, 3056, 3122, 3216, 3150, 3056, 3010, 2972, 2972, 2972, 2925, 2740, 4229, 4149, 3310, 3347, 2925, 2963, 2888, 2981, 2981, 2846, 2793, 2740, 2846, 2846, 2846, 2793,
    4080, 4014, 3103, 3010, 2925, 2925, 2925, 2888, 2925, 2925, 2846, 2846, 2846, 2793, 2888, 2780, 4615, 4575, 3169, 3441, 3207, 2981, 2897, 3038, 3122, 2740, 2687, 2687, 2687, 2740, 2793, 2700,
    4149, 4269, 3789, 3657, 2726, 2780, 2888, 2888, 3010, 2972, 2925, 2846, 2687, 2687, 2793, 2888, 4215, 3554, 2753, 2846, 2846, 2888, 2888, 2888, 2925, 2925, 2888, 2925, 2925, 2925, 2963, 2888,
    5174, 4921, 2261, 3432, 3789, 3479, 3347, 2846, 3310, 3479, 3150, 2897, 2460, 2487, 2753, 2925, 3451, 3685, 3122, 3197, 3357, 3047, 3207, 3207, 2981, 3216, 3085, 2925, 2925, 2687, 2540, 2434,
    2981, 3010, 2793, 2793, 2740, 2793, 2846, 2972, 3056, 3103, 3150, 3150, 3150, 3103, 3010, 3010, 2944, 2873, 2687, 2726, 2780, 3010, 3432, 3545, 3357, 3244, 3056, 3010, 2963, 2925, 2888, 2846,
    3019, 2944, 2897, 3010, 3010, 2972, 3019, 3103, 3056, 3056, 3010, 2888, 2846, 2925, 2925, 2888, 3920, 3967, 3010, 3197, 3357, 3216, 3291, 3291, 3479, 3704, 3441, 2726, 2181, 2460, 2580, 2607};

static const uint8_t silk_NLSF_CB1_iCDF_WB[64] = {225, 204, 201, 184, 183, 175, 158, 154, 153, 135, 119, 115, 113, 110, 109, 99,  98, 95, 79, 68, 52, 50, 48, 45, 43, 32, 31, 27, 18, 10, 3, 0,
                                                  255, 251, 235, 230, 212, 201, 196, 182, 167, 166, 163, 151, 138, 124, 110, 104, 90, 78, 76, 70, 69, 57, 45, 34, 24, 21, 11, 6,  5,  4,  3, 0};

static const uint8_t silk_NLSF_CB2_SELECT_WB[256] = {
    0,   0,   0,   0,   0,   0,   0,   1,   100, 102, 102, 68,  68,  36,  34,  96,  164, 107, 158, 185, 180, 185, 139, 102, 64,  66,  36,  34,  34,  0,   1,   32,  208, 139, 141, 191, 152,
    185, 155, 104, 96,  171, 104, 166, 102, 102, 102, 132, 1,   0,   0,   0,   0,   16,  16,  0,   80,  109, 78,  107, 185, 139, 103, 101, 208, 212, 141, 139, 173, 153, 123, 103, 36,  0,
    0,   0,   0,   0,   0,   1,   48,  0,   0,   0,   0,   0,   0,   32,  68,  135, 123, 119, 119, 103, 69,  98,  68,  103, 120, 118, 118, 102, 71,  98,  134, 136, 157, 184, 182, 153, 139,
    134, 208, 168, 248, 75,  189, 143, 121, 107, 32,  49,  34,  34,  34,  0,   17,  2,   210, 235, 139, 123, 185, 137, 105, 134, 98,  135, 104, 182, 100, 183, 171, 134, 100, 70,  68,  70,
    66,  66,  34,  131, 64,  166, 102, 68,  36,  2,   1,   0,   134, 166, 102, 68,  34,  34,  66,  132, 212, 246, 158, 139, 107, 107, 87,  102, 100, 219, 125, 122, 137, 118, 103, 132, 114,
    135, 137, 105, 171, 106, 50,  34,  164, 214, 141, 143, 185, 151, 121, 103, 192, 34,  0,   0,   0,   0,   0,   1,   208, 109, 74,  187, 134, 249, 159, 137, 102, 110, 154, 118, 87,  101,
    119, 101, 0,   2,   0,   36,  36,  66,  68,  35,  96,  164, 102, 100, 36,  0,   2,   33,  167, 138, 174, 102, 100, 84,  2,   2,   100, 107, 120, 119, 36,  197, 24,  0};

static const uint8_t silk_NLSF_CB2_iCDF_WB[72] = {255, 254, 253, 244, 12, 3, 2, 1, 0, 255, 254, 252, 224, 38, 3,  2, 1, 0, 255, 254, 251, 209, 57, 4,  2, 1, 0, 255, 254, 244, 195, 69,  4,  2, 1, 0,
                                                  255, 251, 232, 184, 84, 7, 2, 1, 0, 255, 254, 240, 186, 86, 14, 2, 1, 0, 255, 254, 239, 178, 91, 30, 5, 1, 0, 255, 248, 227, 177, 100, 19, 2, 1, 0};

static const uint8_t silk_NLSF_CB2_BITS_WB_Q5[72] = {255, 255, 255, 156, 4,   154, 255, 255, 255, 255, 255, 227, 102, 15,  92,  255, 255, 255, 255, 255, 213, 83,  24,  72,
                                                     236, 255, 255, 255, 255, 150, 76,  33,  63,  214, 255, 255, 255, 190, 121, 77,  43,  55,  185, 255, 255, 255, 245, 137,
                                                     71,  43,  59,  139, 255, 255, 255, 255, 131, 66,  50,  66,  107, 194, 255, 255, 166, 116, 76,  55,  53,  125, 255, 255};

static const uint8_t silk_NLSF_PRED_WB_Q8[30] = {175, 148, 160, 176, 178, 173, 174, 164, 177, 174, 196, 182, 198, 192, 182, 68, 62, 66, 60, 72, 117, 85, 90, 118, 136, 151, 142, 160, 142, 155};

static const int16_t silk_NLSF_DELTA_MIN_WB_Q15[17] = {100, 3, 40, 3, 3, 3, 5, 14, 14, 10, 11, 3, 8, 9, 7, 3, 347};

const int8_t silk_CB_lags_stage2_10_ms[PE_MAX_NB_SUBFR >> 1][PE_NB_CBKS_STAGE2_10MS] = {{0, 1, 0}, {0, 0, 1}};

const int8_t silk_CB_lags_stage3_10_ms[PE_MAX_NB_SUBFR >> 1][PE_NB_CBKS_STAGE3_10MS] = {{0, 0, 1, -1, 1, -1, 2, -2, 2, -2, 3, -3}, {0, 1, 0, 1, -1, 2, -1, 2, -2, 3, -2, 3}};

const int8_t silk_Lag_range_stage3_10_ms[PE_MAX_NB_SUBFR >> 1][2] = {{-3, 7}, {-2, 7}};

const int8_t silk_CB_lags_stage2[PE_MAX_NB_SUBFR][PE_NB_CBKS_STAGE2_EXT] = {{0, 2, -1, -1, -1, 0, 0, 1, 1, 0, 1},
                                                                            {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0},
                                                                            {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0},
                                                                            {0, -1, 2, 1, 0, 1, 1, 0, 0, -1, -1}};

const int8_t silk_CB_lags_stage3[PE_MAX_NB_SUBFR][PE_NB_CBKS_STAGE3_MAX] = {{0, 0, 1, -1, 0, 1, -1, 0, -1, 1, -2, 2, -2, -2, 2, -3, 2, 3, -3, -4, 3, -4, 4, 4, -5, 5, -6, -5, 6, -7, 6, 5, 8, -9},
                                                                            {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 1, -1, 0, 1, -1, -1, 1, -1, 2, 1, -1, 2, -2, -2, 2, -2, 2, 2, 3, -3},
                                                                            {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, -1, 1, 0, 0, 2, 1, -1, 2, -1, -1, 2, -1, 2, 2, -1, 3, -2, -2, -2, 3},
                                                                            {0, 1, 0, 0, 1, 0, 1, -1, 2, -1, 2, -1, 2, 3, -2, 3, -2, -2, 4, 4, -3, 5, -3, -4, 6, -4, 6, 5, -5, 8, -6, -5, -7, 9}};

const int8_t silk_Lag_range_stage3[SILK_PE_MAX_COMPLEX + 1][PE_MAX_NB_SUBFR][2] = {
    /* Lags to search for low number of stage3 cbks */
    {{-5, 8}, {-1, 6}, {-1, 6}, {-4, 10}},
    /* Lags to search for middle number of stage3 cbks */
    {{-6, 10}, {-2, 6}, {-1, 6}, {-5, 10}},
    /* Lags to search for max number of stage3 cbks */
    {{-9, 12}, {-3, 7}, {-2, 7}, {-7, 13}}};

/* Tables with delay compensation values to equalize total delay for different modes */
static const int8_t delay_matrix_enc[5][3] = {
    /* in  \ out  8  12  16 */
    /*  8 */ {6, 0, 3},
    /* 12 */ {0, 7, 3},
    /* 16 */ {0, 1, 10},
    /* 24 */ {0, 2, 6},
    /* 48 */ {18, 10, 12}};

static const int8_t delay_matrix_dec[3][5] = {
    /* in  \ out  8  12  16  24  48 */
    /*  8 */ {4, 0, 2, 0, 0},
    /* 12 */ {0, 9, 4, 7, 4},
    /* 16 */ {0, 3, 12, 7, 7}};

/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */
const int16_t silk_Resampler_3_4_COEFS[2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2] = {
    -20694, -13867, -49, 64, 17, -157, 353, -496, 163, 11047, 22205, -39, 6, 91, -170, 186, 23, -896, 6336, 19928, -19, -36, 102, -89, -24, 328, -951, 2568, 15909,
};

const int16_t silk_Resampler_2_3_COEFS[2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2] = {
    -14457, -14019, 64, 128, -122, 36, 310, -768, 584, 9267, 17733, 12, 128, 18, -142, 288, -117, -865, 4123, 14459,
};

const int16_t silk_Resampler_1_2_COEFS[2 + RESAMPLER_DOWN_ORDER_FIR1 / 2] = {
    616, -14323, -10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024,
};

const int16_t silk_Resampler_1_3_COEFS[2 + RESAMPLER_DOWN_ORDER_FIR2 / 2] = {
    16102, -15162, -13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271,
};

const int16_t silk_Resampler_1_4_COEFS[2 + RESAMPLER_DOWN_ORDER_FIR2 / 2] = {
    22500, -15099, 3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464,
};

const int16_t silk_Resampler_1_6_COEFS[2 + RESAMPLER_DOWN_ORDER_FIR2 / 2] = {
    27540, -15257, 17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455,
};

const int16_t silk_Resampler_2_3_COEFS_LQ[2 + 2 * 2] = {
    -2797, -6507, 4697, 10739, 1567, 8276,
};

/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */
const int16_t silk_resampler_frac_FIR_12[12][RESAMPLER_ORDER_FIR_12 / 2] = {
    {189, -600, 617, 30567},  {117, -159, -1070, 29704}, {52, 221, -2392, 28276},   {-4, 529, -3350, 26341}, {-48, 758, -3956, 23973}, {-80, 905, -4235, 21254},
    {-99, 972, -4222, 18278}, {-107, 967, -3957, 15143}, {-103, 896, -3487, 11950}, {-91, 773, -2865, 8798}, {-71, 611, -2143, 5784},  {-46, 425, -1375, 2996},
};

/* Tables for 2x downsampler */
static const int16_t silk_resampler_down2_0 = 9872;
static const int16_t silk_resampler_down2_1 = 39809 - 65536;

/* Tables for 2x upsampler, high quality */
static const int16_t silk_resampler_up2_hq_0[3] = {1746, 14986, 39083 - 65536};
static const int16_t silk_resampler_up2_hq_1[3] = {6854, 25769, 55542 - 65536};

/* fprintf(1, '%d, ', round(1024 * ([1 ./ (1 + exp(-(1:5))), 1] - 1 ./ (1 + exp(-(0:5)))))); */
static const int32_t sigm_LUT_slope_Q10[6] = {237, 153, 73, 30, 12, 7};
/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp(-(0:5))))); */
static const int32_t sigm_LUT_pos_Q15[6] = {16384, 23955, 28861, 31213, 32178, 32548};
/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp((0:5))))); */
static const int32_t sigm_LUT_neg_Q15[6] = {16384, 8812, 3906, 1554, 589, 219};

const int8_t silk_nb_cbk_searchs_stage3[SILK_PE_MAX_COMPLEX + 1] = {PE_NB_CBKS_STAGE3_MIN, PE_NB_CBKS_STAGE3_MID, PE_NB_CBKS_STAGE3_MAX};

const silk_NLSF_CB_struct silk_NLSF_CB_WB = {
    32,
    16,
    SILK_FIX_CONST(0.15, 16),
    SILK_FIX_CONST(1.0 / 0.15, 6),
    silk_NLSF_CB1_WB_Q8,
    silk_NLSF_CB1_WB_Wght_Q9,
    silk_NLSF_CB1_iCDF_WB,
    silk_NLSF_PRED_WB_Q8,
    silk_NLSF_CB2_SELECT_WB,
    silk_NLSF_CB2_iCDF_WB,
    silk_NLSF_CB2_BITS_WB_Q5,
    silk_NLSF_DELTA_MIN_WB_Q15,
};

const int8_t* const silk_LTP_vq_ptrs_Q7[NB_LTP_CBKS] = {(int8_t*)&silk_LTP_gain_vq_0[0][0], (int8_t*)&silk_LTP_gain_vq_1[0][0], (int8_t*)&silk_LTP_gain_vq_2[0][0]};

/* Maximum frequency-dependent response of the pitch taps above,
   computed as max(abs(freqz(taps))) */
static const uint8_t silk_LTP_gain_vq_0_gain[8] = {46, 2, 90, 87, 93, 91, 82, 98};

static const uint8_t silk_LTP_gain_vq_1_gain[16] = {109, 120, 118, 12, 113, 115, 117, 119, 99, 59, 87, 111, 63, 111, 112, 80};

static const uint8_t silk_LTP_gain_vq_2_gain[32] = {126, 124, 125, 124, 129, 121, 126, 23, 132, 127, 127, 127, 126, 127, 122, 133,
                                                    130, 134, 101, 118, 119, 145, 126, 86, 124, 120, 123, 119, 170, 173, 107, 109};

const uint8_t* const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS] = {&silk_LTP_gain_vq_0_gain[0], &silk_LTP_gain_vq_1_gain[0], &silk_LTP_gain_vq_2_gain[0]};

const int8_t silk_LTP_vq_sizes[NB_LTP_CBKS] = {8, 16, 32};

const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB = {
    32,
    10,
    SILK_FIX_CONST(0.18, 16),
    SILK_FIX_CONST(1.0 / 0.18, 6),
    silk_NLSF_CB1_NB_MB_Q8,
    silk_NLSF_CB1_Wght_Q9,
    silk_NLSF_CB1_iCDF_NB_MB,
    silk_NLSF_PRED_NB_MB_Q8,
    silk_NLSF_CB2_SELECT_NB_MB,
    silk_NLSF_CB2_iCDF_NB_MB,
    silk_NLSF_CB2_BITS_NB_MB_Q5,
    silk_NLSF_DELTA_MIN_NB_MB_Q15,
};

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Transforms polynomials from cos(n*f) to cos(f)^n  */
void silk_A2NLSF_trans_poly(int32_t* p, const int32_t dd) {
    int32_t k, n;
    for (k = 2; k <= dd; k++) {
        for (n = dd; n > k; n--) { p[n - 2] -= p[n]; }
        p[k - 2] -= silk_LSHIFT(p[k], 1);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Polynomial evaluation          */
int32_t silk_A2NLSF_eval_poly(int32_t* p, const int32_t x, const int32_t dd) {
    int32_t n;
    int32_t x_Q16, y32;

    y32 = p[dd]; /* Q16 */
    x_Q16 = silk_LSHIFT(x, 4);

    if (8 == dd) {
        y32 = silk_SMLAWW(p[7], y32, x_Q16);
        y32 = silk_SMLAWW(p[6], y32, x_Q16);
        y32 = silk_SMLAWW(p[5], y32, x_Q16);
        y32 = silk_SMLAWW(p[4], y32, x_Q16);
        y32 = silk_SMLAWW(p[3], y32, x_Q16);
        y32 = silk_SMLAWW(p[2], y32, x_Q16);
        y32 = silk_SMLAWW(p[1], y32, x_Q16);
        y32 = silk_SMLAWW(p[0], y32, x_Q16);
    } else {
        for (n = dd - 1; n >= 0; n--) { y32 = silk_SMLAWW(p[n], y32, x_Q16); /* Q16 */ }
    }
    return y32;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_A2NLSF_init(const int32_t* a_Q16, int32_t* P, int32_t* Q, const int32_t dd) {
    int32_t k;

    /* Convert filter coefs to even and odd polynomials */
    P[dd] = silk_LSHIFT(1, 16);
    Q[dd] = silk_LSHIFT(1, 16);
    for (k = 0; k < dd; k++) {
        P[k] = -a_Q16[dd - k - 1] - a_Q16[dd + k]; /* Q16 */
        Q[k] = -a_Q16[dd - k - 1] + a_Q16[dd + k]; /* Q16 */
    }

    /* Divide out zeros as we have that for even filter orders, */
    /* z =  1 is always a root in Q, and                        */
    /* z = -1 is always a root in P                             */
    for (k = dd; k > 0; k--) {
        P[k - 1] -= P[k];
        Q[k - 1] += Q[k];
    }

    /* Transform polynomials from cos(n*f) to cos(f)^n */
    silk_A2NLSF_trans_poly(P, dd);
    silk_A2NLSF_trans_poly(Q, dd);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients      */
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
void silk_A2NLSF(int16_t*      NLSF,  /* O    Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
                 int32_t*      a_Q16, /* I/O  Monic whitening filter coefficients in Q16 [d]              */
                 const int32_t d      /* I    Filter order (must be even)                                 */
) {
    int32_t  i, k, m, dd, root_ix, ffrac;
    int32_t  xlo, xhi, xmid;
    int32_t  ylo, yhi, ymid, thr;
    int32_t  nom, den;
    int32_t  P[SILK_MAX_ORDER_LPC / 2 + 1];
    int32_t  Q[SILK_MAX_ORDER_LPC / 2 + 1];
    int32_t* PQ[2];
    int32_t* p;

    /* Store pointers to array */
    PQ[0] = P;
    PQ[1] = Q;

    dd = silk_RSHIFT(d, 1);

    silk_A2NLSF_init(a_Q16, P, Q, dd);

    /* Find roots, alternating between P and Q */
    p = P; /* Pointer to polynomial */

    xlo = silk_LSFCosTab_FIX_Q12[0]; /* Q12*/
    ylo = silk_A2NLSF_eval_poly(p, xlo, dd);

    if (ylo < 0) {
        /* Set the first NLSF to zero and move on to the next */
        NLSF[0] = 0;
        p = Q; /* Pointer to polynomial */
        ylo = silk_A2NLSF_eval_poly(p, xlo, dd);
        root_ix = 1; /* Index of current root */
    } else {
        root_ix = 0; /* Index of current root */
    }
    k = 1; /* Loop counter */
    i = 0; /* Counter for bandwidth expansions applied */
    thr = 0;
    while (1) {
        /* Evaluate polynomial */
        xhi = silk_LSFCosTab_FIX_Q12[k]; /* Q12 */
        yhi = silk_A2NLSF_eval_poly(p, xhi, dd);

        /* Detect zero crossing */
        if ((ylo <= 0 && yhi >= thr) || (ylo >= 0 && yhi <= -thr)) {
            if (yhi == 0) { /* If the root lies exactly at the end of the current interval, look for the next root in the next interval    */
                thr = 1;
            } else {
                thr = 0;
            }
            /* Binary division */
            ffrac = -256;
            for (m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++) {
                /* Evaluate polynomial */
                xmid = silk_RSHIFT_ROUND(xlo + xhi, 1);
                ymid = silk_A2NLSF_eval_poly(p, xmid, dd);

                /* Detect zero crossing */
                if ((ylo <= 0 && ymid >= 0) || (ylo >= 0 && ymid <= 0)) {
                    /* Reduce frequency */
                    xhi = xmid;
                    yhi = ymid;
                } else {
                    /* Increase frequency */
                    xlo = xmid;
                    ylo = ymid;
                    ffrac = silk_ADD_RSHIFT(ffrac, 128, m);
                }
            }

            /* Interpolate */
            if (silk_abs(ylo) < 65536) {
                /* Avoid dividing by zero */
                den = ylo - yhi;
                nom = silk_LSHIFT(ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX) + silk_RSHIFT(den, 1);
                if (den != 0) { ffrac += silk_DIV32(nom, den); }
            } else {
                /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
                ffrac += silk_DIV32(ylo, silk_RSHIFT(ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX));
            }
            NLSF[root_ix] = (int16_t)silk_min_32(silk_LSHIFT((int32_t)k, 8) + ffrac, silk_int16_MAX);

            assert(NLSF[root_ix] >= 0);

            root_ix++; /* Next root */
            if (root_ix >= d) {
                /* Found all roots */
                break;
            }
            /* Alternate pointer to polynomial */
            p = PQ[root_ix & 1];

            /* Evaluate polynomial */
            xlo = silk_LSFCosTab_FIX_Q12[k - 1]; /* Q12*/
            ylo = silk_LSHIFT(1 - (root_ix & 2), 12);
        } else {
            /* Increment loop counter */
            k++;
            xlo = xhi;
            ylo = yhi;
            thr = 0;

            if (k > LSF_COS_TAB_SZ_FIX) {
                i++;
                if (i > MAX_ITERATIONS_A2NLSF_FIX) {
                    /* Set NLSFs to white spectrum and exit */
                    NLSF[0] = (int16_t)silk_DIV32_16(1 << 15, d + 1);
                    for (k = 1; k < d; k++) { NLSF[k] = (int16_t)(NLSF[k - 1] + NLSF[0]); }
                    return;
                }

                /* Error: Apply progressively more bandwidth expansion and run again */
                silk_bwexpander_32(a_Q16, d, 65536 - silk_LSHIFT(1, i));

                silk_A2NLSF_init(a_Q16, P, Q, dd);
                p = P;                           /* Pointer to polynomial */
                xlo = silk_LSFCosTab_FIX_Q12[0]; /* Q12*/
                ylo = silk_A2NLSF_eval_poly(p, xlo, dd);
                if (ylo < 0) {
                    /* Set the first NLSF to zero and move on to the next */
                    NLSF[0] = 0;
                    p = Q; /* Pointer to polynomial */
                    ylo = silk_A2NLSF_eval_poly(p, xlo, dd);
                    root_ix = 1; /* Index of current root */
                } else {
                    root_ix = 0; /* Index of current root */
                }
                k = 1; /* Reset loop counter */
            }
        }
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Split signal into two decimated bands using first-order allpass filters */
void silk_ana_filt_bank_1(const int16_t* in,   /* I    Input signal [N]        */
                          int32_t*       S,    /* I/O  State vector [2]        */
                          int16_t*       outL, /* O    Low band [N/2]          */
                          int16_t*       outH, /* O    High band [N/2]         */
                          const int32_t  N     /* I    Number of input samples */
) {
    int32_t k, N2 = silk_RSHIFT(N, 1);
    int32_t in32, X, Y, out_1, out_2;

    /* Internal variables and state are in Q10 format */
    for (k = 0; k < N2; k++) {
        /* Convert to Q10 */
        in32 = silk_LSHIFT((int32_t)in[2 * k], 10);

        /* All-pass section for even input sample */
        Y = silk_SUB32(in32, S[0]);
        X = silk_SMLAWB(Y, Y, A_fb1_21);
        out_1 = silk_ADD32(S[0], X);
        S[0] = silk_ADD32(in32, X);

        /* Convert to Q10 */
        in32 = silk_LSHIFT((int32_t)in[2 * k + 1], 10);

        /* All-pass section for odd input sample, and add to output of previous section */
        Y = silk_SUB32(in32, S[1]);
        X = silk_SMULWB(Y, A_fb1_20);
        out_2 = silk_ADD32(S[1], X);
        S[1] = silk_ADD32(in32, X);

        /* Add/subtract, convert back to int16 and store to output */
        outL[k] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(silk_ADD32(out_2, out_1), 11));
        outH[k] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(silk_SUB32(out_2, out_1), 11));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Second order ARMA filter, alternative implementation */
void silk_biquad_alt_stride1(const int16_t* in,    /* I     input signal                 */
                             const int32_t* B_Q28, /* I     MA coefficients [3]          */
                             const int32_t* A_Q28, /* I     AR coefficients [2]          */
                             int32_t*       S,     /* I/O   State vector [2]             */
                             int16_t*       out,   /* O     output signal                */
                             const int32_t  len    /* I     signal length (must be even) */
) {
    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
    int32_t k;
    int32_t inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;

    /* Negate A_Q28 values and split in two parts */
    A0_L_Q28 = (-A_Q28[0]) & 0x00003FFF;   /* lower part */
    A0_U_Q28 = silk_RSHIFT(-A_Q28[0], 14); /* upper part */
    A1_L_Q28 = (-A_Q28[1]) & 0x00003FFF;   /* lower part */
    A1_U_Q28 = silk_RSHIFT(-A_Q28[1], 14); /* upper part */

    for (k = 0; k < len; k++) {
        /* S[ 0 ], S[ 1 ]: Q12 */
        inval = in[k];
        out32_Q14 = silk_LSHIFT(silk_SMLAWB(S[0], B_Q28[0], inval), 2);

        S[0] = S[1] + silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14, A0_L_Q28), 14);
        S[0] = silk_SMLAWB(S[0], out32_Q14, A0_U_Q28);
        S[0] = silk_SMLAWB(S[0], B_Q28[1], inval);

        S[1] = silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14, A1_L_Q28), 14);
        S[1] = silk_SMLAWB(S[1], out32_Q14, A1_U_Q28);
        S[1] = silk_SMLAWB(S[1], B_Q28[2], inval);

        /* Scale back to Q0 and saturate */
        out[k] = (int16_t)silk_SAT16(silk_RSHIFT(out32_Q14 + (1 << 14) - 1, 14));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_biquad_alt_stride2_c(const int16_t* in,    /* I     input signal                 */
                               const int32_t* B_Q28, /* I     MA coefficients [3]          */
                               const int32_t* A_Q28, /* I     AR coefficients [2]          */
                               int32_t*       S,     /* I/O   State vector [4]             */
                               int16_t*       out,   /* O     output signal                */
                               const int32_t  len    /* I     signal length (must be even) */
) {
    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
    int32_t k;
    int32_t A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[2];

    /* Negate A_Q28 values and split in two parts */
    A0_L_Q28 = (-A_Q28[0]) & 0x00003FFF;   /* lower part */
    A0_U_Q28 = silk_RSHIFT(-A_Q28[0], 14); /* upper part */
    A1_L_Q28 = (-A_Q28[1]) & 0x00003FFF;   /* lower part */
    A1_U_Q28 = silk_RSHIFT(-A_Q28[1], 14); /* upper part */

    for (k = 0; k < len; k++) {
        /* S[ 0 ], S[ 1 ], S[ 2 ], S[ 3 ]: Q12 */
        out32_Q14[0] = silk_LSHIFT(silk_SMLAWB(S[0], B_Q28[0], in[2 * k + 0]), 2);
        out32_Q14[1] = silk_LSHIFT(silk_SMLAWB(S[2], B_Q28[0], in[2 * k + 1]), 2);

        S[0] = S[1] + silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14[0], A0_L_Q28), 14);
        S[2] = S[3] + silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14[1], A0_L_Q28), 14);
        S[0] = silk_SMLAWB(S[0], out32_Q14[0], A0_U_Q28);
        S[2] = silk_SMLAWB(S[2], out32_Q14[1], A0_U_Q28);
        S[0] = silk_SMLAWB(S[0], B_Q28[1], in[2 * k + 0]);
        S[2] = silk_SMLAWB(S[2], B_Q28[1], in[2 * k + 1]);

        S[1] = silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14[0], A1_L_Q28), 14);
        S[3] = silk_RSHIFT_ROUND(silk_SMULWB(out32_Q14[1], A1_L_Q28), 14);
        S[1] = silk_SMLAWB(S[1], out32_Q14[0], A1_U_Q28);
        S[3] = silk_SMLAWB(S[3], out32_Q14[1], A1_U_Q28);
        S[1] = silk_SMLAWB(S[1], B_Q28[2], in[2 * k + 0]);
        S[3] = silk_SMLAWB(S[3], B_Q28[2], in[2 * k + 1]);

        /* Scale back to Q0 and saturate */
        out[2 * k + 0] = (int16_t)silk_SAT16(silk_RSHIFT(out32_Q14[0] + (1 << 14) - 1, 14));
        out[2 * k + 1] = (int16_t)silk_SAT16(silk_RSHIFT(out32_Q14[1] + (1 << 14) - 1, 14));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Chirp (bandwidth expand) LP AR filter */
void silk_bwexpander_32(int32_t*      ar,       /* I/O  AR filter to be expanded (without leading 1)                */
                        const int32_t d,        /* I    Length of ar                                                */
                        int32_t       chirp_Q16 /* I    Chirp factor in Q16                                         */
) {
    int32_t i;
    int32_t chirp_minus_one_Q16 = chirp_Q16 - 65536;

    for (i = 0; i < d - 1; i++) {
        ar[i] = silk_SMULWW(chirp_Q16, ar[i]);
        chirp_Q16 += silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, chirp_minus_one_Q16), 16);
    }
    ar[d - 1] = silk_SMULWW(chirp_Q16, ar[d - 1]);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Chirp (bandwidth expand) LP AR filter */
void silk_bwexpander(int16_t*      ar,       /* I/O  AR filter to be expanded (without leading 1)                */
                     const int32_t d,        /* I    Length of ar                                                */
                     int32_t       chirp_Q16 /* I    Chirp factor (typically in the range 0 to 1)                */
) {
    int32_t i;
    int32_t chirp_minus_one_Q16 = chirp_Q16 - 65536;

    /* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below. Bias in silk_SMULWB can lead to unstable filters                                */
    for (i = 0; i < d - 1; i++) {
        ar[i] = (int16_t)silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, ar[i]), 16);
        chirp_Q16 += silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, chirp_minus_one_Q16), 16);
    }
    ar[d - 1] = (int16_t)silk_RSHIFT_ROUND(silk_MUL(chirp_Q16, ar[d - 1]), 16);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decode mid/side predictors */
void silk_stereo_decode_pred(int32_t pred_Q13[]) {
    int32_t n, ix[2][3];
    int32_t low_Q13, step_Q13;

    /* Entropy decoding */
    n = ec_dec_icdf(silk_stereo_pred_joint_iCDF, 8);
    ix[0][2] = silk_DIV32_16(n, 5);
    ix[1][2] = n - 5 * ix[0][2];
    for (n = 0; n < 2; n++) {
        ix[n][0] = ec_dec_icdf(silk_uniform3_iCDF, 8);
        ix[n][1] = ec_dec_icdf(silk_uniform5_iCDF, 8);
    }

    /* Dequantize */
    for (n = 0; n < 2; n++) {
        ix[n][0] += 3 * ix[n][2];
        low_Q13 = silk_stereo_pred_quant_Q13[ix[n][0]];
        step_Q13 = silk_SMULWB(silk_stereo_pred_quant_Q13[ix[n][0] + 1] - low_Q13, SILK_FIX_CONST(0.5 / STEREO_QUANT_SUB_STEPS, 16));
        pred_Q13[n] = silk_SMLABB(low_Q13, step_Q13, 2 * ix[n][1] + 1);
    }

    /* Subtract second from first predictor (helps when actually applying these) */
    pred_Q13[0] -= pred_Q13[1];
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decode mid-only flag */
void silk_stereo_decode_mid_only(int32_t* decode_only_mid /* O    Flag that only mid channel has been coded   */
) {
    /* Decode flag that only mid channel is coded */
    *decode_only_mid = ec_dec_icdf(silk_stereo_only_code_mid_iCDF, 8);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* helper function for NLSF2A(intermediate polynomial, Q[dd+1], vector of interleaved 2*cos(LSFs), QA_[d], polynomial order (= 1/2 * filter order)  ) */
void silk_NLSF2A_find_poly(int32_t* out, const int32_t* cLSF, int32_t dd) {
    int32_t k, n;
    int32_t ftmp;
    uint8_t QA16 = 16;

    out[0] = silk_LSHIFT(1, QA16);
    out[1] = -cLSF[0];
    for (k = 1; k < dd; k++) {
        ftmp = cLSF[2 * k]; /* QA16*/
        out[k + 1] = silk_LSHIFT(out[k - 1], 1) - (int32_t)silk_RSHIFT_ROUND64(silk_SMULL(ftmp, out[k]), QA16);
        for (n = k; n > 1; n--) { out[n] += out[n - 2] - (int32_t)silk_RSHIFT_ROUND64(silk_SMULL(ftmp, out[n - 1]), QA16); }
        out[1] -= ftmp;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* compute whitening filter coefficients from normalized line spectral frequencies(monic whitening filter coefficients in Q12, normalized line spectral frequencies in Q15, filter order) */
void silk_NLSF2A(int16_t* a_Q12, const int16_t* NLSF, const int32_t d) {
    /* This ordering was found to maximize quality. It improves numerical accuracy of silk_NLSF2A_find_poly() compared to "standard" ordering. */
    static const unsigned char ordering16[16] = {0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1};
    static const unsigned char ordering10[10] = {0, 9, 6, 3, 4, 5, 8, 1, 2, 7};
    const unsigned char*       ordering;
    uint8_t                    QA16 = 16;
    int32_t                    k, i, dd;
    int32_t*                   cos_LSF_QA = (int32_t*)__malloc_heap_psram(sizeof(int32_t) * SILK_MAX_ORDER_LPC);
    int32_t*                   P = (int32_t*)__malloc_heap_psram(sizeof(int32_t) * (SILK_MAX_ORDER_LPC / 2 + 1));
    int32_t*                   Q = (int32_t*)__malloc_heap_psram(sizeof(int32_t) * (SILK_MAX_ORDER_LPC / 2 + 1));
    int32_t                    Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
    int32_t*                   a32_QA1 = (int32_t*)__malloc_heap_psram(sizeof(int32_t) * SILK_MAX_ORDER_LPC);

    assert(LSF_COS_TAB_SZ_FIX == 128);
    assert(d == 10 || d == 16);

    /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
    ordering = d == 16 ? ordering16 : ordering10;
    for (k = 0; k < d; k++) {
        assert(NLSF[k] >= 0);

        /* f_int on a scale 0-127 (rounded down) */
        f_int = silk_RSHIFT(NLSF[k], 15 - 7);

        /* f_frac, range: 0..255 */
        f_frac = NLSF[k] - silk_LSHIFT(f_int, 15 - 7);

        assert(f_int >= 0);
        assert(f_int < LSF_COS_TAB_SZ_FIX);

        /* Read start and end value from table */
        cos_val = silk_LSFCosTab_FIX_Q12[f_int];             /* Q12 */
        delta = silk_LSFCosTab_FIX_Q12[f_int + 1] - cos_val; /* Q12, with a range of 0..200 */

        /* Linear interpolation */
        cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND(silk_LSHIFT(cos_val, 8) + silk_MUL(delta, f_frac), 20 - QA16); /* QA16 */
    }

    dd = silk_RSHIFT(d, 1);

    /* generate even and odd polynomials using convolution */
    silk_NLSF2A_find_poly(P, &cos_LSF_QA[0], dd);
    silk_NLSF2A_find_poly(Q, &cos_LSF_QA[1], dd);

    /* convert even and odd polynomials to int32_t Q12 filter coefs */
    for (k = 0; k < dd; k++) {
        Ptmp = P[k + 1] + P[k];
        Qtmp = Q[k + 1] - Q[k];

        /* the Ptmp and Qtmp values at this stage need to fit in int32 */
        a32_QA1[k] = -Qtmp - Ptmp;
        a32_QA1[d - k - 1] = Qtmp - Ptmp;
    }

    /* Convert int32 coefficients to Q12 int16 coefs */
    silk_LPC_fit(a_Q12, a32_QA1, 12, QA16 + 1, d);

    for (i = 0; silk_LPC_inverse_pred_gain(a_Q12, d) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++) {
        /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
        /* on the unscaled coefficients, convert to Q12 and measure again                   */
        silk_bwexpander_32(a32_QA1, d, 65536 - silk_LSHIFT(2, i));
        for (k = 0; k < d; k++) { a_Q12[k] = (int16_t)silk_RSHIFT_ROUND(a32_QA1[k], QA16 + 1 - 12); /* QA16+1 -> Q12 */ }
    }
    free(cos_LSF_QA);
    free(P);
    free(Q);
    free(a32_QA1);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decode side-information parameters from payload (State, Compressor data structure, Frame number, Flag indicating LBRR data is being decoded, The type of conditional coding to use) */
void silk_decode_indices(silk_decoder_state* psDec, int32_t FrameIndex, int32_t decode_LBRR, int32_t condCoding) {
    int32_t i, k, Ix;
    int32_t decode_absolute_lagIndex, delta_lagIndex;
    int16_t ec_ix[MAX_LPC_ORDER];
    uint8_t pred_Q8[MAX_LPC_ORDER];

    /*******************************************/
    /* Decode signal type and quantizer offset */
    /*******************************************/
    if (decode_LBRR || psDec->VAD_flags[FrameIndex]) {
        Ix = ec_dec_icdf(silk_type_offset_VAD_iCDF, 8) + 2;
    } else {
        Ix = ec_dec_icdf(silk_type_offset_no_VAD_iCDF, 8);
    }
    psDec->indices.signalType = (int8_t)silk_RSHIFT(Ix, 1);
    psDec->indices.quantOffsetType = (int8_t)(Ix & 1);

    /****************/
    /* Decode gains */
    /****************/
    /* First subframe */
    if (condCoding == CODE_CONDITIONALLY) {
        /* Conditional coding */
        psDec->indices.GainsIndices[0] = (int8_t)ec_dec_icdf(silk_delta_gain_iCDF, 8);
    } else {
        /* Independent coding, in two stages: MSB bits followed by 3 LSBs */
        psDec->indices.GainsIndices[0] = (int8_t)silk_LSHIFT(ec_dec_icdf(silk_gain_iCDF[psDec->indices.signalType], 8), 3);
        psDec->indices.GainsIndices[0] += (int8_t)ec_dec_icdf(silk_uniform8_iCDF, 8);
    }

    /* Remaining subframes */
    for (i = 1; i < psDec->nb_subfr; i++) { psDec->indices.GainsIndices[i] = (int8_t)ec_dec_icdf(silk_delta_gain_iCDF, 8); }

    /**********************/
    /* Decode LSF Indices */
    /**********************/
    psDec->indices.NLSFIndices[0] = (int8_t)ec_dec_icdf(&psDec->psNLSF_CB->CB1_iCDF[(psDec->indices.signalType >> 1) * psDec->psNLSF_CB->nVectors], 8);
    silk_NLSF_unpack(ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[0]);
    assert(psDec->psNLSF_CB->order == psDec->LPC_order);
    for (i = 0; i < psDec->psNLSF_CB->order; i++) {
        Ix = ec_dec_icdf(&psDec->psNLSF_CB->ec_iCDF[ec_ix[i]], 8);
        if (Ix == 0) {
            Ix -= ec_dec_icdf(silk_NLSF_EXT_iCDF, 8);
        } else if (Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE) {
            Ix += ec_dec_icdf(silk_NLSF_EXT_iCDF, 8);
        }
        psDec->indices.NLSFIndices[i + 1] = (int8_t)(Ix - NLSF_QUANT_MAX_AMPLITUDE);
    }

    /* Decode LSF interpolation factor */
    if (psDec->nb_subfr == MAX_NB_SUBFR) {
        psDec->indices.NLSFInterpCoef_Q2 = (int8_t)ec_dec_icdf(silk_NLSF_interpolation_factor_iCDF, 8);
    } else {
        psDec->indices.NLSFInterpCoef_Q2 = 4;
    }

    if (psDec->indices.signalType == TYPE_VOICED) {
        /*********************/
        /* Decode pitch lags */
        /*********************/
        /* Get lag index */
        decode_absolute_lagIndex = 1;
        if (condCoding == CODE_CONDITIONALLY && psDec->ec_prevSignalType == TYPE_VOICED) {
            /* Decode Delta index */
            delta_lagIndex = (int16_t)ec_dec_icdf(silk_pitch_delta_iCDF, 8);
            if (delta_lagIndex > 0) {
                delta_lagIndex = delta_lagIndex - 9;
                psDec->indices.lagIndex = (int16_t)(psDec->ec_prevLagIndex + delta_lagIndex);
                decode_absolute_lagIndex = 0;
            }
        }
        if (decode_absolute_lagIndex) {
            /* Absolute decoding */
            psDec->indices.lagIndex = (int16_t)ec_dec_icdf(silk_pitch_lag_iCDF, 8) * silk_RSHIFT(psDec->fs_kHz, 1);
            psDec->indices.lagIndex += (int16_t)ec_dec_icdf(psDec->pitch_lag_low_bits_iCDF, 8);
        }
        psDec->ec_prevLagIndex = psDec->indices.lagIndex;

        /* Get countour index */
        psDec->indices.contourIndex = (int8_t)ec_dec_icdf(psDec->pitch_contour_iCDF, 8);

        /********************/
        /* Decode LTP gains */
        /********************/
        /* Decode PERIndex value */
        psDec->indices.PERIndex = (int8_t)ec_dec_icdf(silk_LTP_per_index_iCDF, 8);

        for (k = 0; k < psDec->nb_subfr; k++) { psDec->indices.LTPIndex[k] = (int8_t)ec_dec_icdf(silk_LTP_gain_iCDF_ptrs[psDec->indices.PERIndex], 8); }

        /**********************/
        /* Decode LTP scaling */
        /**********************/
        if (condCoding == CODE_INDEPENDENTLY) {
            psDec->indices.LTP_scaleIndex = (int8_t)ec_dec_icdf(silk_LTPscale_iCDF, 8);
        } else {
            psDec->indices.LTP_scaleIndex = 0;
        }
    }
    psDec->ec_prevSignalType = psDec->indices.signalType;

    /***************/
    /* Decode seed */
    /***************/
    psDec->indices.Seed = (int8_t)ec_dec_icdf(silk_uniform4_iCDF, 8);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void silk_decode_parameters(silk_decoder_state*   psDec,     /* I/O  State                                       */
                            silk_decoder_control* psDecCtrl, /* I/O  Decoder control                             */
                            int32_t               condCoding /* I    The type of conditional coding to use       */
) {
    int32_t       i, k, Ix;
    int16_t       pNLSF_Q15[MAX_LPC_ORDER], pNLSF0_Q15[MAX_LPC_ORDER];
    const int8_t* cbk_ptr_Q7;

    /* Dequant Gains */
    silk_gains_dequant(psDecCtrl->Gains_Q16, psDec->indices.GainsIndices, &psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, psDec->nb_subfr);

    /****************/
    /* Decode NLSFs */
    /****************/
    silk_NLSF_decode(pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB);

    /* Convert NLSF parameters to AR prediction filter coefficients */
    silk_NLSF2A(psDecCtrl->PredCoef_Q12[1], pNLSF_Q15, psDec->LPC_order);

    /* If just reset, e.g., because internal Fs changed, do not allow interpolation */
    /* improves the case of packet loss in the first frame after a switch           */
    if (psDec->first_frame_after_reset == 1) { psDec->indices.NLSFInterpCoef_Q2 = 4; }

    if (psDec->indices.NLSFInterpCoef_Q2 < 4) {
        /* Calculation of the interpolated NLSF0 vector from the interpolation factor, the previous NLSF1, and the current NLSF1 */
        for (i = 0; i < psDec->LPC_order; i++) { pNLSF0_Q15[i] = psDec->prevNLSF_Q15[i] + silk_RSHIFT(silk_MUL(psDec->indices.NLSFInterpCoef_Q2, pNLSF_Q15[i] - psDec->prevNLSF_Q15[i]), 2); }

        /* Convert NLSF parameters to AR prediction filter coefficients */
        silk_NLSF2A(psDecCtrl->PredCoef_Q12[0], pNLSF0_Q15, psDec->LPC_order);
    } else {
        /* Copy LPC coefficients for first half from second half */
        memcpy(psDecCtrl->PredCoef_Q12[0], psDecCtrl->PredCoef_Q12[1], psDec->LPC_order * sizeof(int16_t));
    }
    memcpy(psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof(int16_t));

    /* After a packet loss do BWE of LPC coefs */
    if (psDec->lossCnt) {
        silk_bwexpander(psDecCtrl->PredCoef_Q12[0], psDec->LPC_order, BWE_AFTER_LOSS_Q16);
        silk_bwexpander(psDecCtrl->PredCoef_Q12[1], psDec->LPC_order, BWE_AFTER_LOSS_Q16);
    }

    if (psDec->indices.signalType == TYPE_VOICED) {
        /*********************/
        /* Decode pitch lags */
        /*********************/

        /* Decode pitch values */
        silk_decode_pitch(psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr);

        /* Decode Codebook Index */
        cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[psDec->indices.PERIndex]; /* set pointer to start of codebook */

        for (k = 0; k < psDec->nb_subfr; k++) {
            Ix = psDec->indices.LTPIndex[k];
            for (i = 0; i < LTP_ORDER; i++) { psDecCtrl->LTPCoef_Q14[k * LTP_ORDER + i] = silk_LSHIFT(cbk_ptr_Q7[Ix * LTP_ORDER + i], 7); }
        }

        /**********************/
        /* Decode LTP scaling */
        /**********************/
        Ix = psDec->indices.LTP_scaleIndex;
        psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[Ix];
    } else {
        memset(psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof(int32_t));
        memset(psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof(int16_t));
        psDec->indices.PERIndex = 0;
        psDecCtrl->LTP_scale_Q14 = 0;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decode quantization indices of excitation (Compressor data structure, Excitation signal, Sigtype, quantOffsetType, Frame length)*/
void silk_decode_pulses(int16_t pulses[], const int32_t signalType, const int32_t quantOffsetType, const int32_t frame_length) {
    int32_t        i, j, k, iter, abs_q, nLS, RateLevelIndex;
    int32_t        sum_pulses[MAX_NB_SHELL_BLOCKS], nLshifts[MAX_NB_SHELL_BLOCKS];
    int16_t*       pulses_ptr;
    const uint8_t* cdf_ptr;

    /*********************/
    /* Decode rate level */
    /*********************/
    RateLevelIndex = ec_dec_icdf(silk_rate_levels_iCDF[signalType >> 1], 8);

    /* Calculate number of shell blocks */
    assert(1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH);
    iter = silk_RSHIFT(frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH);
    if (iter * SHELL_CODEC_FRAME_LENGTH < frame_length) {
        assert(frame_length == 12 * 10); /* Make sure only happens for 10 ms @ 12 kHz */
        iter++;
    }

    /***************************************************/
    /* Sum-Weighted-Pulses Decoding                    */
    /***************************************************/
    cdf_ptr = silk_pulses_per_block_iCDF[RateLevelIndex];
    for (i = 0; i < iter; i++) {
        nLshifts[i] = 0;
        sum_pulses[i] = ec_dec_icdf(cdf_ptr, 8);

        /* LSB indication */
        while (sum_pulses[i] == SILK_MAX_PULSES + 1) {
            nLshifts[i]++;
            /* When we've already got 10 LSBs, we shift the table to not allow (SILK_MAX_PULSES + 1) */
            sum_pulses[i] = ec_dec_icdf(silk_pulses_per_block_iCDF[N_RATE_LEVELS - 1] + (nLshifts[i] == 10), 8);
        }
    }

    /***************************************************/
    /* Shell decoding                                  */
    /***************************************************/
    for (i = 0; i < iter; i++) {
        if (sum_pulses[i] > 0) {
            silk_shell_decoder(&pulses[silk_SMULBB(i, SHELL_CODEC_FRAME_LENGTH)], sum_pulses[i]);
        } else {
            memset(&pulses[silk_SMULBB(i, SHELL_CODEC_FRAME_LENGTH)], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(pulses[0]));
        }
    }

    /***************************************************/
    /* LSB Decoding                                    */
    /***************************************************/
    for (i = 0; i < iter; i++) {
        if (nLshifts[i] > 0) {
            nLS = nLshifts[i];
            pulses_ptr = &pulses[silk_SMULBB(i, SHELL_CODEC_FRAME_LENGTH)];
            for (k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++) {
                abs_q = pulses_ptr[k];
                for (j = 0; j < nLS; j++) {
                    abs_q = silk_LSHIFT(abs_q, 1);
                    abs_q += ec_dec_icdf(silk_lsb_iCDF, 8);
                }
                pulses_ptr[k] = abs_q;
            }
            /* Mark the number of pulses non-zero for sign decoding. */
            sum_pulses[i] |= nLS << 5;
        }
    }

    /****************************************/
    /* Decode and add signs to pulse signal */
    /****************************************/
    silk_decode_signs(pulses, frame_length, signalType, quantOffsetType, sum_pulses);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Set decoder sampling rate (Decoder state pointer , Sampling frequency (kHz) , API Sampling frequency (Hz))*/
int32_t silk_decoder_set_fs(silk_decoder_state* psDec, int32_t fs_kHz, int32_t fs_API_Hz) {
    int32_t frame_length, ret = 0;

    assert(fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16);
    assert(psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR / 2);

    /* New (sub)frame length */
    psDec->subfr_length = silk_SMULBB(SUB_FRAME_LENGTH_MS, fs_kHz);
    frame_length = silk_SMULBB(psDec->nb_subfr, psDec->subfr_length);

    /* Initialize resampler when switching internal or external sampling frequency */
    if (psDec->fs_kHz != fs_kHz || psDec->fs_API_hz != fs_API_Hz) {
        /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */
        ret += silk_resampler_init(&psDec->resampler_state, silk_SMULBB(fs_kHz, 1000), fs_API_Hz, 0);

        psDec->fs_API_hz = fs_API_Hz;
    }

    if (psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length) {
        if (fs_kHz == 8) {
            if (psDec->nb_subfr == MAX_NB_SUBFR) {
                psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
            } else {
                psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
            }
        } else {
            if (psDec->nb_subfr == MAX_NB_SUBFR) {
                psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF;
            } else {
                psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
            }
        }
        if (psDec->fs_kHz != fs_kHz) {
            psDec->ltp_mem_length = silk_SMULBB(LTP_MEM_LENGTH_MS, fs_kHz);
            if (fs_kHz == 8 || fs_kHz == 12) {
                psDec->LPC_order = MIN_LPC_ORDER;
                psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB;
            } else {
                psDec->LPC_order = MAX_LPC_ORDER;
                psDec->psNLSF_CB = &silk_NLSF_CB_WB;
            }
            if (fs_kHz == 16) {
                psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
            } else if (fs_kHz == 12) {
                psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
            } else if (fs_kHz == 8) {
                psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
            } else {
                /* unsupported sampling rate */
                assert(0);
            }
            psDec->first_frame_after_reset = 1;
            psDec->lagPrev = 100;
            psDec->LastGainIndex = 10;
            psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY;
            memset(psDec->outBuf, 0, sizeof(psDec->outBuf));
            memset(psDec->sLPC_Q14_buf, 0, sizeof(psDec->sLPC_Q14_buf));
        }

        psDec->fs_kHz = fs_kHz;
        psDec->frame_length = frame_length;
    }

    /* Check that settings are valid */
    assert(psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH);

    return ret;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Encode quantization indices of excitation */
static inline int32_t combine_and_check(                            /* return ok                           */
                                        int32_t*       pulses_comb, /* O                                   */
                                        const int32_t* pulses_in,   /* I                                   */
                                        int32_t        max_pulses,  /* I    max value for sum of pulses    */
                                        int32_t        len          /* I    number of output values        */
) {
    int32_t k, sum;

    for (k = 0; k < len; k++) {
        sum = pulses_in[2 * k] + pulses_in[2 * k + 1];
        if (sum > max_pulses) { return 1; }
        pulses_comb[k] = sum;
    }

    return 0;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_quant_LTP_gains(int16_t       B_Q14[MAX_NB_SUBFR * LTP_ORDER],              /* O    Quantized LTP gains             */
                          int8_t        cbk_index[MAX_NB_SUBFR],                      /* O    Codebook Index                  */
                          int8_t*       periodicity_index,                            /* O    Periodicity Index               */
                          int32_t*      sum_log_gain_Q7,                              /* I/O  Cumulative max prediction gain  */
                          int32_t*      pred_gain_dB_Q7,                              /* O    LTP prediction gain             */
                          const int32_t XX_Q17[MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER], /* I    Correlation matrix in Q18       */
                          const int32_t xX_Q17[MAX_NB_SUBFR * LTP_ORDER],             /* I    Correlation vector in Q18       */
                          const int32_t subfr_len,                                    /* I    Number of samples per subframe  */
                          const int32_t nb_subfr                                      /* I    Number of subframes             */
) {
    int32_t        j, k, cbk_size;
    int8_t         temp_idx[MAX_NB_SUBFR];
    const uint8_t* cl_ptr_Q5;
    const int8_t*  cbk_ptr_Q7;
    const uint8_t* cbk_gain_ptr_Q7;
    const int32_t *XX_Q17_ptr, *xX_Q17_ptr;
    int32_t        res_nrg_Q15_subfr, res_nrg_Q15, rate_dist_Q7_subfr, rate_dist_Q7, min_rate_dist_Q7;
    int32_t        sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7;
    int32_t        gain_Q7;

    /***************************************************/
    /* iterate over different codebooks with different */
    /* rates/distortions, and choose best */
    /***************************************************/
    min_rate_dist_Q7 = silk_int32_MAX;
    best_sum_log_gain_Q7 = 0;
    for (k = 0; k < 3; k++) {
        /* Safety margin for pitch gain control, to take into account factors
           such as state rescaling/rewhitening. */
        int32_t gain_safety = SILK_FIX_CONST(0.4, 7);

        cl_ptr_Q5 = silk_LTP_gain_BITS_Q5_ptrs[k];
        cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[k];
        cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[k];
        cbk_size = silk_LTP_vq_sizes[k];

        /* Set up pointers to first subframe */
        XX_Q17_ptr = XX_Q17;
        xX_Q17_ptr = xX_Q17;

        res_nrg_Q15 = 0;
        rate_dist_Q7 = 0;
        sum_log_gain_tmp_Q7 = *sum_log_gain_Q7;
        for (j = 0; j < nb_subfr; j++) {
            max_gain_Q7 = silk_log2lin((SILK_FIX_CONST(MAX_SUM_LOG_GAIN_DB / 6.0L, 7) - sum_log_gain_tmp_Q7) + SILK_FIX_CONST(7, 7)) - gain_safety;
            silk_VQ_WMat_EC(&temp_idx[j],        /* O    index of best codebook vector                           */
                            &res_nrg_Q15_subfr,  /* O    residual energy                                         */
                            &rate_dist_Q7_subfr, /* O    best weighted quantization error + mu * rate            */
                            &gain_Q7,            /* O    sum of absolute LTP coefficients                        */
                            XX_Q17_ptr,          /* I    correlation matrix                                      */
                            xX_Q17_ptr,          /* I    correlation vector                                      */
                            cbk_ptr_Q7,          /* I    codebook                                                */
                            cbk_gain_ptr_Q7,     /* I    codebook effective gains                                */
                            cl_ptr_Q5,           /* I    code length for each codebook vector                    */
                            subfr_len,           /* I    number of samples per subframe                          */
                            max_gain_Q7,         /* I    maximum sum of absolute LTP coefficients                */
                            cbk_size             /* I    number of vectors in codebook                           */
            );

            res_nrg_Q15 = silk_ADD_POS_SAT32(res_nrg_Q15, res_nrg_Q15_subfr);
            rate_dist_Q7 = silk_ADD_POS_SAT32(rate_dist_Q7, rate_dist_Q7_subfr);
            sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7 + silk_lin2log(gain_safety + gain_Q7) - SILK_FIX_CONST(7, 7));

            XX_Q17_ptr += LTP_ORDER * LTP_ORDER;
            xX_Q17_ptr += LTP_ORDER;
        }

        if (rate_dist_Q7 <= min_rate_dist_Q7) {
            min_rate_dist_Q7 = rate_dist_Q7;
            *periodicity_index = (int8_t)k;
            memcpy(cbk_index, temp_idx, nb_subfr * sizeof(int8_t));
            best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7;
        }
    }

    cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[*periodicity_index];
    for (j = 0; j < nb_subfr; j++) {
        for (k = 0; k < LTP_ORDER; k++) { B_Q14[j * LTP_ORDER + k] = silk_LSHIFT(cbk_ptr_Q7[cbk_index[j] * LTP_ORDER + k], 7); }
    }

    if (nb_subfr == 2) {
        res_nrg_Q15 = silk_RSHIFT32(res_nrg_Q15, 1);
    } else {
        res_nrg_Q15 = silk_RSHIFT32(res_nrg_Q15, 2);
    }

    *sum_log_gain_Q7 = best_sum_log_gain_Q7;
    *pred_gain_dB_Q7 = (int32_t)silk_SMULBB(-3, silk_lin2log(res_nrg_Q15) - (15 << 7));
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static inline void decode_split(int16_t*       p_child1,   /* O    pulse amplitude of first child subframe     */
                                int16_t*       p_child2,   /* O    pulse amplitude of second child subframe    */
                                const int32_t  p,          /* I    pulse amplitude of current subframe         */
                                const uint8_t* shell_table /* I    table of shell cdfs                         */
) {
    if (p > 0) {
        p_child1[0] = ec_dec_icdf(&shell_table[silk_shell_code_table_offsets[p]], 8);
        p_child2[0] = p - p_child1[0];
    } else {
        p_child1[0] = 0;
        p_child2[0] = 0;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Shell decoder, operates on one shell code frame of 16 pulses */
void silk_shell_decoder(int16_t*      pulses0, /* O    data: nonnegative pulse amplitudes          */
                        const int32_t pulses4  /* I    number of pulses per pulse-subframe         */
) {
    int16_t pulses3[2], pulses2[4], pulses1[8];

    /* this function operates on one shell code frame of 16 pulses */
    assert(SHELL_CODEC_FRAME_LENGTH == 16);
    decode_split(&pulses3[0], &pulses3[1], pulses4, silk_shell_code_table3);
    decode_split(&pulses2[0], &pulses2[1], pulses3[0], silk_shell_code_table2);
    decode_split(&pulses1[0], &pulses1[1], pulses2[0], silk_shell_code_table1);
    decode_split(&pulses0[0], &pulses0[1], pulses1[0], silk_shell_code_table0);
    decode_split(&pulses0[2], &pulses0[3], pulses1[1], silk_shell_code_table0);
    decode_split(&pulses1[2], &pulses1[3], pulses2[1], silk_shell_code_table1);
    decode_split(&pulses0[4], &pulses0[5], pulses1[2], silk_shell_code_table0);
    decode_split(&pulses0[6], &pulses0[7], pulses1[3], silk_shell_code_table0);
    decode_split(&pulses2[2], &pulses2[3], pulses3[1], silk_shell_code_table2);
    decode_split(&pulses1[4], &pulses1[5], pulses2[2], silk_shell_code_table1);
    decode_split(&pulses0[8], &pulses0[9], pulses1[4], silk_shell_code_table0);
    decode_split(&pulses0[10], &pulses0[11], pulses1[5], silk_shell_code_table0);
    decode_split(&pulses1[6], &pulses1[7], pulses2[3], silk_shell_code_table1);
    decode_split(&pulses0[12], &pulses0[13], pulses1[6], silk_shell_code_table0);
    decode_split(&pulses0[14], &pulses0[15], pulses1[7], silk_shell_code_table0);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Quantize mid/side predictors */
void silk_stereo_quant_pred(int32_t pred_Q13[], /* I/O  Predictors (out: quantized)                 */
                            int8_t  ix[2][3]    /* O    Quantization indices                        */
) {
    int32_t i, j, n;
    int32_t low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0;

    /* Quantize */
    for (n = 0; n < 2; n++) {
        /* Brute-force search over quantization levels */
        err_min_Q13 = silk_int32_MAX;
        for (i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++) {
            low_Q13 = silk_stereo_pred_quant_Q13[i];
            step_Q13 = silk_SMULWB(silk_stereo_pred_quant_Q13[i + 1] - low_Q13, SILK_FIX_CONST(0.5 / STEREO_QUANT_SUB_STEPS, 16));
            for (j = 0; j < STEREO_QUANT_SUB_STEPS; j++) {
                lvl_Q13 = silk_SMLABB(low_Q13, step_Q13, 2 * j + 1);
                err_Q13 = silk_abs(pred_Q13[n] - lvl_Q13);
                if (err_Q13 < err_min_Q13) {
                    err_min_Q13 = err_Q13;
                    quant_pred_Q13 = lvl_Q13;
                    ix[n][0] = i;
                    ix[n][1] = j;
                } else {
                    /* Error increasing, so we're past the optimum */
                    goto done;
                }
            }
        }
    done:
        ix[n][2] = silk_DIV32_16(ix[n][0], 3);
        ix[n][0] -= ix[n][2] * 3;
        pred_Q13[n] = quant_pred_Q13;
    }

    /* Subtract second from first predictor (helps when actually applying these) */
    pred_Q13[0] -= pred_Q13[1];
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Helper function, interpolates the filter taps */
void silk_LP_interpolate_filter_taps(int32_t B_Q28[TRANSITION_NB], int32_t A_Q28[TRANSITION_NA], const int32_t ind, const int32_t fac_Q16) {
    int32_t nb, na;

    if (ind < TRANSITION_INT_NUM - 1) {
        if (fac_Q16 > 0) {
            if (fac_Q16 < 32768) { /* fac_Q16 is in range of a 16-bit int */
                /* Piece-wise linear interpolation of B and A */
                for (nb = 0; nb < TRANSITION_NB; nb++) {
                    B_Q28[nb] = silk_SMLAWB(silk_Transition_LP_B_Q28[ind][nb], silk_Transition_LP_B_Q28[ind + 1][nb] - silk_Transition_LP_B_Q28[ind][nb], fac_Q16);
                }
                for (na = 0; na < TRANSITION_NA; na++) {
                    A_Q28[na] = silk_SMLAWB(silk_Transition_LP_A_Q28[ind][na], silk_Transition_LP_A_Q28[ind + 1][na] - silk_Transition_LP_A_Q28[ind][na], fac_Q16);
                }
            } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
                assert(fac_Q16 - (1 << 16) == silk_SAT16(fac_Q16 - (1 << 16)));
                /* Piece-wise linear interpolation of B and A */
                for (nb = 0; nb < TRANSITION_NB; nb++) {
                    B_Q28[nb] = silk_SMLAWB(silk_Transition_LP_B_Q28[ind + 1][nb], silk_Transition_LP_B_Q28[ind + 1][nb] - silk_Transition_LP_B_Q28[ind][nb], fac_Q16 - ((int32_t)1 << 16));
                }
                for (na = 0; na < TRANSITION_NA; na++) {
                    A_Q28[na] = silk_SMLAWB(silk_Transition_LP_A_Q28[ind + 1][na], silk_Transition_LP_A_Q28[ind + 1][na] - silk_Transition_LP_A_Q28[ind][na], fac_Q16 - ((int32_t)1 << 16));
                }
            }
        } else {
            memcpy(B_Q28, silk_Transition_LP_B_Q28[ind], TRANSITION_NB * sizeof(int32_t));
            memcpy(A_Q28, silk_Transition_LP_A_Q28[ind], TRANSITION_NA * sizeof(int32_t));
        }
    } else {
        memcpy(B_Q28, silk_Transition_LP_B_Q28[TRANSITION_INT_NUM - 1], TRANSITION_NB * sizeof(int32_t));
        memcpy(A_Q28, silk_Transition_LP_A_Q28[TRANSITION_INT_NUM - 1], TRANSITION_NA * sizeof(int32_t));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Low-pass filter with variable cutoff frequency based on  */
/* piece-wise linear interpolation between elliptic filters */
/* Start by setting psEncC->mode <> 0;                      */
/* Deactivate by setting psEncC->mode = 0;                  */
void silk_LP_variable_cutoff(silk_LP_state* psLP,        /* I/O  LP filter state                             */
                             int16_t*       frame,       /* I/O  Low-pass filtered output signal             */
                             const int32_t  frame_length /* I    Frame length                                */
) {
    int32_t B_Q28[TRANSITION_NB], A_Q28[TRANSITION_NA], fac_Q16 = 0;
    int32_t ind = 0;

    assert(psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES);

    /* Run filter if needed */
    if (psLP->mode != 0) {
        /* Calculate index and interpolation factor for interpolation */
#if (TRANSITION_INT_STEPS == 64)
        fac_Q16 = silk_LSHIFT(TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6);
#else
        fac_Q16 = silk_DIV32_16(silk_LSHIFT(TRANSITION_FRAMES - psLP->transition_frame_no, 16), TRANSITION_FRAMES);
#endif
        ind = silk_RSHIFT(fac_Q16, 16);
        fac_Q16 -= silk_LSHIFT(ind, 16);

        assert(ind >= 0);
        assert(ind < TRANSITION_INT_NUM);

        /* Interpolate filter coefficients */
        silk_LP_interpolate_filter_taps(B_Q28, A_Q28, ind, fac_Q16);

        /* Update transition frame number for next frame */
        psLP->transition_frame_no = silk_LIMIT(psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES);

        /* ARMA low-pass filtering */
        assert(TRANSITION_NB == 3 && TRANSITION_NA == 2);
        silk_biquad_alt_stride1(frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Generates excitation for CNG LPC synthesis */
void silk_CNG_exc(int32_t  exc_Q14[],     /* O    CNG excitation signal Q10                   */
                  int32_t  exc_buf_Q14[], /* I    Random samples buffer Q10                   */
                  int32_t  length,        /* I    Length                                      */
                  int32_t* rand_seed      /* I/O  Seed to random index generator              */
) {
    int32_t seed;
    int32_t i, idx, exc_mask;

    exc_mask = CNG_BUF_MASK_MAX;
    while (exc_mask > length) { exc_mask = silk_RSHIFT(exc_mask, 1); }

    seed = *rand_seed;
    for (i = 0; i < length; i++) {
        seed = silk_RAND(seed);
        idx = (int32_t)(silk_RSHIFT(seed, 24) & exc_mask);
        assert(idx >= 0);
        assert(idx <= CNG_BUF_MASK_MAX);
        exc_Q14[i] = exc_buf_Q14[idx];
    }
    *rand_seed = seed;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_CNG_Reset(silk_decoder_state* psDec /* I/O  Decoder state                               */
) {
    int32_t i, NLSF_step_Q15, NLSF_acc_Q15;

    NLSF_step_Q15 = silk_DIV32_16(silk_int16_MAX, psDec->LPC_order + 1);
    NLSF_acc_Q15 = 0;
    for (i = 0; i < psDec->LPC_order; i++) {
        NLSF_acc_Q15 += NLSF_step_Q15;
        psDec->sCNG.CNG_smth_NLSF_Q15[i] = NLSF_acc_Q15;
    }
    psDec->sCNG.CNG_smth_Gain_Q16 = 0;
    psDec->sCNG.rand_seed = 3176576;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Updates CNG estimate, and applies the CNG when packet was lost   */
void silk_CNG(silk_decoder_state*   psDec,     /* I/O  Decoder state                               */
              silk_decoder_control* psDecCtrl, /* I/O  Decoder control                             */
              int16_t               frame[],   /* I/O  Signal                                      */
              int32_t               length     /* I    Length of residual                          */
) {
    int32_t          i, subfr;
    int32_t          LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
    int16_t          A_Q12[MAX_LPC_ORDER];
    silk_CNG_struct* psCNG = &psDec->sCNG;

    if (psDec->fs_kHz != psCNG->fs_kHz) {
        /* Reset state */
        silk_CNG_Reset(psDec);

        psCNG->fs_kHz = psDec->fs_kHz;
    }
    if (psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY) {
        /* Update CNG parameters */

        /* Smoothing of LSF's  */
        for (i = 0; i < psDec->LPC_order; i++) { psCNG->CNG_smth_NLSF_Q15[i] += silk_SMULWB((int32_t)psDec->prevNLSF_Q15[i] - (int32_t)psCNG->CNG_smth_NLSF_Q15[i], CNG_NLSF_SMTH_Q16); }
        /* Find the subframe with the highest gain */
        max_Gain_Q16 = 0;
        subfr = 0;
        for (i = 0; i < psDec->nb_subfr; i++) {
            if (psDecCtrl->Gains_Q16[i] > max_Gain_Q16) {
                max_Gain_Q16 = psDecCtrl->Gains_Q16[i];
                subfr = i;
            }
        }
        /* Update CNG excitation buffer with excitation from this subframe */
        memmove(&psCNG->CNG_exc_buf_Q14[psDec->subfr_length], psCNG->CNG_exc_buf_Q14, (psDec->nb_subfr - 1) * psDec->subfr_length * sizeof(int32_t));
        memcpy(psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[subfr * psDec->subfr_length], psDec->subfr_length * sizeof(int32_t));

        /* Smooth gains */
        for (i = 0; i < psDec->nb_subfr; i++) { psCNG->CNG_smth_Gain_Q16 += silk_SMULWB(psDecCtrl->Gains_Q16[i] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16); }
    }
    /* Add CNG when packet is lost or during DTX */
    if (psDec->lossCnt) {
        int32_t* CNG_sig_Q14 = (int32_t*)__malloc_heap_psram(length + MAX_LPC_ORDER * sizeof(int32_t));
        // ALLOC(CNG_sig_Q14, length + MAX_LPC_ORDER, int32_t);

        /* Generate CNG excitation */
        gain_Q16 = silk_SMULWW(psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1]);
        if (gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23)) {
            gain_Q16 = silk_SMULTT(gain_Q16, gain_Q16);
            gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT(psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16), gain_Q16, 5);
            gain_Q16 = silk_LSHIFT32(silk_SQRT_APPROX(gain_Q16), 16);
        } else {
            gain_Q16 = silk_SMULWW(gain_Q16, gain_Q16);
            gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW(psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16), gain_Q16, 5);
            gain_Q16 = silk_LSHIFT32(silk_SQRT_APPROX(gain_Q16), 8);
        }
        gain_Q10 = silk_RSHIFT(gain_Q16, 6);

        silk_CNG_exc(CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed);

        /* Convert CNG NLSF to filter representation */
        silk_NLSF2A(A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order);

        /* Generate CNG signal, by synthesis filtering */
        memcpy(CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof(int32_t));
        assert(psDec->LPC_order == 10 || psDec->LPC_order == 16);
        for (i = 0; i < length; i++) {
            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
            LPC_pred_Q10 = silk_RSHIFT(psDec->LPC_order, 1);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 1], A_Q12[0]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 2], A_Q12[1]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 3], A_Q12[2]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 4], A_Q12[3]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 5], A_Q12[4]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 6], A_Q12[5]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 7], A_Q12[6]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 8], A_Q12[7]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 9], A_Q12[8]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 10], A_Q12[9]);
            if (psDec->LPC_order == 16) {
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 11], A_Q12[10]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 12], A_Q12[11]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 13], A_Q12[12]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 14], A_Q12[13]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 15], A_Q12[14]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, CNG_sig_Q14[MAX_LPC_ORDER + i - 16], A_Q12[15]);
            }

            /* Update states */
            CNG_sig_Q14[MAX_LPC_ORDER + i] = silk_ADD_SAT32(CNG_sig_Q14[MAX_LPC_ORDER + i], silk_LSHIFT_SAT32(LPC_pred_Q10, 4));

            /* Scale with Gain and add to input signal */
            frame[i] = (int16_t)silk_ADD_SAT16(frame[i], silk_SAT16(silk_RSHIFT_ROUND(silk_SMULWW(CNG_sig_Q14[MAX_LPC_ORDER + i], gain_Q10), 8)));
        }
        memcpy(psCNG->CNG_synth_state, &CNG_sig_Q14[length], MAX_LPC_ORDER * sizeof(int32_t));
        free(CNG_sig_Q14);
    } else {
        memset(psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof(int32_t));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Decodes signs of excitation */
void silk_decode_signs(int16_t       pulses[],                       /* I/O  pulse signal                                */
                       int32_t       length,                         /* I    length of input                             */
                       const int32_t signalType,                     /* I    Signal type                                 */
                       const int32_t quantOffsetType,                /* I    Quantization offset type                    */
                       const int32_t sum_pulses[MAX_NB_SHELL_BLOCKS] /* I    Sum of absolute pulses per block */
) {
    int32_t        i, j, p;
    uint8_t        icdf[2];
    int16_t*       q_ptr;
    const uint8_t* icdf_ptr;

    icdf[1] = 0;
    q_ptr = pulses;
    i = silk_SMULBB(7, silk_ADD_LSHIFT(quantOffsetType, signalType, 1));
    icdf_ptr = &silk_sign_iCDF[i];
    length = silk_RSHIFT(length + SHELL_CODEC_FRAME_LENGTH / 2, LOG2_SHELL_CODEC_FRAME_LENGTH);
    for (i = 0; i < length; i++) {
        p = sum_pulses[i];
        if (p > 0) {
            icdf[0] = icdf_ptr[silk_min(p & 0x1F, 6)];
            for (j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++) {
                if (q_ptr[j] > 0) {
                    /* attach sign */
                    /* implementation with shift, subtraction, multiplication */
                    q_ptr[j] *= silk_dec_map(ec_dec_icdf(icdf, 8));
                }
            }
        }
        q_ptr += SHELL_CODEC_FRAME_LENGTH;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_setRawParams(uint8_t channels, uint8_t API_channels, uint8_t payloadSize_ms, uint32_t internalSampleRate, uint32_t API_samleRate) {
    s_channelsInternal = channels;
    s_API_channels = API_channels;
    s_payloadSize_ms = payloadSize_ms;
    s_silk_internalSampleRate = internalSampleRate;
    s_API_sampleRate = API_samleRate;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint32_t silk_getPrevPitchLag() {
    return s_prevPitchLag;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decode a frame */
int32_t silk_Decode(int32_t  lostFlag,      /* I    0: no loss, 1 loss, 2 decode fec                */
                    int32_t  newPacketFlag, /* I    Indicates first decoder call for this packet    */
                    int16_t* samplesOut,    /* O    Decoded output speech vector                    */
                    int32_t* nSamplesOut    /* O    Number of samples decoded                       */
) {

    int32_t  i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
    int32_t  nSamplesOutDec, LBRR_symbol;
    int16_t* samplesOut1_tmp[2];
    int16_t* samplesOut1_tmp_storage1 = NULL;
    int16_t* samplesOut1_tmp_storage2 = NULL;
    int16_t* samplesOut2_tmp = NULL;
    int32_t       MS_pred_Q13[2] = {0};
    int16_t*      resample_out_ptr;
    silk_decoder* psDec = (silk_decoder*)&s_decState;
    int32_t       has_side;
    int32_t       stereo_to_mono;
    int           delay_stack_alloc;

    assert(s_channelsInternal == 1 || s_channelsInternal == 2);

    /**********************************/
    /* Test if first frame in payload */
    /**********************************/
    if (newPacketFlag) {
        for (n = 0; n < s_channelsInternal; n++) { s_channel_state[n].nFramesDecoded = 0; /* Used to count frames in packet */ }
    }

    /* If Mono -> Stereo transition in bitstream: init state of second channel */
    if (s_channelsInternal > psDec->nChannelsInternal) { ret += silk_init_decoder(&s_channel_state[1]); }

    stereo_to_mono = s_channelsInternal == 1 && psDec->nChannelsInternal == 2 && (s_silk_internalSampleRate == 1000 * s_channel_state[0].fs_kHz);

    if (s_channel_state[0].nFramesDecoded == 0) {
        for (n = 0; n < s_channelsInternal; n++) {
            int32_t fs_kHz_dec;
            if (s_payloadSize_ms == 0) {
                /* Assuming packet loss, use 10 ms */
                s_channel_state[n].nFramesPerPacket = 1;
                s_channel_state[n].nb_subfr = 2;
            } else if (s_payloadSize_ms == 10) {
                s_channel_state[n].nFramesPerPacket = 1;
                s_channel_state[n].nb_subfr = 2;
            } else if (s_payloadSize_ms == 20) {
                s_channel_state[n].nFramesPerPacket = 1;
                s_channel_state[n].nb_subfr = 4;
            } else if (s_payloadSize_ms == 40) {
                s_channel_state[n].nFramesPerPacket = 2;
                s_channel_state[n].nb_subfr = 4;
            } else if (s_payloadSize_ms == 60) {
                s_channel_state[n].nFramesPerPacket = 3;
                s_channel_state[n].nb_subfr = 4;
            } else {
                return SILK_DEC_INVALID_FRAME_SIZE;
            }
            fs_kHz_dec = (s_silk_internalSampleRate >> 10) + 1;
            if (fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16) { return SILK_DEC_INVALID_SAMPLING_FREQUENCY; }
            ret += silk_decoder_set_fs(&s_channel_state[n], fs_kHz_dec, s_API_sampleRate);
        }
    }

    if (s_API_channels == 2 && s_channelsInternal == 2 && (psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1)) {
        memset(psDec->sStereo.pred_prev_Q13, 0, sizeof(psDec->sStereo.pred_prev_Q13));
        memset(psDec->sStereo.sSide, 0, sizeof(psDec->sStereo.sSide));
        memcpy(&s_channel_state[1].resampler_state, &s_channel_state[0].resampler_state, sizeof(silk_resampler_state_struct));
    }
    psDec->nChannelsAPI = s_API_channels;
    psDec->nChannelsInternal = s_channelsInternal;

    if (s_API_sampleRate > (int32_t)MAX_API_FS_KHZ * 1000 || s_API_sampleRate < 8000) {
        ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY;

        return (ret);
    }

    if (lostFlag != FLAG_PACKET_LOST && s_channel_state[0].nFramesDecoded == 0) {
        /* First decoder call for this payload */
        /* Decode VAD flags and LBRR flag */
        for (n = 0; n < s_channelsInternal; n++) {
            for (i = 0; i < s_channel_state[n].nFramesPerPacket; i++) { s_channel_state[n].VAD_flags[i] = ec_dec_bit_logp(1); }
            s_channel_state[n].LBRR_flag = ec_dec_bit_logp(1);
        }
        /* Decode LBRR flags */
        for (n = 0; n < s_channelsInternal; n++) {
            memset(s_channel_state[n].LBRR_flags, 0, sizeof(s_channel_state[n].LBRR_flags));
            if (s_channel_state[n].LBRR_flag) {
                if (s_channel_state[n].nFramesPerPacket == 1) {
                    s_channel_state[n].LBRR_flags[0] = 1;
                } else {
                    LBRR_symbol = ec_dec_icdf(silk_LBRR_flags_iCDF_ptr[s_channel_state[n].nFramesPerPacket - 2], 8) + 1;
                    for (i = 0; i < s_channel_state[n].nFramesPerPacket; i++) { s_channel_state[n].LBRR_flags[i] = silk_RSHIFT(LBRR_symbol, i) & 1; }
                }
            }
        }

        if (lostFlag == FLAG_DECODE_NORMAL) {
            /* Regular decoding: skip all LBRR data */
            for (i = 0; i < s_channel_state[0].nFramesPerPacket; i++) {
                for (n = 0; n < s_channelsInternal; n++) {
                    if (s_channel_state[n].LBRR_flags[i]) {
                        int16_t pulses[MAX_FRAME_LENGTH];
                        int32_t condCoding;

                        if (s_channelsInternal == 2 && n == 0) {
                            silk_stereo_decode_pred(MS_pred_Q13);
                            if (s_channel_state[1].LBRR_flags[i] == 0) { silk_stereo_decode_mid_only(&decode_only_middle); }
                        }
                        /* Use conditional coding if previous frame available */
                        if (i > 0 && s_channel_state[n].LBRR_flags[i - 1]) {
                            condCoding = CODE_CONDITIONALLY;
                        } else {
                            condCoding = CODE_INDEPENDENTLY;
                        }
                        silk_decode_indices(&s_channel_state[n], i, 1, condCoding);
                        silk_decode_pulses(pulses, s_channel_state[n].indices.signalType, s_channel_state[n].indices.quantOffsetType, s_channel_state[n].frame_length);
                    }
                }
            }
        }
    }

    /* Get MS predictor index */
    if (s_channelsInternal == 2) {
        if (lostFlag == FLAG_DECODE_NORMAL || (lostFlag == FLAG_DECODE_LBRR && s_channel_state[0].LBRR_flags[s_channel_state[0].nFramesDecoded] == 1)) {
            silk_stereo_decode_pred(MS_pred_Q13);
            /* For LBRR data, decode mid-only flag only if side-channel's LBRR flag is false */
            if ((lostFlag == FLAG_DECODE_NORMAL && s_channel_state[1].VAD_flags[s_channel_state[0].nFramesDecoded] == 0) ||
                (lostFlag == FLAG_DECODE_LBRR && s_channel_state[1].LBRR_flags[s_channel_state[0].nFramesDecoded] == 0)) {
                silk_stereo_decode_mid_only(&decode_only_middle);
            } else {
                decode_only_middle = 0;
            }
        } else {
            for (n = 0; n < 2; n++) { MS_pred_Q13[n] = psDec->sStereo.pred_prev_Q13[n]; }
        }
    }

    /* Reset side channel decoder prediction memory for first frame with side coding */
    if (s_channelsInternal == 2 && decode_only_middle == 0 && psDec->prev_decode_only_middle == 1) {
        memset(s_channel_state[1].outBuf, 0, sizeof(s_channel_state[1].outBuf));
        memset(s_channel_state[1].sLPC_Q14_buf, 0, sizeof(s_channel_state[1].sLPC_Q14_buf));
        s_channel_state[1].lagPrev = 100;
        s_channel_state[1].LastGainIndex = 10;
        s_channel_state[1].prevSignalType = TYPE_NO_VOICE_ACTIVITY;
        s_channel_state[1].first_frame_after_reset = 1;
    }

    /* Check if the temp buffer fits into the output PCM buffer. If it fits, we can delay allocating the temp buffer until after the SILK peak stack
       usage. We need to use a < and not a <= because of the two extra samples. */
    delay_stack_alloc = s_silk_internalSampleRate * s_channelsInternal < s_API_sampleRate * s_API_channels;
//    ALLOC(samplesOut1_tmp_storage1, delay_stack_alloc ? ALLOC_NONE : s_channelsInternal * (s_channel_state[0].frame_length + 2), int16_t);
    int size = delay_stack_alloc ? ALLOC_NONE : s_channelsInternal * (s_channel_state[0].frame_length + 2);
    samplesOut1_tmp_storage1 = (int16_t*) __malloc_heap_psram(size * sizeof(int16_t));

    if (delay_stack_alloc) {
        samplesOut1_tmp[0] = samplesOut;
        samplesOut1_tmp[1] = samplesOut + s_channel_state[0].frame_length + 2;
    } else {
        samplesOut1_tmp[0] = samplesOut1_tmp_storage1;
        samplesOut1_tmp[1] = samplesOut1_tmp_storage1 + s_channel_state[0].frame_length + 2;
    }

    if (lostFlag == FLAG_DECODE_NORMAL) {
        has_side = !decode_only_middle;
    } else {
        has_side = !psDec->prev_decode_only_middle || (s_channelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && s_channel_state[1].LBRR_flags[s_channel_state[1].nFramesDecoded] == 1);
    }
    /* Call decoder for one frame */
    for (n = 0; n < s_channelsInternal; n++) {
        if (n == 0 || has_side) {
            int32_t FrameIndex;
            int32_t condCoding;

            FrameIndex = s_channel_state[0].nFramesDecoded - n;
            /* Use independent coding if no previous frame available */
            if (FrameIndex <= 0) {
                condCoding = CODE_INDEPENDENTLY;
            } else if (lostFlag == FLAG_DECODE_LBRR) {
                condCoding = s_channel_state[n].LBRR_flags[FrameIndex - 1] ? CODE_CONDITIONALLY : CODE_INDEPENDENTLY;
            } else if (n > 0 && psDec->prev_decode_only_middle) {
                /* If we skipped a side frame in this packet, we don't
                   need LTP scaling; the LTP state is well-defined. */
                condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING;
            } else {
                condCoding = CODE_CONDITIONALLY;
            }
            ret += silk_decode_frame(&s_channel_state[n], &samplesOut1_tmp[n][2], &nSamplesOutDec, lostFlag, condCoding);
        } else {
            memset(&samplesOut1_tmp[n][2], 0, nSamplesOutDec * sizeof(int16_t));
        }
        s_channel_state[n].nFramesDecoded++;
    }

    if (s_API_channels == 2 && s_channelsInternal == 2) {
        /* Convert Mid/Side to Left/Right */
        silk_stereo_MS_to_LR(&psDec->sStereo, samplesOut1_tmp[0], samplesOut1_tmp[1], MS_pred_Q13, s_channel_state[0].fs_kHz, nSamplesOutDec);
    } else {
        /* Buffering */
        memcpy(samplesOut1_tmp[0], psDec->sStereo.sMid, 2 * sizeof(int16_t));
        memcpy(psDec->sStereo.sMid, &samplesOut1_tmp[0][nSamplesOutDec], 2 * sizeof(int16_t));
    }

    /* Number of output samples */
    *nSamplesOut = silk_DIV32(nSamplesOutDec * s_API_sampleRate, silk_SMULBB(s_channel_state[0].fs_kHz, 1000));

    /* Set up pointers to temp buffers */
    // ALLOC(samplesOut2_tmp, s_API_channels == 2 ? *nSamplesOut : ALLOC_NONE, int16_t);
    size = s_API_channels == 2 ? *nSamplesOut : ALLOC_NONE;
    samplesOut2_tmp = (int16_t*) __malloc_heap_psram(size * sizeof(int16_t));

    if (s_API_channels == 2) {
        resample_out_ptr = samplesOut2_tmp;
    } else {
        resample_out_ptr = samplesOut;
    }

    // ALLOC(samplesOut1_tmp_storage2, delay_stack_alloc ? s_channelsInternal * (s_channel_state[0].frame_length + 2) : ALLOC_NONE, int16_t);
    size = delay_stack_alloc ? s_channelsInternal * (s_channel_state[0].frame_length + 2) : ALLOC_NONE;
    samplesOut1_tmp_storage2 = (int16_t*) __malloc_heap_psram(size * sizeof(int16_t));

    if (delay_stack_alloc) {
        memcpy(samplesOut1_tmp_storage2, samplesOut, size * sizeof(int16_t));
        samplesOut1_tmp[0] = samplesOut1_tmp_storage2;
        samplesOut1_tmp[1] = samplesOut1_tmp_storage2 + s_channel_state[0].frame_length + 2;
    }
    for (n = 0; n < silk_min(s_API_channels, s_channelsInternal); n++) {

        /* Resample decoded signal to API_sampleRate */
        ret += silk_resampler(&s_channel_state[n].resampler_state, resample_out_ptr, &samplesOut1_tmp[n][1], nSamplesOutDec);

        /* Interleave if stereo output and stereo stream */
        if (s_API_channels == 2) {
            for (i = 0; i < *nSamplesOut; i++) { samplesOut[n + 2 * i] = resample_out_ptr[i]; }
        }
    }

    /* Create two channel output from mono stream */
    if (s_API_channels == 2 && s_channelsInternal == 1) {
        if (stereo_to_mono) {
            /* Resample right channel for newly collapsed stereo just in case
               we weren't doing collapsing when switching to mono */
            ret += silk_resampler(&s_channel_state[1].resampler_state, resample_out_ptr, &samplesOut1_tmp[0][1], nSamplesOutDec);

            for (i = 0; i < *nSamplesOut; i++) { samplesOut[1 + 2 * i] = resample_out_ptr[i]; }
        } else {
            for (i = 0; i < *nSamplesOut; i++) { samplesOut[1 + 2 * i] = samplesOut[0 + 2 * i]; }
        }
    }

    /* Export pitch lag, measured at 48 kHz sampling rate */
    if (s_channel_state[0].prevSignalType == TYPE_VOICED) {
        int mult_tab[3] = {6, 4, 3};
        s_prevPitchLag = s_channel_state[0].lagPrev * mult_tab[(s_channel_state[0].fs_kHz - 8) >> 2];
    } else {
        s_prevPitchLag = 0;
    }

    if (lostFlag == FLAG_PACKET_LOST) {
        /* On packet loss, remove the gain clamping to prevent having the energy "bounce back"
           if we lose packets when the energy is going down */
        for (i = 0; i < psDec->nChannelsInternal; i++) s_channel_state[i].LastGainIndex = 10;
    } else {
        psDec->prev_decode_only_middle = decode_only_middle;
    }

    free(samplesOut1_tmp_storage1);
    free(samplesOut2_tmp);
    free(samplesOut1_tmp_storage2);

    return ret;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decoder functions */
int32_t silk_Get_Decoder_Size(int32_t* decSizeBytes) {
    int32_t ret = SILK_NO_ERROR;

    *decSizeBytes = sizeof(silk_decoder);

    return ret;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Reset decoder state */
int32_t silk_InitDecoder() {

    int32_t n, ret = SILK_NO_ERROR;
    for (n = 0; n < DECODER_NUM_CHANNELS; n++) { ret = silk_init_decoder(&s_channel_state[n]); }
    memset(&s_decState.sStereo, 0, sizeof(s_decState.sStereo));
    /* Not strictly needed, but it's cleaner that way */
    s_decState.prev_decode_only_middle = 0;

    return ret;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Core decoder. Performs inverse NSQ operation LTP + LPC */
void silk_decode_core(silk_decoder_state*   psDec,                   /* I/O  Decoder state                               */
                      silk_decoder_control* psDecCtrl,               /* I    Decoder control                             */
                      int16_t               xq[],                    /* O    Decoded speech                              */
                      const int16_t         pulses[MAX_FRAME_LENGTH] /* I    Pulse signal                                */
) {
    int32_t  i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
    int16_t *A_Q12, *B_Q14, *pxq, A_Q12_tmp[MAX_LPC_ORDER];
    int32_t  LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
    int32_t *pred_lag_ptr, *pexc_Q14, *pres_Q14;

    assert(psDec->prev_gain_Q16 != 0);

    // int16_t sLTP[psDec->ltp_mem_length];
    // int32_t sLTP_Q15[psDec->ltp_mem_length + psDec->frame_length];
    // int32_t res_Q14[psDec->subfr_length];
    // int32_t sLPC_Q14[psDec->subfr_length + MAX_LPC_ORDER];
    int16_t* sLTP = (int16_t*)__malloc_heap_psram(psDec->ltp_mem_length * sizeof(int16_t));
    int32_t* sLTP_Q15 = (int32_t*)__malloc_heap_psram((psDec->ltp_mem_length + psDec->frame_length) * sizeof(int32_t));
    int32_t* res_Q14 = (int32_t*)__malloc_heap_psram(psDec->subfr_length * sizeof(int32_t));
    int32_t* sLPC_Q14 = (int32_t*)__malloc_heap_psram((psDec->subfr_length + MAX_LPC_ORDER) * sizeof(int32_t));

    offset_Q10 = silk_Quantization_Offsets_Q10[psDec->indices.signalType >> 1][psDec->indices.quantOffsetType];

    if (psDec->indices.NLSFInterpCoef_Q2 < 1 << 2) {
        NLSF_interpolation_flag = 1;
    } else {
        NLSF_interpolation_flag = 0;
    }

    /* Decode excitation */
    rand_seed = psDec->indices.Seed;
    for (i = 0; i < psDec->frame_length; i++) {
        rand_seed = silk_RAND(rand_seed);
        psDec->exc_Q14[i] = silk_LSHIFT((int32_t)pulses[i], 14);
        if (psDec->exc_Q14[i] > 0) {
            psDec->exc_Q14[i] -= QUANT_LEVEL_ADJUST_Q10 << 4;
        } else if (psDec->exc_Q14[i] < 0) {
            psDec->exc_Q14[i] += QUANT_LEVEL_ADJUST_Q10 << 4;
        }
        psDec->exc_Q14[i] += offset_Q10 << 4;
        if (rand_seed < 0) { psDec->exc_Q14[i] = -psDec->exc_Q14[i]; }

        rand_seed = silk_ADD32_ovflw(rand_seed, pulses[i]);
    }

    /* Copy LPC state */
    memcpy(sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof(int32_t));

    pexc_Q14 = psDec->exc_Q14;
    pxq = xq;
    sLTP_buf_idx = psDec->ltp_mem_length;
    /* Loop over subframes */
    for (k = 0; k < psDec->nb_subfr; k++) {
        pres_Q14 = res_Q14;
        A_Q12 = psDecCtrl->PredCoef_Q12[k >> 1];

        /* Preload LPC coeficients to array on stack. Gives small performance gain */
        memcpy(A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof(int16_t));
        B_Q14 = &psDecCtrl->LTPCoef_Q14[k * LTP_ORDER];
        signalType = psDec->indices.signalType;

        Gain_Q10 = silk_RSHIFT(psDecCtrl->Gains_Q16[k], 6);
        inv_gain_Q31 = silk_INVERSE32_varQ(psDecCtrl->Gains_Q16[k], 47);

        /* Calculate gain adjustment factor */
        if (psDecCtrl->Gains_Q16[k] != psDec->prev_gain_Q16) {
            gain_adj_Q16 = silk_DIV32_varQ(psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[k], 16);

            /* Scale short term state */
            for (i = 0; i < MAX_LPC_ORDER; i++) { sLPC_Q14[i] = silk_SMULWW(gain_adj_Q16, sLPC_Q14[i]); }
        } else {
            gain_adj_Q16 = (int32_t)1 << 16;
        }

        /* Save inv_gain */
        assert(inv_gain_Q31 != 0);
        psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[k];

        /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
        if (psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED && psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR / 2) {
            memset(B_Q14, 0, LTP_ORDER * sizeof(int16_t));
            B_Q14[LTP_ORDER / 2] = SILK_FIX_CONST(0.25, 14);

            signalType = TYPE_VOICED;
            psDecCtrl->pitchL[k] = psDec->lagPrev;
        }

        if (signalType == TYPE_VOICED) {
            /* Voiced */
            lag = psDecCtrl->pitchL[k];

            /* Re-whitening */
            if (k == 0 || (k == 2 && NLSF_interpolation_flag)) {
                /* Rewhiten with new A coefs */
                start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
                assert(start_idx > 0);

                if (k == 2) { memcpy(&psDec->outBuf[psDec->ltp_mem_length], xq, 2 * psDec->subfr_length * sizeof(int16_t)); }

                silk_LPC_analysis_filter(&sLTP[start_idx], &psDec->outBuf[start_idx + k * psDec->subfr_length], A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order);

                /* After rewhitening the LTP state is unscaled */
                if (k == 0) {
                    /* Do LTP downscaling to reduce inter-packet dependency */
                    inv_gain_Q31 = silk_LSHIFT(silk_SMULWB(inv_gain_Q31, psDecCtrl->LTP_scale_Q14), 2);
                }
                for (i = 0; i < lag + LTP_ORDER / 2; i++) { sLTP_Q15[sLTP_buf_idx - i - 1] = silk_SMULWB(inv_gain_Q31, sLTP[psDec->ltp_mem_length - i - 1]); }
            } else {
                /* Update LTP state when Gain changes */
                if (gain_adj_Q16 != (int32_t)1 << 16) {
                    for (i = 0; i < lag + LTP_ORDER / 2; i++) { sLTP_Q15[sLTP_buf_idx - i - 1] = silk_SMULWW(gain_adj_Q16, sLTP_Q15[sLTP_buf_idx - i - 1]); }
                }
            }
        }

        /* Long-term prediction */
        if (signalType == TYPE_VOICED) {
            /* Set up pointer */
            pred_lag_ptr = &sLTP_Q15[sLTP_buf_idx - lag + LTP_ORDER / 2];
            for (i = 0; i < psDec->subfr_length; i++) {
                /* Unrolled loop */
                /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
                LTP_pred_Q13 = 2;
                LTP_pred_Q13 = silk_SMLAWB(LTP_pred_Q13, pred_lag_ptr[0], B_Q14[0]);
                LTP_pred_Q13 = silk_SMLAWB(LTP_pred_Q13, pred_lag_ptr[-1], B_Q14[1]);
                LTP_pred_Q13 = silk_SMLAWB(LTP_pred_Q13, pred_lag_ptr[-2], B_Q14[2]);
                LTP_pred_Q13 = silk_SMLAWB(LTP_pred_Q13, pred_lag_ptr[-3], B_Q14[3]);
                LTP_pred_Q13 = silk_SMLAWB(LTP_pred_Q13, pred_lag_ptr[-4], B_Q14[4]);
                pred_lag_ptr++;

                /* Generate LPC excitation */
                pres_Q14[i] = silk_ADD_LSHIFT32(pexc_Q14[i], LTP_pred_Q13, 1);

                /* Update states */
                sLTP_Q15[sLTP_buf_idx] = silk_LSHIFT(pres_Q14[i], 1);
                sLTP_buf_idx++;
            }
        } else {
            pres_Q14 = pexc_Q14;
        }

        for (i = 0; i < psDec->subfr_length; i++) {
            /* Short-term prediction */
            assert(psDec->LPC_order == 10 || psDec->LPC_order == 16);
            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
            LPC_pred_Q10 = silk_RSHIFT(psDec->LPC_order, 1);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 1], A_Q12_tmp[0]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 2], A_Q12_tmp[1]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 3], A_Q12_tmp[2]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 4], A_Q12_tmp[3]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 5], A_Q12_tmp[4]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 6], A_Q12_tmp[5]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 7], A_Q12_tmp[6]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 8], A_Q12_tmp[7]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 9], A_Q12_tmp[8]);
            LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 10], A_Q12_tmp[9]);
            if (psDec->LPC_order == 16) {
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 11], A_Q12_tmp[10]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 12], A_Q12_tmp[11]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 13], A_Q12_tmp[12]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 14], A_Q12_tmp[13]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 15], A_Q12_tmp[14]);
                LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14[MAX_LPC_ORDER + i - 16], A_Q12_tmp[15]);
            }

            /* Add prediction to LPC excitation */
            sLPC_Q14[MAX_LPC_ORDER + i] = silk_ADD_SAT32(pres_Q14[i], silk_LSHIFT_SAT32(LPC_pred_Q10, 4));

            /* Scale with gain */
            pxq[i] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(silk_SMULWW(sLPC_Q14[MAX_LPC_ORDER + i], Gain_Q10), 8));
        }

        /* Update LPC filter state */
        memcpy(sLPC_Q14, &sLPC_Q14[psDec->subfr_length], MAX_LPC_ORDER * sizeof(int32_t));
        pexc_Q14 += psDec->subfr_length;
        pxq += psDec->subfr_length;
    }

    /* Save LPC state */
    memcpy(psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof(int32_t));

    free (sLTP);
    free (sLTP_Q15);
    free (res_Q14);
    free (sLPC_Q14);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Decode frame */
int32_t silk_decode_frame(silk_decoder_state* psDec,     /* I/O  Pointer to Silk decoder state               */
                          int16_t             pOut[],    /* O    Pointer to output speech frame              */
                          int32_t*            pN,        /* O    Pointer to size of output frame             */
                          int32_t             lostFlag,  /* I    0: no loss, 1 loss, 2 decode fec            */
                          int32_t             condCoding /* I    The type of conditional coding to use       */
) {
    // VARDECL(silk_decoder_control, psDecCtrl);
    int32_t L, mv_len, ret = 0;

    L = psDec->frame_length;
    silk_decoder_control psDecCtrl[1];
    psDecCtrl->LTP_scale_Q14 = 0;

    /* Safety checks */
    assert(L > 0 && L <= MAX_FRAME_LENGTH);

    if (lostFlag == FLAG_DECODE_NORMAL || (lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[psDec->nFramesDecoded] == 1)) {
        int16_t pulses[(L + SHELL_CODEC_FRAME_LENGTH - 1) & ~(SHELL_CODEC_FRAME_LENGTH - 1)];
        /*********************************************/
        /* Decode quantization indices of side info  */
        /*********************************************/
        silk_decode_indices(psDec, psDec->nFramesDecoded, lostFlag, condCoding);

        /*********************************************/
        /* Decode quantization indices of excitation */
        /*********************************************/
        silk_decode_pulses(pulses, psDec->indices.signalType, psDec->indices.quantOffsetType, psDec->frame_length);

        /********************************************/
        /* Decode parameters and pulse signal       */
        /********************************************/
        silk_decode_parameters(psDec, psDecCtrl, condCoding);

        /********************************************************/
        /* Run inverse NSQ                                      */
        /********************************************************/
        silk_decode_core(psDec, psDecCtrl, pOut, pulses);

        /********************************************************/
        /* Update PLC state                                     */
        /********************************************************/
        silk_PLC(psDec, psDecCtrl, pOut, 0);

        psDec->lossCnt = 0;
        psDec->prevSignalType = psDec->indices.signalType;
        assert(psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2);

        /* A frame has been decoded without errors */
        psDec->first_frame_after_reset = 0;
    } else {
        /* Handle packet loss by extrapolation */
        psDec->indices.signalType = psDec->prevSignalType;
        silk_PLC(psDec, psDecCtrl, pOut, 1);
    }

    /*************************/
    /* Update output buffer. */
    /*************************/
    assert(psDec->ltp_mem_length >= psDec->frame_length);
    mv_len = psDec->ltp_mem_length - psDec->frame_length;
    memmove(psDec->outBuf, &psDec->outBuf[psDec->frame_length], mv_len * sizeof(int16_t));
    memcpy(&psDec->outBuf[mv_len], pOut, psDec->frame_length * sizeof(int16_t));

    /************************************************/
    /* Comfort noise generation / estimation        */
    /************************************************/
    silk_CNG(psDec, psDecCtrl, pOut, L);

    /****************************************************************/
    /* Ensure smooth connection of extrapolated and good frames     */
    /****************************************************************/
    silk_PLC_glue_frames(psDec, pOut, L);

    /* Update some decoder state variables */
    psDec->lagPrev = psDecCtrl->pitchL[psDec->nb_subfr - 1];

    /* Set output frame length */
    *pN = L;

    return ret;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_decode_pitch(int16_t       lagIndex,     /* I                                                                */
                       int8_t        contourIndex, /* O                                                                */
                       int32_t       pitch_lags[], /* O    4 pitch values                                              */
                       const int32_t Fs_kHz,       /* I    sampling frequency (kHz)                                    */
                       const int32_t nb_subfr      /* I    number of sub frames                                        */
) {
    int32_t       lag, k, min_lag, max_lag, cbk_size;
    const int8_t* Lag_CB_ptr;

    if (Fs_kHz == 8) {
        if (nb_subfr == PE_MAX_NB_SUBFR) {
            Lag_CB_ptr = &silk_CB_lags_stage2[0][0];
            cbk_size = PE_NB_CBKS_STAGE2_EXT;
        } else {
            assert(nb_subfr == PE_MAX_NB_SUBFR >> 1);
            Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[0][0];
            cbk_size = PE_NB_CBKS_STAGE2_10MS;
        }
    } else {
        if (nb_subfr == PE_MAX_NB_SUBFR) {
            Lag_CB_ptr = &silk_CB_lags_stage3[0][0];
            cbk_size = PE_NB_CBKS_STAGE3_MAX;
        } else {
            assert(nb_subfr == PE_MAX_NB_SUBFR >> 1);
            Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[0][0];
            cbk_size = PE_NB_CBKS_STAGE3_10MS;
        }
    }

    min_lag = silk_SMULBB(PE_MIN_LAG_MS, Fs_kHz);
    max_lag = silk_SMULBB(PE_MAX_LAG_MS, Fs_kHz);
    lag = min_lag + lagIndex;

    for (k = 0; k < nb_subfr; k++) {
        pitch_lags[k] = lag + matrix_ptr(Lag_CB_ptr, k, contourIndex, cbk_size);
        pitch_lags[k] = silk_LIMIT(pitch_lags[k], min_lag, max_lag);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Gain scalar quantization with hysteresis, uniform on log scale */
void silk_gains_quant(int8_t        ind[MAX_NB_SUBFR],      /* O    gain indices                                */
                      int32_t       gain_Q16[MAX_NB_SUBFR], /* I/O  gains (quantized out)                       */
                      int8_t*       prev_ind,               /* I/O  last index in previous frame                */
                      const int32_t conditional,            /* I    first gain is delta coded if 1              */
                      const int32_t nb_subfr                /* I    number of subframes                         */
) {
    int32_t k, double_step_size_threshold;

    for (k = 0; k < nb_subfr; k++) {
        /* Convert to log scale, scale, floor() */
        ind[k] = silk_SMULWB(SCALE_Q16, silk_lin2log(gain_Q16[k]) - OFFSET);

        /* Round towards previous quantized gain (hysteresis) */
        if (ind[k] < *prev_ind) { ind[k]++; }
        ind[k] = silk_LIMIT_int(ind[k], 0, N_LEVELS_QGAIN - 1);

        /* Compute delta indices and limit */
        if (k == 0 && conditional == 0) {
            /* Full index */
            ind[k] = silk_LIMIT_int(ind[k], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1);
            *prev_ind = ind[k];
        } else {
            /* Delta index */
            ind[k] = ind[k] - *prev_ind;

            /* Double the quantization step size for large gain increases, so that the max gain level can be reached */
            double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
            if (ind[k] > double_step_size_threshold) { ind[k] = double_step_size_threshold + silk_RSHIFT(ind[k] - double_step_size_threshold + 1, 1); }

            ind[k] = silk_LIMIT_int(ind[k], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT);

            /* Accumulate deltas */
            if (ind[k] > double_step_size_threshold) {
                *prev_ind += silk_LSHIFT(ind[k], 1) - double_step_size_threshold;
                *prev_ind = silk_min_int(*prev_ind, N_LEVELS_QGAIN - 1);
            } else {
                *prev_ind += ind[k];
            }

            /* Shift to make non-negative */
            ind[k] -= MIN_DELTA_GAIN_QUANT;
        }

        /* Scale and convert to linear scale */
        gain_Q16[k] = silk_log2lin(silk_min_32(silk_SMULWB(INV_SCALE_Q16, *prev_ind) + OFFSET, 3967)); /* 3967 = 31 in Q7 */
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Gains scalar dequantization, uniform on log scale */
void silk_gains_dequant(int32_t       gain_Q16[MAX_NB_SUBFR], /* O    quantized gains                             */
                        const int8_t  ind[MAX_NB_SUBFR],      /* I    gain indices                                */
                        int8_t*       prev_ind,               /* I/O  last index in previous frame                */
                        const int32_t conditional,            /* I    first gain is delta coded if 1              */
                        const int32_t nb_subfr                /* I    number of subframes                          */
) {
    int32_t k, ind_tmp, double_step_size_threshold;

    for (k = 0; k < nb_subfr; k++) {
        if (k == 0 && conditional == 0) {
            /* Gain index is not allowed to go down more than 16 steps (~21.8 dB) */
            *prev_ind = silk_max_int(ind[k], *prev_ind - 16);
        } else {
            /* Delta index */
            ind_tmp = ind[k] + MIN_DELTA_GAIN_QUANT;

            /* Accumulate deltas */
            double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
            if (ind_tmp > double_step_size_threshold) {
                *prev_ind += silk_LSHIFT(ind_tmp, 1) - double_step_size_threshold;
            } else {
                *prev_ind += ind_tmp;
            }
        }
        *prev_ind = silk_LIMIT_int(*prev_ind, 0, N_LEVELS_QGAIN - 1);

        /* Scale and convert to linear scale */
        gain_Q16[k] = silk_log2lin(silk_min_32(silk_SMULWB(INV_SCALE_Q16, *prev_ind) + OFFSET, 3967)); /* 3967 = 31 in Q7 */
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Compute unique identifier of gain indices vector */
int32_t silk_gains_ID(                                 /* O    returns unique identifier of gains          */
                      const int8_t  ind[MAX_NB_SUBFR], /* I    gain indices                                */
                      const int32_t nb_subfr           /* I    number of subframes                         */
) {
    int32_t k;
    int32_t gainsID;

    gainsID = 0;
    for (k = 0; k < nb_subfr; k++) { gainsID = silk_ADD_LSHIFT32(ind[k], gainsID, 8); }

    return gainsID;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int32_t silk_init_decoder(silk_decoder_state* psDec) {
    /* Clear the entire encoder state, except anything copied */
    memset(psDec, 0, sizeof(silk_decoder_state));

    /* Used to deactivate LSF interpolation */
    psDec->first_frame_after_reset = 1;
    psDec->prev_gain_Q16 = 65536;

    /* Reset CNG state */
    silk_CNG_Reset(psDec);

    /* Reset PLC state */
    silk_PLC_Reset(psDec);

    return (0);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int32_t silk_inner_prod_aligned_scale(const int16_t* const inVec1, /*    I input vector 1 */
                                      const int16_t* const inVec2, /*    I input vector 2 */
                                      const int32_t        scale,  /*    I number of bits to shift         */
                                      const int32_t        len     /*    I vector lengths            */
) {
    int32_t i;
    int32_t sum = 0;
    for (i = 0; i < len; i++) { sum = silk_ADD_RSHIFT32(sum, silk_SMULBB(inVec1[i], inVec2[i]), scale); }
    return sum;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Interpolate two vectors */
void silk_interpolate(int16_t       xi[MAX_LPC_ORDER], /* O    interpolated vector                         */
                      const int16_t x0[MAX_LPC_ORDER], /* I    first vector                                */
                      const int16_t x1[MAX_LPC_ORDER], /* I    second vector                               */
                      const int32_t ifact_Q2,          /* I    interp. factor, weight on 2nd vector        */
                      const int32_t d                  /* I    number of parameters                        */
) {
    int32_t i;

    assert(ifact_Q2 >= 0);
    assert(ifact_Q2 <= 4);

    for (i = 0; i < d; i++) { xi[i] = (int16_t)silk_ADD_RSHIFT(x0[i], silk_SMULBB(x1[i] - x0[i], ifact_Q2), 2); }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

int32_t silk_lin2log(const int32_t inLin /* I  input in linear scale                                         */
) {
    int32_t lz, frac_Q7;

    silk_CLZ_FRAC(inLin, &lz, &frac_Q7);

    /* Piece-wise parabolic approximation */
    return silk_ADD_LSHIFT32(silk_SMLAWB(frac_Q7, silk_MUL(frac_Q7, 128 - frac_Q7), 179), 31 - lz, 7);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Approximation of 2^() (very close inverse of silk_lin2log()) Convert input to a linear scale    */
int32_t silk_log2lin(const int32_t inLog_Q7) {
    int32_t out, frac_Q7;

    if (inLog_Q7 < 0) {
        return 0;
    } else if (inLog_Q7 >= 3967) {
        return silk_int32_MAX;
    }

    out = silk_LSHIFT(1, silk_RSHIFT(inLog_Q7, 7));
    frac_Q7 = inLog_Q7 & 0x7F;
    if (inLog_Q7 < 2048) {
        /* Piece-wise parabolic approximation */
        out = silk_ADD_RSHIFT32(out, silk_MUL(out, silk_SMLAWB(frac_Q7, silk_SMULBB(frac_Q7, 128 - frac_Q7), -174)), 7);
    } else {
        /* Piece-wise parabolic approximation */
        out = silk_MLA(out, silk_RSHIFT(out, 7), silk_SMLAWB(frac_Q7, silk_SMULBB(frac_Q7, 128 - frac_Q7), -174));
    }
    return out;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void silk_LPC_analysis_filter(int16_t*       out, /* O    Output signal                                               */
                              const int16_t* in,  /* I    Input signal                                                */
                              const int16_t* B,   /* I    MA prediction coefficients, Q12 [order]                     */
                              const int32_t  len, /* I    Signal length                                               */
                              const int32_t  d    /* I    Filter order                                                */
) {
    int32_t        j;
    int            ix;
    int32_t        out32_Q12, out32;
    const int16_t* in_ptr;
    assert(d >= 6);
    assert((d & 1) == 0);
    assert(d <= len);

    for (ix = d; ix < len; ix++) {
        in_ptr = &in[ix - 1];

        out32_Q12 = silk_SMULBB(in_ptr[0], B[0]);
        /* Allowing wrap around so that two wraps can cancel each other. The rare
           cases where the result wraps around can only be triggered by invalid streams*/
        out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-1], B[1]);
        out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-2], B[2]);
        out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-3], B[3]);
        out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-4], B[4]);
        out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-5], B[5]);
        for (j = 6; j < d; j += 2) {
            out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-j], B[j]);
            out32_Q12 = silk_SMLABB_ovflw(out32_Q12, in_ptr[-j - 1], B[j + 1]);
        }

        /* Subtract prediction */
        out32_Q12 = silk_SUB32_ovflw(silk_LSHIFT((int32_t)in_ptr[1], 12), out32_Q12);

        /* Scale to Q0 */
        out32 = silk_RSHIFT_ROUND(out32_Q12, 12);

        /* Saturate output */
        out[ix] = (int16_t)silk_SAT16(out32);
    }

    /* Set first d output samples to zero */
    memset(out, 0, d * sizeof(int16_t));
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
void silk_LPC_fit(int16_t*      a_QOUT, /* O    Output signal                                               */
                  int32_t*      a_QIN,  /* I/O  Input signal                                                */
                  const int32_t QOUT,   /* I    Input Q domain                                              */
                  const int32_t QIN,    /* I    Input Q domain                                              */
                  const int32_t d       /* I    Filter order                                                */
) {
    int32_t i, k, idx = 0;
    int32_t maxabs, absval, chirp_Q16;

    /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
    for (i = 0; i < 10; i++) {
        /* Find maximum absolute value and its index */
        maxabs = 0;
        for (k = 0; k < d; k++) {
            absval = silk_abs(a_QIN[k]);
            if (absval > maxabs) {
                maxabs = absval;
                idx = k;
            }
        }
        maxabs = silk_RSHIFT_ROUND(maxabs, QIN - QOUT);

        if (maxabs > silk_int16_MAX) {
            /* Reduce magnitude of prediction coefficients */
            maxabs = silk_min(maxabs, 163838); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
            chirp_Q16 = SILK_FIX_CONST(0.999, 16) - silk_DIV32(silk_LSHIFT(maxabs - silk_int16_MAX, 14), silk_RSHIFT32(silk_MUL(maxabs, idx + 1), 2));
            silk_bwexpander_32(a_QIN, d, chirp_Q16);
        } else {
            break;
        }
    }

    if (i == 10) {
        /* Reached the last iteration, clip the coefficients */
        for (k = 0; k < d; k++) {
            a_QOUT[k] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(a_QIN[k], QIN - QOUT));
            a_QIN[k] = silk_LSHIFT((int32_t)a_QOUT[k], QIN - QOUT);
        }
    } else {
        for (k = 0; k < d; k++) { a_QOUT[k] = (int16_t)silk_RSHIFT_ROUND(a_QIN[k], QIN - QOUT); }
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Compute inverse of LPC prediction gain, and                          */
/* test if LPC coefficients are stable (all poles within unit circle)   */
int32_t LPC_inverse_pred_gain_QA_c(                                        /* O   Returns inverse prediction gain in energy domain, Q30    */
                                   int32_t       A_QA[SILK_MAX_ORDER_LPC], /* I   Prediction coefficients */
                                   const int32_t order                     /* I   Prediction order               */
) {
    const uint8_t QA24 = 24;
    int32_t       k, n, mult2Q;
    int32_t       invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;

    invGain_Q30 = SILK_FIX_CONST(1, 30);
    for (k = order - 1; k > 0; k--) {
        /* Check for stability */
        if ((A_QA[k] > A_LIMIT) || (A_QA[k] < -A_LIMIT)) { return 0; }

        /* Set RC equal to negated AR coef */
        rc_Q31 = -silk_LSHIFT(A_QA[k], 31 - QA24);

        /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
        rc_mult1_Q30 = silk_SUB32(SILK_FIX_CONST(1, 30), silk_SMMUL(rc_Q31, rc_Q31));
        assert(rc_mult1_Q30 > (1 << 15)); /* reduce A_LIMIT if fails */
        assert(rc_mult1_Q30 <= (1 << 30));

        /* Update inverse gain */
        /* invGain_Q30 range: [ 0 : 2^30 ] */
        invGain_Q30 = silk_LSHIFT(silk_SMMUL(invGain_Q30, rc_mult1_Q30), 2);
        assert(invGain_Q30 >= 0);
        assert(invGain_Q30 <= (1 << 30));
        if (invGain_Q30 < SILK_FIX_CONST(1.0f / MAX_PREDICTION_POWER_GAIN, 30)) { return 0; }

        /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
        mult2Q = 32 - silk_CLZ32(silk_abs(rc_mult1_Q30));
        rc_mult2 = silk_INVERSE32_varQ(rc_mult1_Q30, mult2Q + 30);

        /* Update AR coefficient */
        for (n = 0; n < (k + 1) >> 1; n++) {
            int64_t tmp64;
            tmp1 = A_QA[n];
            tmp2 = A_QA[k - n - 1];
            tmp64 = silk_RSHIFT_ROUND64(silk_SMULL(silk_SUB_SAT32(tmp1, MUL32_FRAC_Q(tmp2, rc_Q31, 31)), rc_mult2), mult2Q);
            if (tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN) { return 0; }
            A_QA[n] = (int32_t)tmp64;
            tmp64 = silk_RSHIFT_ROUND64(silk_SMULL(silk_SUB_SAT32(tmp2, MUL32_FRAC_Q(tmp1, rc_Q31, 31)), rc_mult2), mult2Q);
            if (tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN) { return 0; }
            A_QA[k - n - 1] = (int32_t)tmp64;
        }
    }

    /* Check for stability */
    if ((A_QA[k] > A_LIMIT) || (A_QA[k] < -A_LIMIT)) { return 0; }

    /* Set RC equal to negated AR coef */
    rc_Q31 = -silk_LSHIFT(A_QA[0], 31 - QA24);

    /* Range: [ 1 : 2^30 ] */
    rc_mult1_Q30 = silk_SUB32(SILK_FIX_CONST(1, 30), silk_SMMUL(rc_Q31, rc_Q31));

    /* Update inverse gain */
    /* Range: [ 0 : 2^30 ] */
    invGain_Q30 = silk_LSHIFT(silk_SMMUL(invGain_Q30, rc_mult1_Q30), 2);
    assert(invGain_Q30 >= 0);
    assert(invGain_Q30 <= (1 << 30));
    if (invGain_Q30 < SILK_FIX_CONST(1.0f / MAX_PREDICTION_POWER_GAIN, 30)) { return 0; }

    return invGain_Q30;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* For input in Q12 domain */
int32_t silk_LPC_inverse_pred_gain_c(                      /* O   Returns inverse prediction gain in energy domain, Q30        */
                                     const int16_t* A_Q12, /* I   Prediction coefficients, Q12 [order] */
                                     const int32_t  order  /* I   Prediction order   */
) {
    int32_t        k;
    int32_t        Atmp_QA[SILK_MAX_ORDER_LPC];
    int32_t        DC_resp = 0;
    const uint32_t QA24 = 24;

    /* Increase Q domain of the AR coefficients */
    for (k = 0; k < order; k++) {
        DC_resp += (int32_t)A_Q12[k];
        Atmp_QA[k] = silk_LSHIFT32((int32_t)A_Q12[k], QA24 - 12);
    }
    /* If the DC is unstable, we don't even need to do the full calculations */
    if (DC_resp >= 4096) { return 0; }
    return LPC_inverse_pred_gain_QA_c(Atmp_QA, order);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Predictive dequantizer for NLSF residuals */
void silk_NLSF_residual_dequant(                                   /* O    Returns RD value in Q30                     */
                                int16_t       x_Q10[],             /* O    Output [ order ]                            */
                                const int8_t  indices[],           /* I    Quantization indices [ order ]              */
                                const uint8_t pred_coef_Q8[],      /* I    Backward predictor coefs [ order ]          */
                                const int32_t quant_step_size_Q16, /* I    Quantization step size                      */
                                const int16_t order                /* I    Number of input values                      */
) {
    int32_t i, out_Q10, pred_Q10;

    out_Q10 = 0;
    for (i = order - 1; i >= 0; i--) {
        pred_Q10 = silk_RSHIFT(silk_SMULBB(out_Q10, (int16_t)pred_coef_Q8[i]), 8);
        out_Q10 = silk_LSHIFT(indices[i], 10);
        if (out_Q10 > 0) {
            out_Q10 = silk_SUB16(out_Q10, SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10));
        } else if (out_Q10 < 0) {
            out_Q10 = out_Q10 + SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10);
        }
        out_Q10 = silk_SMLAWB(pred_Q10, (int32_t)out_Q10, quant_step_size_Q16);
        x_Q10[i] = out_Q10;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* NLSF vector decoder */
void silk_NLSF_decode(int16_t*                   pNLSF_Q15,   /* O    Quantized NLSF vector [ LPC_ORDER ]         */
                      int8_t*                    NLSFIndices, /* I    Codebook path vector [ LPC_ORDER + 1 ]      */
                      const silk_NLSF_CB_struct* psNLSF_CB    /* I    Codebook object                             */
) {
    int32_t        i;
    uint8_t        pred_Q8[MAX_LPC_ORDER];
    int16_t        ec_ix[MAX_LPC_ORDER];
    int16_t        res_Q10[MAX_LPC_ORDER];
    int32_t        NLSF_Q15_tmp;
    const uint8_t* pCB_element;
    const int16_t* pCB_Wght_Q9;

    /* Unpack entropy table indices and predictor for current CB1 index */
    silk_NLSF_unpack(ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[0]);

    /* Predictive residual dequantizer */
    silk_NLSF_residual_dequant(res_Q10, &NLSFIndices[1], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order);

    /* Apply inverse square-rooted weights to first stage and add to output */
    pCB_element = &psNLSF_CB->CB1_NLSF_Q8[NLSFIndices[0] * psNLSF_CB->order];
    pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[NLSFIndices[0] * psNLSF_CB->order];
    for (i = 0; i < psNLSF_CB->order; i++) {
        NLSF_Q15_tmp = silk_ADD_LSHIFT32(silk_DIV32_16(silk_LSHIFT((int32_t)res_Q10[i], 14), pCB_Wght_Q9[i]), (int16_t)pCB_element[i], 7);
        pNLSF_Q15[i] = (int16_t)silk_LIMIT(NLSF_Q15_tmp, 0, 32767);
    }

    /* NLSF stabilization */
    silk_NLSF_stabilize(pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Delayed-decision quantizer for NLSF residuals */
int32_t silk_NLSF_del_dec_quant(                                      /* O    Returns RD value in Q25                     */
                                int8_t        indices[],              /* O    Quantization indices [ order ]              */
                                const int16_t x_Q10[],                /* I    Input [ order ]                             */
                                const int16_t w_Q5[],                 /* I    Weights [ order ]                           */
                                const uint8_t pred_coef_Q8[],         /* I    Backward predictor coefs [ order ]          */
                                const int16_t ec_ix[],                /* I    Indices to entropy coding tables [ order ]  */
                                const uint8_t ec_rates_Q5[],          /* I    Rates []                                    */
                                const int32_t quant_step_size_Q16,    /* I    Quantization step size    */
                                const int16_t inv_quant_step_size_Q6, /* I    Inverse quantization step size */
                                const int32_t mu_Q20,                 /* I    R/D tradeoff                                */
                                const int16_t order                   /* I    Number of input values                      */
) {
    int32_t        i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10;
    int32_t        pred_Q10, diff_Q10, rate0_Q5, rate1_Q5;
    int16_t        out0_Q10, out1_Q10;
    int32_t        RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25;
    int32_t        ind_sort[NLSF_QUANT_DEL_DEC_STATES];
    int8_t         ind[NLSF_QUANT_DEL_DEC_STATES][MAX_LPC_ORDER];
    int16_t        prev_out_Q10[2 * NLSF_QUANT_DEL_DEC_STATES];
    int32_t        RD_Q25[2 * NLSF_QUANT_DEL_DEC_STATES];
    int32_t        RD_min_Q25[NLSF_QUANT_DEL_DEC_STATES];
    int32_t        RD_max_Q25[NLSF_QUANT_DEL_DEC_STATES];
    const uint8_t* rates_Q5;

    int32_t out0_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT];
    int32_t out1_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT];

    for (i = -NLSF_QUANT_MAX_AMPLITUDE_EXT; i <= NLSF_QUANT_MAX_AMPLITUDE_EXT - 1; i++) {
        out0_Q10 = silk_LSHIFT(i, 10);
        out1_Q10 = out0_Q10 + 1024;
        if (i > 0) {
            out0_Q10 = silk_SUB16(out0_Q10, SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10));
            out1_Q10 = silk_SUB16(out1_Q10, SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10));
        } else if (i == 0) {
            out1_Q10 = silk_SUB16(out1_Q10, SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10));
        } else if (i == -1) {
            out0_Q10 = out0_Q10 + SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10);
        } else {
            out0_Q10 = out0_Q10 + SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10);
            out1_Q10 = out1_Q10 + SILK_FIX_CONST(NLSF_QUANT_LEVEL_ADJ, 10);
        }
        out0_Q10_table[i + NLSF_QUANT_MAX_AMPLITUDE_EXT] = silk_RSHIFT(silk_SMULBB(out0_Q10, quant_step_size_Q16), 16);
        out1_Q10_table[i + NLSF_QUANT_MAX_AMPLITUDE_EXT] = silk_RSHIFT(silk_SMULBB(out1_Q10, quant_step_size_Q16), 16);
    }

    assert((NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES - 1)) == 0); /* must be power of two */

    nStates = 1;
    RD_Q25[0] = 0;
    prev_out_Q10[0] = 0;
    for (i = order - 1; i >= 0; i--) {
        rates_Q5 = &ec_rates_Q5[ec_ix[i]];
        in_Q10 = x_Q10[i];
        for (j = 0; j < nStates; j++) {
            pred_Q10 = silk_RSHIFT(silk_SMULBB((int16_t)pred_coef_Q8[i], prev_out_Q10[j]), 8);
            res_Q10 = silk_SUB16(in_Q10, pred_Q10);
            ind_tmp = silk_RSHIFT(silk_SMULBB(inv_quant_step_size_Q6, res_Q10), 16);
            ind_tmp = silk_LIMIT(ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT - 1);
            ind[j][i] = (int8_t)ind_tmp;

            /* compute outputs for ind_tmp and ind_tmp + 1 */
            out0_Q10 = out0_Q10_table[ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT];
            out1_Q10 = out1_Q10_table[ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT];

            out0_Q10 = out0_Q10 + pred_Q10;
            out1_Q10 = out1_Q10 + pred_Q10;
            prev_out_Q10[j] = out0_Q10;
            prev_out_Q10[j + nStates] = out1_Q10;

            /* compute RD for ind_tmp and ind_tmp + 1 */
            if (ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE) {
                if (ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE) {
                    rate0_Q5 = rates_Q5[ind_tmp + NLSF_QUANT_MAX_AMPLITUDE];
                    rate1_Q5 = 280;
                } else {
                    rate0_Q5 = silk_SMLABB(280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp);
                    rate1_Q5 = rate0_Q5 + 43;
                }
            } else if (ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE) {
                if (ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE) {
                    rate0_Q5 = 280;
                    rate1_Q5 = rates_Q5[ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE];
                } else {
                    rate0_Q5 = silk_SMLABB(280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp);
                    rate1_Q5 = silk_SUB16(rate0_Q5, 43);
                }
            } else {
                rate0_Q5 = rates_Q5[ind_tmp + NLSF_QUANT_MAX_AMPLITUDE];
                rate1_Q5 = rates_Q5[ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE];
            }
            RD_tmp_Q25 = RD_Q25[j];
            diff_Q10 = silk_SUB16(in_Q10, out0_Q10);
            RD_Q25[j] = silk_SMLABB(silk_MLA(RD_tmp_Q25, silk_SMULBB(diff_Q10, diff_Q10), w_Q5[i]), mu_Q20, rate0_Q5);
            diff_Q10 = silk_SUB16(in_Q10, out1_Q10);
            RD_Q25[j + nStates] = silk_SMLABB(silk_MLA(RD_tmp_Q25, silk_SMULBB(diff_Q10, diff_Q10), w_Q5[i]), mu_Q20, rate1_Q5);
        }

        if (nStates <= NLSF_QUANT_DEL_DEC_STATES / 2) {
            /* double number of states and copy */
            for (j = 0; j < nStates; j++) { ind[j + nStates][i] = ind[j][i] + 1; }
            nStates = silk_LSHIFT(nStates, 1);
            for (j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++) { ind[j][i] = ind[j - nStates][i]; }
        } else {
            /* sort lower and upper half of RD_Q25, pairwise */
            for (j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++) {
                if (RD_Q25[j] > RD_Q25[j + NLSF_QUANT_DEL_DEC_STATES]) {
                    RD_max_Q25[j] = RD_Q25[j];
                    RD_min_Q25[j] = RD_Q25[j + NLSF_QUANT_DEL_DEC_STATES];
                    RD_Q25[j] = RD_min_Q25[j];
                    RD_Q25[j + NLSF_QUANT_DEL_DEC_STATES] = RD_max_Q25[j];
                    /* swap prev_out values */
                    out0_Q10 = prev_out_Q10[j];
                    prev_out_Q10[j] = prev_out_Q10[j + NLSF_QUANT_DEL_DEC_STATES];
                    prev_out_Q10[j + NLSF_QUANT_DEL_DEC_STATES] = out0_Q10;
                    ind_sort[j] = j + NLSF_QUANT_DEL_DEC_STATES;
                } else {
                    RD_min_Q25[j] = RD_Q25[j];
                    RD_max_Q25[j] = RD_Q25[j + NLSF_QUANT_DEL_DEC_STATES];
                    ind_sort[j] = j;
                }
            }
            /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if
             * necessary */
            /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */
            while (1) {
                min_max_Q25 = silk_int32_MAX;
                max_min_Q25 = 0;
                ind_min_max = 0;
                ind_max_min = 0;
                for (j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++) {
                    if (min_max_Q25 > RD_max_Q25[j]) {
                        min_max_Q25 = RD_max_Q25[j];
                        ind_min_max = j;
                    }
                    if (max_min_Q25 < RD_min_Q25[j]) {
                        max_min_Q25 = RD_min_Q25[j];
                        ind_max_min = j;
                    }
                }
                if (min_max_Q25 >= max_min_Q25) { break; }
                /* copy ind_min_max to ind_max_min */
                ind_sort[ind_max_min] = ind_sort[ind_min_max] ^ NLSF_QUANT_DEL_DEC_STATES;
                RD_Q25[ind_max_min] = RD_Q25[ind_min_max + NLSF_QUANT_DEL_DEC_STATES];
                prev_out_Q10[ind_max_min] = prev_out_Q10[ind_min_max + NLSF_QUANT_DEL_DEC_STATES];
                RD_min_Q25[ind_max_min] = 0;
                RD_max_Q25[ind_min_max] = silk_int32_MAX;
                memcpy(ind[ind_max_min], ind[ind_min_max], MAX_LPC_ORDER * sizeof(int8_t));
            }
            /* increment index if it comes from the upper half */
            for (j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++) { ind[j][i] += silk_RSHIFT(ind_sort[j], NLSF_QUANT_DEL_DEC_STATES_LOG2); }
        }
    }

    /* last sample: find winner, copy indices and return RD value */
    ind_tmp = 0;
    min_Q25 = silk_int32_MAX;
    for (j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++) {
        if (min_Q25 > RD_Q25[j]) {
            min_Q25 = RD_Q25[j];
            ind_tmp = j;
        }
    }
    for (j = 0; j < order; j++) {
        indices[j] = ind[ind_tmp & (NLSF_QUANT_DEL_DEC_STATES - 1)][j];
        assert(indices[j] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT);
        assert(indices[j] <= NLSF_QUANT_MAX_AMPLITUDE_EXT);
    }
    indices[0] += silk_RSHIFT(ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2);
    assert(indices[0] <= NLSF_QUANT_MAX_AMPLITUDE_EXT);
    assert(min_Q25 >= 0);
    return min_Q25;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* NLSF stabilizer, for a single input data vector */
void silk_NLSF_stabilize(int16_t*       NLSF_Q15,      /* I/O   Unstable/stabilized normalized LSF vector in Q15 [L]       */
                         const int16_t* NDeltaMin_Q15, /* I     Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1]   */
                         const int32_t  L              /* I     Number of NLSF parameters in the input vector              */
) {
    int32_t i, I = 0, k, loops;
    int16_t center_freq_Q15;
    int32_t diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15;

    /* This is necessary to ensure an output within range of a int16_t */
    assert(NDeltaMin_Q15[L] >= 1);

    for (loops = 0; loops < MAX_LOOPS; loops++) {
        /**************************/
        /* Find smallest distance */
        /**************************/
        /* First element */
        min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
        I = 0;
        /* Middle elements */
        for (i = 1; i <= L - 1; i++) {
            diff_Q15 = NLSF_Q15[i] - (NLSF_Q15[i - 1] + NDeltaMin_Q15[i]);
            if (diff_Q15 < min_diff_Q15) {
                min_diff_Q15 = diff_Q15;
                I = i;
            }
        }
        /* Last element */
        diff_Q15 = (1 << 15) - (NLSF_Q15[L - 1] + NDeltaMin_Q15[L]);
        if (diff_Q15 < min_diff_Q15) {
            min_diff_Q15 = diff_Q15;
            I = L;
        }

        /***************************************************/
        /* Now check if the smallest distance non-negative */
        /***************************************************/
        if (min_diff_Q15 >= 0) { return; }

        if (I == 0) {
            /* Move away from lower limit */
            NLSF_Q15[0] = NDeltaMin_Q15[0];
        } else if (I == L) {
            /* Move away from higher limit */
            NLSF_Q15[L - 1] = (1 << 15) - NDeltaMin_Q15[L];
        } else {
            /* Find the lower extreme for the location of the current center frequency */
            min_center_Q15 = 0;
            for (k = 0; k < I; k++) { min_center_Q15 += NDeltaMin_Q15[k]; }
            min_center_Q15 += silk_RSHIFT(NDeltaMin_Q15[I], 1);

            /* Find the upper extreme for the location of the current center frequency */
            max_center_Q15 = 1 << 15;
            for (k = L; k > I; k--) { max_center_Q15 -= NDeltaMin_Q15[k]; }
            max_center_Q15 -= silk_RSHIFT(NDeltaMin_Q15[I], 1);

            /* Move apart, sorted by value, keeping the same center frequency */
            center_freq_Q15 = (int16_t)silk_LIMIT_32(silk_RSHIFT_ROUND((int32_t)NLSF_Q15[I - 1] + (int32_t)NLSF_Q15[I], 1), min_center_Q15, max_center_Q15);
            NLSF_Q15[I - 1] = center_freq_Q15 - silk_RSHIFT(NDeltaMin_Q15[I], 1);
            NLSF_Q15[I] = NLSF_Q15[I - 1] + NDeltaMin_Q15[I];
        }
    }

    /* Safe and simple fall back method, which is less ideal than the above */
    if (loops == MAX_LOOPS) {
        /* Insertion sort (fast for already almost sorted arrays):   */
        /* Best case:  O(n)   for an already sorted array            */
        /* Worst case: O(n^2) for an inversely sorted array          */
        silk_insertion_sort_increasing_all_values_int16(&NLSF_Q15[0], L);

        /* First NLSF should be no less than NDeltaMin[0] */
        NLSF_Q15[0] = silk_max_int(NLSF_Q15[0], NDeltaMin_Q15[0]);

        /* Keep delta_min distance between the NLSFs */
        for (i = 1; i < L; i++) NLSF_Q15[i] = silk_max_int(NLSF_Q15[i], silk_ADD_SAT16(NLSF_Q15[i - 1], NDeltaMin_Q15[i]));

        /* Last NLSF should be no higher than 1 - NDeltaMin[L] */
        NLSF_Q15[L - 1] = silk_min_int(NLSF_Q15[L - 1], (1 << 15) - NDeltaMin_Q15[L]);

        /* Keep NDeltaMin distance between the NLSFs */
        for (i = L - 2; i >= 0; i--) NLSF_Q15[i] = silk_min_int(NLSF_Q15[i], NLSF_Q15[i + 1] - NDeltaMin_Q15[i + 1]);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Unpack predictor values and indices for entropy coding tables */
void silk_NLSF_unpack(int16_t                    ec_ix[],   /* O    Indices to entropy tables [ LPC_ORDER ]     */
                      uint8_t                    pred_Q8[], /* O    LSF predictor [ LPC_ORDER ]                 */
                      const silk_NLSF_CB_struct* psNLSF_CB, /* I    Codebook object                             */
                      const int32_t              CB1_index  /* I    Index of vector in first LSF codebook       */
) {
    int32_t        i;
    uint8_t        entry;
    const uint8_t* ec_sel_ptr;

    ec_sel_ptr = &psNLSF_CB->ec_sel[CB1_index * psNLSF_CB->order / 2];
    for (i = 0; i < psNLSF_CB->order; i += 2) {
        entry = *ec_sel_ptr++;
        ec_ix[i] = silk_SMULBB(silk_RSHIFT(entry, 1) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1);
        pred_Q8[i] = psNLSF_CB->pred_Q8[i + (entry & 1) * (psNLSF_CB->order - 1)];
        ec_ix[i + 1] = silk_SMULBB(silk_RSHIFT(entry, 5) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1);
        pred_Q8[i + 1] = psNLSF_CB->pred_Q8[i + (silk_RSHIFT(entry, 4) & 1) * (psNLSF_CB->order - 1) + 1];
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Laroia low complexity NLSF weights */
void silk_NLSF_VQ_weights_laroia(int16_t*       pNLSFW_Q_OUT, /* O     Pointer to input vector weights [D]    */
                                 const int16_t* pNLSF_Q15,    /* I     Pointer to input vector         [D] */
                                 const int32_t  D             /* I     Input vector dimension (even)                              */
) {
    int32_t k;
    int32_t tmp1_int, tmp2_int;

    assert(D > 0);
    assert((D & 1) == 0);

    /* First value */
    tmp1_int = silk_max_int(pNLSF_Q15[0], 1);
    tmp1_int = silk_DIV32_16((int32_t)1 << (15 + NLSF_W_Q), tmp1_int);
    tmp2_int = silk_max_int(pNLSF_Q15[1] - pNLSF_Q15[0], 1);
    tmp2_int = silk_DIV32_16((int32_t)1 << (15 + NLSF_W_Q), tmp2_int);
    pNLSFW_Q_OUT[0] = (int16_t)silk_min_int(tmp1_int + tmp2_int, silk_int16_MAX);
    assert(pNLSFW_Q_OUT[0] > 0);

    /* Main loop */
    for (k = 1; k < D - 1; k += 2) {
        tmp1_int = silk_max_int(pNLSF_Q15[k + 1] - pNLSF_Q15[k], 1);
        tmp1_int = silk_DIV32_16((int32_t)1 << (15 + NLSF_W_Q), tmp1_int);
        pNLSFW_Q_OUT[k] = (int16_t)silk_min_int(tmp1_int + tmp2_int, silk_int16_MAX);
        assert(pNLSFW_Q_OUT[k] > 0);

        tmp2_int = silk_max_int(pNLSF_Q15[k + 2] - pNLSF_Q15[k + 1], 1);
        tmp2_int = silk_DIV32_16((int32_t)1 << (15 + NLSF_W_Q), tmp2_int);
        pNLSFW_Q_OUT[k + 1] = (int16_t)silk_min_int(tmp1_int + tmp2_int, silk_int16_MAX);
        assert(pNLSFW_Q_OUT[k + 1] > 0);
    }

    /* Last value */
    tmp1_int = silk_max_int((1 << 15) - pNLSF_Q15[D - 1], 1);
    tmp1_int = silk_DIV32_16((int32_t)1 << (15 + NLSF_W_Q), tmp1_int);
    pNLSFW_Q_OUT[D - 1] = (int16_t)silk_min_int(tmp1_int + tmp2_int, silk_int16_MAX);
    assert(pNLSFW_Q_OUT[D - 1] > 0);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
void silk_NLSF_VQ(int32_t       err_Q24[],  /* O    Quantization errors [K]                     */
                  const int16_t in_Q15[],   /* I    Input vectors to be quantized [LPC_order]   */
                  const uint8_t pCB_Q8[],   /* I    Codebook vectors [K*LPC_order]              */
                  const int16_t pWght_Q9[], /* I    Codebook weights [K*LPC_order]              */
                  const int32_t K,          /* I    Number of codebook vectors                  */
                  const int32_t LPC_order   /* I    Number of LPCs                              */
) {
    int32_t        i, m;
    int32_t        diff_Q15, diffw_Q24, sum_error_Q24, pred_Q24;
    const int16_t* w_Q9_ptr;
    const uint8_t* cb_Q8_ptr;

    assert((LPC_order & 1) == 0);

    /* Loop over codebook */
    cb_Q8_ptr = pCB_Q8;
    w_Q9_ptr = pWght_Q9;
    for (i = 0; i < K; i++) {
        sum_error_Q24 = 0;
        pred_Q24 = 0;
        for (m = LPC_order - 2; m >= 0; m -= 2) {
            /* Compute weighted absolute predictive quantization error for index m + 1 */
            diff_Q15 = silk_SUB_LSHIFT32(in_Q15[m + 1], (int32_t)cb_Q8_ptr[m + 1], 7); /* range: [ -32767 : 32767 ]*/
            diffw_Q24 = silk_SMULBB(diff_Q15, w_Q9_ptr[m + 1]);
            sum_error_Q24 = sum_error_Q24 + silk_abs(silk_SUB_RSHIFT32(diffw_Q24, pred_Q24, 1));
            pred_Q24 = diffw_Q24;

            /* Compute weighted absolute predictive quantization error for index m */
            diff_Q15 = silk_SUB_LSHIFT32(in_Q15[m], (int32_t)cb_Q8_ptr[m], 7); /* range: [ -32767 : 32767 ]*/
            diffw_Q24 = silk_SMULBB(diff_Q15, w_Q9_ptr[m]);
            sum_error_Q24 = sum_error_Q24 + silk_abs(silk_SUB_RSHIFT32(diffw_Q24, pred_Q24, 1));
            pred_Q24 = diffw_Q24;

            assert(sum_error_Q24 >= 0);
        }
        err_Q24[i] = sum_error_Q24;
        cb_Q8_ptr += LPC_order;
        w_Q9_ptr += LPC_order;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void silk_PLC_Reset(silk_decoder_state* psDec) { /* I/O Decoder state        */

    psDec->sPLC.pitchL_Q8 = silk_LSHIFT(psDec->frame_length, 8 - 1);
    psDec->sPLC.prevGain_Q16[0] = SILK_FIX_CONST(1, 16);
    psDec->sPLC.prevGain_Q16[1] = SILK_FIX_CONST(1, 16);
    psDec->sPLC.subfr_length = 20;
    psDec->sPLC.nb_subfr = 2;
}

void silk_PLC(silk_decoder_state*   psDec,     /* I/O Decoder state        */
              silk_decoder_control* psDecCtrl, /* I/O Decoder control      */
              int16_t               frame[],   /* I/O  signal              */
              int32_t               lost       /* I Loss flag              */
) {
    /* PLC control function */
    if (psDec->fs_kHz != psDec->sPLC.fs_kHz) {
        silk_PLC_Reset(psDec);
        psDec->sPLC.fs_kHz = psDec->fs_kHz;
    }

    if (lost) {
        /****************************/
        /* Generate Signal          */
        /****************************/
        silk_PLC_conceal(psDec, psDecCtrl, frame);

        psDec->lossCnt++;
    } else {
        /****************************/
        /* Update state             */
        /****************************/
        silk_PLC_update(psDec, psDecCtrl);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Update state of PLC                            */
void silk_PLC_update(silk_decoder_state*   psDec,    /* I/O Decoder state        */
                     silk_decoder_control* psDecCtrl /* I/O Decoder control      */
) {
    int32_t          LTP_Gain_Q14, temp_LTP_Gain_Q14;
    int32_t          i, j;
    silk_PLC_struct* psPLC;

    psPLC = &psDec->sPLC;

    /* Update parameters used in case of packet loss */
    psDec->prevSignalType = psDec->indices.signalType;
    LTP_Gain_Q14 = 0;
    if (psDec->indices.signalType == TYPE_VOICED) {
        /* Find the parameters for the last subframe which contains a pitch pulse */
        for (j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[psDec->nb_subfr - 1]; j++) {
            if (j == psDec->nb_subfr) { break; }
            temp_LTP_Gain_Q14 = 0;
            for (i = 0; i < LTP_ORDER; i++) { temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[(psDec->nb_subfr - 1 - j) * LTP_ORDER + i]; }
            if (temp_LTP_Gain_Q14 > LTP_Gain_Q14) {
                LTP_Gain_Q14 = temp_LTP_Gain_Q14;
                memcpy(psPLC->LTPCoef_Q14, &psDecCtrl->LTPCoef_Q14[silk_SMULBB(psDec->nb_subfr - 1 - j, LTP_ORDER)], LTP_ORDER * sizeof(int16_t));
                psPLC->pitchL_Q8 = silk_LSHIFT(psDecCtrl->pitchL[psDec->nb_subfr - 1 - j], 8);
            }
        }

        memset(psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof(int16_t));
        psPLC->LTPCoef_Q14[LTP_ORDER / 2] = LTP_Gain_Q14;

        /* Limit LT coefs */
        if (LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14) {
            int32_t scale_Q10;
            int32_t tmp;

            tmp = silk_LSHIFT(V_PITCH_GAIN_START_MIN_Q14, 10);
            scale_Q10 = silk_DIV32(tmp, silk_max(LTP_Gain_Q14, 1));
            for (i = 0; i < LTP_ORDER; i++) { psPLC->LTPCoef_Q14[i] = silk_RSHIFT(silk_SMULBB(psPLC->LTPCoef_Q14[i], scale_Q10), 10); }
        } else if (LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14) {
            int32_t scale_Q14;
            int32_t tmp;

            tmp = silk_LSHIFT(V_PITCH_GAIN_START_MAX_Q14, 14);
            scale_Q14 = silk_DIV32(tmp, silk_max(LTP_Gain_Q14, 1));
            for (i = 0; i < LTP_ORDER; i++) { psPLC->LTPCoef_Q14[i] = silk_RSHIFT(silk_SMULBB(psPLC->LTPCoef_Q14[i], scale_Q14), 14); }
        }
    } else {
        psPLC->pitchL_Q8 = silk_LSHIFT(silk_SMULBB(psDec->fs_kHz, 18), 8);
        memset(psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof(int16_t));
    }

    /* Save LPC coeficients */
    memcpy(psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[1], psDec->LPC_order * sizeof(int16_t));
    psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;

    /* Save last two gains */
    memcpy(psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[psDec->nb_subfr - 2], 2 * sizeof(int32_t));

    psPLC->subfr_length = psDec->subfr_length;
    psPLC->nb_subfr = psDec->nb_subfr;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void silk_PLC_energy(int32_t* energy1, int32_t* shift1, int32_t* energy2, int32_t* shift2, const int32_t* exc_Q14, const int32_t* prevGain_Q10, int subfr_length, int nb_subfr) {
    int i, k;
    int16_t* exc_buf = NULL;
    int16_t* exc_buf_ptr;

    //ALLOC(exc_buf, 2 * subfr_length, int16_t);
    exc_buf = (int16_t*)__malloc_heap_psram(2 * subfr_length * sizeof(int16_t));

    /* Find random noise component */
    /* Scale previous excitation signal */
    exc_buf_ptr = exc_buf;
    for (k = 0; k < 2; k++) {
        for (i = 0; i < subfr_length; i++) { exc_buf_ptr[i] = (int16_t)silk_SAT16(silk_RSHIFT(silk_SMULWW(exc_Q14[i + (k + nb_subfr - 2) * subfr_length], prevGain_Q10[k]), 8)); }
        exc_buf_ptr += subfr_length;
    }
    /* Find the subframe with lowest energy of the last two and use that as random noise generator */
    silk_sum_sqr_shift(energy1, shift1, exc_buf, subfr_length);
    silk_sum_sqr_shift(energy2, shift2, &exc_buf[subfr_length], subfr_length);

    free(exc_buf);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void silk_PLC_conceal(silk_decoder_state*   psDec,     /* I/O Decoder state        */
                      silk_decoder_control* psDecCtrl, /* I/O Decoder control      */
                      int16_t               frame[]    /* O LPC residual signal    */
) {
    int32_t  i, j, k;
    int32_t  lag, idx, sLTP_buf_idx, shift1, shift2;
    int32_t  rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
    int32_t  energy1, energy2, *rand_ptr, *pred_lag_ptr;
    int32_t  LPC_pred_Q10, LTP_pred_Q12;
    int16_t  rand_scale_Q14;
    int16_t* B_Q14;
    int32_t* sLPC_Q14_ptr;
    int16_t  A_Q12[MAX_LPC_ORDER];

    int16_t* sLTP = NULL;
    int32_t* sLTP_Q14 = NULL;
    silk_PLC_struct* psPLC = &psDec->sPLC;
    int32_t          prevGain_Q10[2];

    //ALLOC(sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, int32_t);
    sLTP_Q14 = (int32_t*)__malloc_heap_psram((psDec->ltp_mem_length + psDec->frame_length) * sizeof(int32_t));
    // ALLOC(sLTP, psDec->ltp_mem_length, int16_t);
    sLTP = (int16_t*)__malloc_heap_psram(psDec->ltp_mem_length * sizeof(int16_t));

    prevGain_Q10[0] = silk_RSHIFT(psPLC->prevGain_Q16[0], 6);
    prevGain_Q10[1] = silk_RSHIFT(psPLC->prevGain_Q16[1], 6);

    if (psDec->first_frame_after_reset) { memset(psPLC->prevLPC_Q12, 0, sizeof(psPLC->prevLPC_Q12)); }

    silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);

    if (silk_RSHIFT(energy1, shift2) < silk_RSHIFT(energy2, shift1)) {
        /* First sub-frame has lowest energy */
        rand_ptr = &psDec->exc_Q14[silk_max_int(0, (psPLC->nb_subfr - 1) * psPLC->subfr_length - RAND_BUF_SIZE)];
    } else {
        /* Second sub-frame has lowest energy */
        rand_ptr = &psDec->exc_Q14[silk_max_int(0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE)];
    }

    /* Set up Gain to random noise component */
    B_Q14 = psPLC->LTPCoef_Q14;
    rand_scale_Q14 = psPLC->randScale_Q14;

    /* Set up attenuation gains */
    harm_Gain_Q15 = HARM_ATT_Q15[silk_min_int(NB_ATT - 1, psDec->lossCnt)];
    if (psDec->prevSignalType == TYPE_VOICED) {
        rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[silk_min_int(NB_ATT - 1, psDec->lossCnt)];
    } else {
        rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[silk_min_int(NB_ATT - 1, psDec->lossCnt)];
    }

    /* LPC concealment. Apply BWE to previous LPC */
    silk_bwexpander(psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST(BWE_COEF, 16));

    /* Preload LPC coeficients to array on stack. Gives small performance gain */
    memcpy(A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof(int16_t));

    /* First Lost frame */
    if (psDec->lossCnt == 0) {
        rand_scale_Q14 = 1 << 14;

        /* Reduce random noise Gain for voiced frames */
        if (psDec->prevSignalType == TYPE_VOICED) {
            for (i = 0; i < LTP_ORDER; i++) { rand_scale_Q14 -= B_Q14[i]; }
            rand_scale_Q14 = silk_max_16(3277, rand_scale_Q14); /* 0.2 */
            rand_scale_Q14 = (int16_t)silk_RSHIFT(silk_SMULBB(rand_scale_Q14, psPLC->prevLTP_scale_Q14), 14);
        } else {
            /* Reduce random noise for unvoiced frames with high LPC gain */
            int32_t invGain_Q30, down_scale_Q30;

            invGain_Q30 = silk_LPC_inverse_pred_gain(psPLC->prevLPC_Q12, psDec->LPC_order);

            down_scale_Q30 = silk_min_32(silk_RSHIFT((int32_t)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES), invGain_Q30);
            down_scale_Q30 = silk_max_32(silk_RSHIFT((int32_t)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES), down_scale_Q30);
            down_scale_Q30 = silk_LSHIFT(down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES);

            rand_Gain_Q15 = silk_RSHIFT(silk_SMULWB(down_scale_Q30, rand_Gain_Q15), 14);
        }
    }

    rand_seed = psPLC->rand_seed;
    lag = silk_RSHIFT_ROUND(psPLC->pitchL_Q8, 8);
    sLTP_buf_idx = psDec->ltp_mem_length;

    /* Rewhiten LTP state */
    idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
    assert(idx > 0);
    silk_LPC_analysis_filter(&sLTP[idx], &psDec->outBuf[idx], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order);
    /* Scale LTP state */
    inv_gain_Q30 = silk_INVERSE32_varQ(psPLC->prevGain_Q16[1], 46);
    inv_gain_Q30 = silk_min(inv_gain_Q30, silk_int32_MAX >> 1);
    for (i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++) { sLTP_Q14[i] = silk_SMULWB(inv_gain_Q30, sLTP[i]); }

    /***************************/
    /* LTP synthesis filtering */
    /***************************/
    for (k = 0; k < psDec->nb_subfr; k++) {
        /* Set up pointer */
        pred_lag_ptr = &sLTP_Q14[sLTP_buf_idx - lag + LTP_ORDER / 2];
        for (i = 0; i < psDec->subfr_length; i++) {
            /* Unrolled loop */
            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
            LTP_pred_Q12 = 2;
            LTP_pred_Q12 = silk_SMLAWB(LTP_pred_Q12, pred_lag_ptr[0], B_Q14[0]);
            LTP_pred_Q12 = silk_SMLAWB(LTP_pred_Q12, pred_lag_ptr[-1], B_Q14[1]);
            LTP_pred_Q12 = silk_SMLAWB(LTP_pred_Q12, pred_lag_ptr[-2], B_Q14[2]);
            LTP_pred_Q12 = silk_SMLAWB(LTP_pred_Q12, pred_lag_ptr[-3], B_Q14[3]);
            LTP_pred_Q12 = silk_SMLAWB(LTP_pred_Q12, pred_lag_ptr[-4], B_Q14[4]);
            pred_lag_ptr++;

            /* Generate LPC excitation */
            rand_seed = silk_RAND(rand_seed);
            idx = silk_RSHIFT(rand_seed, 25) & RAND_BUF_MASK;
            sLTP_Q14[sLTP_buf_idx] = silk_LSHIFT32(silk_SMLAWB(LTP_pred_Q12, rand_ptr[idx], rand_scale_Q14), 2);
            sLTP_buf_idx++;
        }

        /* Gradually reduce LTP gain */
        for (j = 0; j < LTP_ORDER; j++) { B_Q14[j] = silk_RSHIFT(silk_SMULBB(harm_Gain_Q15, B_Q14[j]), 15); }
        if (psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY) {
            /* Gradually reduce excitation gain */
            rand_scale_Q14 = silk_RSHIFT(silk_SMULBB(rand_scale_Q14, rand_Gain_Q15), 15);
        }

        /* Slowly increase pitch lag */
        psPLC->pitchL_Q8 = silk_SMLAWB(psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16);
        psPLC->pitchL_Q8 = silk_min_32(psPLC->pitchL_Q8, silk_LSHIFT(silk_SMULBB(MAX_PITCH_LAG_MS, psDec->fs_kHz), 8));
        lag = silk_RSHIFT_ROUND(psPLC->pitchL_Q8, 8);
    }

    /***************************/
    /* LPC synthesis filtering */
    /***************************/
    sLPC_Q14_ptr = &sLTP_Q14[psDec->ltp_mem_length - MAX_LPC_ORDER];

    /* Copy LPC state */
    memcpy(sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof(int32_t));

    assert(psDec->LPC_order >= 10); /* check that unrolling works */
    for (i = 0; i < psDec->frame_length; i++) {
        /* partly unrolled */
        /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
        LPC_pred_Q10 = silk_RSHIFT(psDec->LPC_order, 1);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 1], A_Q12[0]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 2], A_Q12[1]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 3], A_Q12[2]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 4], A_Q12[3]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 5], A_Q12[4]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 6], A_Q12[5]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 7], A_Q12[6]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 8], A_Q12[7]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 9], A_Q12[8]);
        LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - 10], A_Q12[9]);
        for (j = 10; j < psDec->LPC_order; j++) { LPC_pred_Q10 = silk_SMLAWB(LPC_pred_Q10, sLPC_Q14_ptr[MAX_LPC_ORDER + i - j - 1], A_Q12[j]); }

        /* Add prediction to LPC excitation */
        sLPC_Q14_ptr[MAX_LPC_ORDER + i] = silk_ADD_SAT32(sLPC_Q14_ptr[MAX_LPC_ORDER + i], silk_LSHIFT_SAT32(LPC_pred_Q10, 4));

        /* Scale with Gain */
        frame[i] = (int16_t)silk_SAT16(silk_SAT16(silk_RSHIFT_ROUND(silk_SMULWW(sLPC_Q14_ptr[MAX_LPC_ORDER + i], prevGain_Q10[1]), 8)));
    }

    /* Save LPC state */
    memcpy(psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[psDec->frame_length], MAX_LPC_ORDER * sizeof(int32_t));

    /**************************************/
    /* Update states                      */
    /**************************************/
    psPLC->rand_seed = rand_seed;
    psPLC->randScale_Q14 = rand_scale_Q14;
    for (i = 0; i < MAX_NB_SUBFR; i++) { psDecCtrl->pitchL[i] = lag; }

    free(sLTP_Q14);
    free(sLTP);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Glues concealed frames with new good received frames */
void silk_PLC_glue_frames(silk_decoder_state* psDec,   /* I/O decoder state        */
                          int16_t             frame[], /* I/O signal               */
                          int32_t             length   /* I length of signal       */
) {
    int32_t          i, energy_shift;
    int32_t          energy;
    silk_PLC_struct* psPLC;
    psPLC = &psDec->sPLC;

    if (psDec->lossCnt) {
        /* Calculate energy in concealed residual */
        silk_sum_sqr_shift(&psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length);

        psPLC->last_frame_lost = 1;
    } else {
        if (psDec->sPLC.last_frame_lost) {
            /* Calculate residual in decoded signal if last frame was lost */
            silk_sum_sqr_shift(&energy, &energy_shift, frame, length);

            /* Normalize energies */
            if (energy_shift > psPLC->conc_energy_shift) {
                psPLC->conc_energy = silk_RSHIFT(psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift);
            } else if (energy_shift < psPLC->conc_energy_shift) {
                energy = silk_RSHIFT(energy, psPLC->conc_energy_shift - energy_shift);
            }

            /* Fade in the energy difference */
            if (energy > psPLC->conc_energy) {
                int32_t frac_Q24, LZ;
                int32_t gain_Q16, slope_Q16;

                LZ = silk_CLZ32(psPLC->conc_energy);
                LZ = LZ - 1;
                psPLC->conc_energy = silk_LSHIFT(psPLC->conc_energy, LZ);
                energy = silk_RSHIFT(energy, silk_max_32(24 - LZ, 0));

                frac_Q24 = silk_DIV32(psPLC->conc_energy, silk_max(energy, 1));

                gain_Q16 = silk_LSHIFT(silk_SQRT_APPROX(frac_Q24), 4);
                slope_Q16 = silk_DIV32_16(((int32_t)1 << 16) - gain_Q16, length);
                /* Make slope 4x steeper to avoid missing onsets after DTX */
                slope_Q16 = silk_LSHIFT(slope_Q16, 2);

                for (i = 0; i < length; i++) {
                    frame[i] = silk_SMULWB(gain_Q16, frame[i]);
                    gain_Q16 += slope_Q16;
                    if (gain_Q16 > (int32_t)1 << 16) { break; }
                }
            }
        }
        psPLC->last_frame_lost = 0;
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Downsample by a factor 2 */
void silk_resampler_down2(int32_t*       S,    /* I/O  State vector [ 2 ]                                          */
                          int16_t*       out,  /* O    Output signal [ floor(len/2) ]                              */
                          const int16_t* in,   /* I    Input signal [ len ]                                        */
                          int32_t        inLen /* I    Number of input samples                                     */
) {
    int32_t k, len2 = silk_RSHIFT32(inLen, 1);
    int32_t in32, out32, Y, X;

    assert(silk_resampler_down2_0 > 0);
    assert(silk_resampler_down2_1 < 0);

    /* Internal variables and state are in Q10 format */
    for (k = 0; k < len2; k++) {
        /* Convert to Q10 */
        in32 = silk_LSHIFT((int32_t)in[2 * k], 10);

        /* All-pass section for even input sample */
        Y = silk_SUB32(in32, S[0]);
        X = silk_SMLAWB(Y, Y, silk_resampler_down2_1);
        out32 = S[0] + X;
        S[0] = in32 + X;

        /* Convert to Q10 */
        in32 = silk_LSHIFT((int32_t)in[2 * k + 1], 10);

        /* All-pass section for odd input sample, and add to output of previous section */
        Y = silk_SUB32(in32, S[1]);
        X = silk_SMULWB(Y, silk_resampler_down2_0);
        out32 = out32 + S[1];
        out32 = out32 + X;
        S[1] = in32 + X;

        /* Add, convert back to int16 and store to output */
        out[k] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(out32, 11));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Second order AR filter with single delay elements */
void silk_resampler_private_AR2(int32_t       S[],      /* I/O  State vector [ 2 ]          */
                                int32_t       out_Q8[], /* O    Output signal               */
                                const int16_t in[],     /* I    Input signal                */
                                const int16_t A_Q14[],  /* I    AR coefficients, Q14        */
                                int32_t       len       /* I    Signal length               */
) {
    int32_t k;
    int32_t out32;

    for (k = 0; k < len; k++) {
        out32 = silk_ADD_LSHIFT32(S[0], (int32_t)in[k], 8);
        out_Q8[k] = out32;
        out32 = silk_LSHIFT(out32, 2);
        S[0] = silk_SMLAWB(S[1], out32, A_Q14[0]);
        S[1] = silk_SMULWB(out32, A_Q14[1]);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

int16_t* silk_resampler_private_down_FIR_INTERPOL(int16_t* out, int32_t* buf, const int16_t* FIR_Coefs, int32_t FIR_Order, int32_t FIR_Fracs, int32_t max_index_Q16, int32_t index_increment_Q16) {
    int32_t        index_Q16, res_Q6;
    int32_t*       buf_ptr;
    int32_t        interpol_ind;
    const int16_t* interpol_ptr;

    switch (FIR_Order) {
        case RESAMPLER_DOWN_ORDER_FIR0:
            for (index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16) {
                /* Integer part gives pointer to buffered input */
                buf_ptr = buf + silk_RSHIFT(index_Q16, 16);

                /* Fractional part gives interpolation coefficients */
                interpol_ind = silk_SMULWB(index_Q16 & 0xFFFF, FIR_Fracs);

                /* Inner product */
                interpol_ptr = &FIR_Coefs[RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind];
                res_Q6 = silk_SMULWB(buf_ptr[0], interpol_ptr[0]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[1], interpol_ptr[1]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[2], interpol_ptr[2]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[3], interpol_ptr[3]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[4], interpol_ptr[4]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[5], interpol_ptr[5]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[6], interpol_ptr[6]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[7], interpol_ptr[7]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[8], interpol_ptr[8]);
                interpol_ptr = &FIR_Coefs[RESAMPLER_DOWN_ORDER_FIR0 / 2 * (FIR_Fracs - 1 - interpol_ind)];
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[17], interpol_ptr[0]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[16], interpol_ptr[1]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[15], interpol_ptr[2]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[14], interpol_ptr[3]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[13], interpol_ptr[4]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[12], interpol_ptr[5]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[11], interpol_ptr[6]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[10], interpol_ptr[7]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[9], interpol_ptr[8]);

                /* Scale down, saturate and store in output array */
                *out++ = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(res_Q6, 6));
            }
            break;
        case RESAMPLER_DOWN_ORDER_FIR1:
            for (index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16) {
                /* Integer part gives pointer to buffered input */
                buf_ptr = buf + silk_RSHIFT(index_Q16, 16);

                /* Inner product */
                res_Q6 = silk_SMULWB(buf_ptr[0] + buf_ptr[23], FIR_Coefs[0]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[1] + buf_ptr[22], FIR_Coefs[1]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[2] + buf_ptr[21], FIR_Coefs[2]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[3] + buf_ptr[20], FIR_Coefs[3]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[4] + buf_ptr[19], FIR_Coefs[4]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[5] + buf_ptr[18], FIR_Coefs[5]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[6] + buf_ptr[17], FIR_Coefs[6]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[7] + buf_ptr[16], FIR_Coefs[7]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[8] + buf_ptr[15], FIR_Coefs[8]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[9] + buf_ptr[14], FIR_Coefs[9]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[10] + buf_ptr[13], FIR_Coefs[10]);
                res_Q6 = silk_SMLAWB(res_Q6, buf_ptr[11] + buf_ptr[12], FIR_Coefs[11]);

                /* Scale down, saturate and store in output array */
                *out++ = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(res_Q6, 6));
            }
            break;
        case RESAMPLER_DOWN_ORDER_FIR2:
            for (index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16) {
                /* Integer part gives pointer to buffered input */
                buf_ptr = buf + silk_RSHIFT(index_Q16, 16);

                /* Inner product */
                res_Q6 = silk_SMULWB(silk_ADD32(buf_ptr[0], buf_ptr[35]), FIR_Coefs[0]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[1], buf_ptr[34]), FIR_Coefs[1]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[2], buf_ptr[33]), FIR_Coefs[2]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[3], buf_ptr[32]), FIR_Coefs[3]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[4], buf_ptr[31]), FIR_Coefs[4]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[5], buf_ptr[30]), FIR_Coefs[5]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[6], buf_ptr[29]), FIR_Coefs[6]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[7], buf_ptr[28]), FIR_Coefs[7]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[8], buf_ptr[27]), FIR_Coefs[8]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[9], buf_ptr[26]), FIR_Coefs[9]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[10], buf_ptr[25]), FIR_Coefs[10]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[11], buf_ptr[24]), FIR_Coefs[11]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[12], buf_ptr[23]), FIR_Coefs[12]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[13], buf_ptr[22]), FIR_Coefs[13]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[14], buf_ptr[21]), FIR_Coefs[14]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[15], buf_ptr[20]), FIR_Coefs[15]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[16], buf_ptr[19]), FIR_Coefs[16]);
                res_Q6 = silk_SMLAWB(res_Q6, silk_ADD32(buf_ptr[17], buf_ptr[18]), FIR_Coefs[17]);

                /* Scale down, saturate and store in output array */
                *out++ = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(res_Q6, 6));
            }
            break;
        default: {
            ;
        }
    }
    return out;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Resample with a 2nd order AR filter followed by FIR interpolation */
void silk_resampler_private_down_FIR(void*         SS,    /* I/O  Resampler state             */
                                     int16_t       out[], /* O    Output signal               */
                                     const int16_t in[],  /* I    Input signal                */
                                     int32_t       inLen  /* I    Number of input samples     */
) {
    silk_resampler_state_struct* S = (silk_resampler_state_struct*)SS;
    int32_t                      nSamplesIn;
    int32_t                      max_index_Q16, index_increment_Q16;
    int32_t* buf = NULL;
    const int16_t* FIR_Coefs;

    //ALLOC(buf, S->batchSize + S->FIR_Order, int32_t);
    buf = (int32_t*)__malloc_heap_psram((S->batchSize + S->FIR_Order) * sizeof(int32_t));

    /* Copy buffered samples to start of buffer */
    memcpy(buf, S->sFIR.i32, S->FIR_Order * sizeof(int32_t));

    FIR_Coefs = &S->Coefs[2];

    /* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
    while (1) {
        nSamplesIn = silk_min(inLen, S->batchSize);

        /* Second-order AR filter (output in Q8) */
        silk_resampler_private_AR2(S->sIIR, &buf[S->FIR_Order], in, S->Coefs, nSamplesIn);

        max_index_Q16 = silk_LSHIFT32(nSamplesIn, 16);

        /* Interpolate filtered signal */
        out = silk_resampler_private_down_FIR_INTERPOL(out, buf, FIR_Coefs, S->FIR_Order, S->FIR_Fracs, max_index_Q16, index_increment_Q16);

        in += nSamplesIn;
        inLen -= nSamplesIn;

        if (inLen > 1) {
            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
            memcpy(buf, &buf[nSamplesIn], S->FIR_Order * sizeof(int32_t));
        } else {
            break;
        }
    }

    /* Copy last part of filtered signal to the state for the next call */
    memcpy(S->sFIR.i32, &buf[nSamplesIn], S->FIR_Order * sizeof(int32_t));

    free (buf);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

int16_t* silk_resampler_private_IIR_FIR_INTERPOL(int16_t* out, int16_t* buf, int32_t max_index_Q16, int32_t index_increment_Q16) {
    int32_t  index_Q16, res_Q15;
    int16_t* buf_ptr;
    int32_t  table_index;

    /* Interpolate upsampled signal and store in output array */
    for (index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16) {
        table_index = silk_SMULWB(index_Q16 & 0xFFFF, 12);
        buf_ptr = &buf[index_Q16 >> 16];

        res_Q15 = silk_SMULBB(buf_ptr[0], silk_resampler_frac_FIR_12[table_index][0]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[1], silk_resampler_frac_FIR_12[table_index][1]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[2], silk_resampler_frac_FIR_12[table_index][2]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[3], silk_resampler_frac_FIR_12[table_index][3]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[4], silk_resampler_frac_FIR_12[11 - table_index][3]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[5], silk_resampler_frac_FIR_12[11 - table_index][2]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[6], silk_resampler_frac_FIR_12[11 - table_index][1]);
        res_Q15 = silk_SMLABB(res_Q15, buf_ptr[7], silk_resampler_frac_FIR_12[11 - table_index][0]);
        *out++ = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(res_Q15, 15));
    }
    return out;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */
void silk_resampler_private_IIR_FIR(void*         SS,    /* I/O  Resampler state             */
                                    int16_t       out[], /* O    Output signal               */
                                    const int16_t in[],  /* I    Input signal                */
                                    int32_t       inLen  /* I    Number of input samples     */
) {
    silk_resampler_state_struct* S = (silk_resampler_state_struct*)SS;
    int32_t                      nSamplesIn;
    int32_t                      max_index_Q16, index_increment_Q16;
    int16_t* buf = NULL;

    //ALLOC(buf, 2 * S->batchSize + RESAMPLER_ORDER_FIR_12, int16_t);
    buf = (int16_t*)__malloc_heap_psram((2 * S->batchSize + RESAMPLER_ORDER_FIR_12) * sizeof(int16_t));

    /* Copy buffered samples to start of buffer */
    memcpy(buf, S->sFIR.i16, RESAMPLER_ORDER_FIR_12 * sizeof(int16_t));

    /* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
    while (1) {
        nSamplesIn = silk_min(inLen, S->batchSize);

        /* Upsample 2x */
        silk_resampler_private_up2_HQ(S->sIIR, &buf[RESAMPLER_ORDER_FIR_12], in, nSamplesIn);

        max_index_Q16 = silk_LSHIFT32(nSamplesIn, 16 + 1); /* + 1 because 2x upsampling */
        out = silk_resampler_private_IIR_FIR_INTERPOL(out, buf, max_index_Q16, index_increment_Q16);
        in += nSamplesIn;
        inLen -= nSamplesIn;

        if (inLen > 0) {
            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
            memcpy(buf, &buf[nSamplesIn << 1], RESAMPLER_ORDER_FIR_12 * sizeof(int16_t));
        } else {
            break;
        }
    }

    /* Copy last part of filtered signal to the state for the next call */
    memcpy(S->sFIR.i16, &buf[nSamplesIn << 1], RESAMPLER_ORDER_FIR_12 * sizeof(int16_t));

    free (buf);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Upsample by a factor 2, high quality. Uses 2nd order allpass filters for the 2x upsampling, followed by a      */
/* notch filter just above Nyquist.                                         */
void silk_resampler_private_up2_HQ(int32_t*       S,   /* I/O  Resampler state [ 6 ]       */
                                   int16_t*       out, /* O    Output signal [ 2 * len ]   */
                                   const int16_t* in,  /* I    Input signal [ len ]        */
                                   int32_t        len  /* I    Number of input samples     */
) {
    int32_t k;
    int32_t in32, out32_1, out32_2, Y, X;

    assert(silk_resampler_up2_hq_0[0] > 0);
    assert(silk_resampler_up2_hq_0[1] > 0);
    assert(silk_resampler_up2_hq_0[2] < 0);
    assert(silk_resampler_up2_hq_1[0] > 0);
    assert(silk_resampler_up2_hq_1[1] > 0);
    assert(silk_resampler_up2_hq_1[2] < 0);

    /* Internal variables and state are in Q10 format */
    for (k = 0; k < len; k++) {
        /* Convert to Q10 */
        in32 = silk_LSHIFT((int32_t)in[k], 10);

        /* First all-pass section for even output sample */
        Y = silk_SUB32(in32, S[0]);
        X = silk_SMULWB(Y, silk_resampler_up2_hq_0[0]);
        out32_1 = silk_ADD32(S[0], X);
        S[0] = silk_ADD32(in32, X);

        /* Second all-pass section for even output sample */
        Y = silk_SUB32(out32_1, S[1]);
        X = silk_SMULWB(Y, silk_resampler_up2_hq_0[1]);
        out32_2 = silk_ADD32(S[1], X);
        S[1] = silk_ADD32(out32_1, X);

        /* Third all-pass section for even output sample */
        Y = silk_SUB32(out32_2, S[2]);
        X = silk_SMLAWB(Y, Y, silk_resampler_up2_hq_0[2]);
        out32_1 = silk_ADD32(S[2], X);
        S[2] = silk_ADD32(out32_2, X);

        /* Apply gain in Q15, convert back to int16 and store to output */
        out[2 * k] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(out32_1, 10));

        /* First all-pass section for odd output sample */
        Y = silk_SUB32(in32, S[3]);
        X = silk_SMULWB(Y, silk_resampler_up2_hq_1[0]);
        out32_1 = silk_ADD32(S[3], X);
        S[3] = silk_ADD32(in32, X);

        /* Second all-pass section for odd output sample */
        Y = silk_SUB32(out32_1, S[4]);
        X = silk_SMULWB(Y, silk_resampler_up2_hq_1[1]);
        out32_2 = silk_ADD32(S[4], X);
        S[4] = silk_ADD32(out32_1, X);

        /* Third all-pass section for odd output sample */
        Y = silk_SUB32(out32_2, S[5]);
        X = silk_SMLAWB(Y, Y, silk_resampler_up2_hq_1[2]);
        out32_1 = silk_ADD32(S[5], X);
        S[5] = silk_ADD32(out32_2, X);

        /* Apply gain in Q15, convert back to int16 and store to output */
        out[2 * k + 1] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(out32_1, 10));
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void silk_resampler_private_up2_HQ_wrapper(void*          SS,  /* I/O  Resampler state (unused)    */
                                           int16_t*       out, /* O    Output signal [ 2 * len ]   */
                                           const int16_t* in,  /* I    Input signal [ len ]        */
                                           int32_t        len  /* I    Number of input samples     */
) {
    silk_resampler_state_struct* S = (silk_resampler_state_struct*)SS;
    silk_resampler_private_up2_HQ(S->sIIR, out, in, len);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Initialize/reset the resampler state for a given pair of input/output sampling rates */
int32_t silk_resampler_init(silk_resampler_state_struct* S,         /* I/O  Resampler state */
                            int32_t                      Fs_Hz_in,  /* I    Input sampling rate (Hz)                                    */
                            int32_t                      Fs_Hz_out, /* I    Output sampling rate (Hz)                                   */
                            int32_t                      forEnc     /* I    If 1: encoder; if 0: decoder                                */
) {
    int32_t up2x;

    /* Clear state */
    memset(S, 0, sizeof(silk_resampler_state_struct));

    /* Input checking */
    if (forEnc) {
        if ((Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000) || (Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000)) { return -1; }
        S->inputDelay = delay_matrix_enc[rateID(Fs_Hz_in)][rateID(Fs_Hz_out)];
    } else {
        if ((Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000) || (Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000)) { return -1; }
        S->inputDelay = delay_matrix_dec[rateID(Fs_Hz_in)][rateID(Fs_Hz_out)];
    }

    S->Fs_in_kHz = silk_DIV32_16(Fs_Hz_in, 1000);
    S->Fs_out_kHz = silk_DIV32_16(Fs_Hz_out, 1000);

    /* Number of samples processed per batch */
    S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS;

    /* Find resampler with the right sampling ratio */
    up2x = 0;
    if (Fs_Hz_out > Fs_Hz_in) {
        /* Upsample */
        if (Fs_Hz_out == silk_MUL(Fs_Hz_in, 2)) { /* Fs_out : Fs_in = 2 : 1 */
            /* Special case: directly use 2x upsampler */
            S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper;
        } else {
            /* Default resampler */
            S->resampler_function = USE_silk_resampler_private_IIR_FIR;
            up2x = 1;
        }
    } else if (Fs_Hz_out < Fs_Hz_in) {
        /* Downsample */
        S->resampler_function = USE_silk_resampler_private_down_FIR;
        if (silk_MUL(Fs_Hz_out, 4) == silk_MUL(Fs_Hz_in, 3)) { /* Fs_out : Fs_in = 3 : 4 */
            S->FIR_Fracs = 3;
            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
            S->Coefs = silk_Resampler_3_4_COEFS;
        } else if (silk_MUL(Fs_Hz_out, 3) == silk_MUL(Fs_Hz_in, 2)) { /* Fs_out : Fs_in = 2 : 3 */
            S->FIR_Fracs = 2;
            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
            S->Coefs = silk_Resampler_2_3_COEFS;
        } else if (silk_MUL(Fs_Hz_out, 2) == Fs_Hz_in) { /* Fs_out : Fs_in = 1 : 2 */
            S->FIR_Fracs = 1;
            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1;
            S->Coefs = silk_Resampler_1_2_COEFS;
        } else if (silk_MUL(Fs_Hz_out, 3) == Fs_Hz_in) { /* Fs_out : Fs_in = 1 : 3 */
            S->FIR_Fracs = 1;
            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
            S->Coefs = silk_Resampler_1_3_COEFS;
        } else if (silk_MUL(Fs_Hz_out, 4) == Fs_Hz_in) { /* Fs_out : Fs_in = 1 : 4 */
            S->FIR_Fracs = 1;
            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
            S->Coefs = silk_Resampler_1_4_COEFS;
        } else if (silk_MUL(Fs_Hz_out, 6) == Fs_Hz_in) { /* Fs_out : Fs_in = 1 : 6 */
            S->FIR_Fracs = 1;
            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
            S->Coefs = silk_Resampler_1_6_COEFS;
        } else {
            /* None available */
            return -1;
        }
    } else {
        /* Input and output sampling rates are equal: copy */
        S->resampler_function = USE_silk_resampler_copy;
    }

    /* Ratio of input/output samples */
    S->invRatio_Q16 = silk_LSHIFT32(silk_DIV32(silk_LSHIFT32(Fs_Hz_in, 14 + up2x), Fs_Hz_out), 2);
    /* Make sure the ratio is rounded up */
    while (silk_SMULWW(S->invRatio_Q16, Fs_Hz_out) < silk_LSHIFT32(Fs_Hz_in, up2x)) { S->invRatio_Q16++; }

    return 0;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Resampler: convert from one sampling rate to another Input and output sampling rate are at most 48000 Hz  */
int32_t silk_resampler(silk_resampler_state_struct* S,     /* I/O  Resampler state */
                       int16_t                      out[], /* O    Output signal                                               */
                       const int16_t                in[],  /* I    Input signal                                                */
                       int32_t                      inLen  /* I    Number of input samples                                     */
) {
    int32_t nSamples;

    /* Need at least 1 ms of input data */
    assert(inLen >= S->Fs_in_kHz);
    /* Delay can't exceed the 1 ms of buffering */
    assert(S->inputDelay <= S->Fs_in_kHz);

    nSamples = S->Fs_in_kHz - S->inputDelay;

    /* Copy to delay buffer */
    memcpy(&S->delayBuf[S->inputDelay], in, nSamples * sizeof(int16_t));

    switch (S->resampler_function) {
        case USE_silk_resampler_private_up2_HQ_wrapper:
            silk_resampler_private_up2_HQ_wrapper(S, out, S->delayBuf, S->Fs_in_kHz);
            silk_resampler_private_up2_HQ_wrapper(S, &out[S->Fs_out_kHz], &in[nSamples], inLen - S->Fs_in_kHz);
            break;
        case USE_silk_resampler_private_IIR_FIR:
            silk_resampler_private_IIR_FIR(S, out, S->delayBuf, S->Fs_in_kHz);
            silk_resampler_private_IIR_FIR(S, &out[S->Fs_out_kHz], &in[nSamples], inLen - S->Fs_in_kHz);
            break;
        case USE_silk_resampler_private_down_FIR:
            silk_resampler_private_down_FIR(S, out, S->delayBuf, S->Fs_in_kHz);
            silk_resampler_private_down_FIR(S, &out[S->Fs_out_kHz], &in[nSamples], inLen - S->Fs_in_kHz);
            break;
        default: memcpy(out, S->delayBuf, S->Fs_in_kHz * sizeof(int16_t)); memcpy(&out[S->Fs_out_kHz], &in[nSamples], (inLen - S->Fs_in_kHz) * sizeof(int16_t));
    }

    /* Copy to delay buffer */
    memcpy(S->delayBuf, &in[inLen - S->inputDelay], S->inputDelay * sizeof(int16_t));

    return 0;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int32_t silk_sigm_Q15(int32_t in_Q5) {
    int32_t ind;
    if (in_Q5 < 0) {
        /* Negative input */
        in_Q5 = -in_Q5;
        if (in_Q5 >= 6 * 32) {
            return 0; /* Clip */
        } else {
            /* Linear interpolation of look up table */
            ind = silk_RSHIFT(in_Q5, 5);
            return (sigm_LUT_neg_Q15[ind] - silk_SMULBB(sigm_LUT_slope_Q10[ind], in_Q5 & 0x1F));
        }
    } else {
        /* Positive input */
        if (in_Q5 >= 6 * 32) {
            return 32767; /* clip */
        } else {
            /* Linear interpolation of look up table */
            ind = silk_RSHIFT(in_Q5, 5);
            return (sigm_LUT_pos_Q15[ind] + silk_SMULBB(sigm_LUT_slope_Q10[ind], in_Q5 & 0x1F));
        }
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// silk_insertion_sort_increasing(Unsorted / Sorted vector, Index vector for the sorted elements, Vector length, Number of correctly sorted positions )
void silk_insertion_sort_increasing(int32_t* a, int32_t* idx, const int32_t L, const int32_t K) {
    int32_t value;
    int32_t i, j;

    /* Safety checks */
    assert(K > 0);
    assert(L > 0);
    assert(L >= K);

    /* Write start indices in index vector */
    for (i = 0; i < K; i++) { idx[i] = i; }

    /* Sort vector elements by value, increasing order */
    for (i = 1; i < K; i++) {
        value = a[i];
        for (j = i - 1; (j >= 0) && (value < a[j]); j--) {
            a[j + 1] = a[j];     /* Shift value */
            idx[j + 1] = idx[j]; /* Shift index */
        }
        a[j + 1] = value; /* Write value */
        idx[j + 1] = i;   /* Write index */
    }

    /* If less than L values are asked for, check the remaining values, but only spend CPU to ensure that the K first values are correct */
    for (i = K; i < L; i++) {
        value = a[i];
        if (value < a[K - 1]) {
            for (j = K - 2; (j >= 0) && (value < a[j]); j--) {
                a[j + 1] = a[j];     /* Shift value */
                idx[j + 1] = idx[j]; /* Shift index */
            }
            a[j + 1] = value; /* Write value */
            idx[j + 1] = i;   /* Write index */
        }
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* This function is only used by the fixed-point build */
void silk_insertion_sort_decreasing_int16(int16_t*      a,   /* I/O   Unsorted / Sorted vector      */
                                          int32_t*      idx, /* O     Index vector for the sorted elements    */
                                          const int32_t L,   /* I     Vector length */
                                          const int32_t K    /* I     Number of correctly sorted positions  */
) {
    int32_t i, j;
    int32_t value;

    /* Safety checks */
    assert(K > 0);
    assert(L > 0);
    assert(L >= K);

    /* Write start indices in index vector */
    for (i = 0; i < K; i++) { idx[i] = i; }

    /* Sort vector elements by value, decreasing order */
    for (i = 1; i < K; i++) {
        value = a[i];
        for (j = i - 1; (j >= 0) && (value > a[j]); j--) {
            a[j + 1] = a[j];     /* Shift value */
            idx[j + 1] = idx[j]; /* Shift index */
        }
        a[j + 1] = value; /* Write value */
        idx[j + 1] = i;   /* Write index */
    }

    /* If less than L values are asked for, check the remaining values, */
    /* but only spend CPU to ensure that the K first values are correct */
    for (i = K; i < L; i++) {
        value = a[i];
        if (value > a[K - 1]) {
            for (j = K - 2; (j >= 0) && (value > a[j]); j--) {
                a[j + 1] = a[j];     /* Shift value */
                idx[j + 1] = idx[j]; /* Shift index */
            }
            a[j + 1] = value; /* Write value */
            idx[j + 1] = i;   /* Write index */
        }
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void silk_insertion_sort_increasing_all_values_int16(int16_t*      a, /* I/O   Unsorted / Sorted vector     */
                                                     const int32_t L  /* I     Vector length */
) {
    int32_t value;
    int32_t i, j;

    /* Safety checks */
    assert(L > 0);

    /* Sort vector elements by value, increasing order */
    for (i = 1; i < L; i++) {
        value = a[i];
        for (j = i - 1; (j >= 0) && (value < a[j]); j--) { a[j + 1] = a[j]; /* Shift value */ }
        a[j + 1] = value; /* Write value */
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Compute number of bits to right shift the sum of squares of a vector */
/* of int16s to make it fit in an int32                                 */
void silk_sum_sqr_shift(int32_t*       energy, /* O   Energy of x, after shifting to the right                     */
                        int32_t*       shift,  /* O   Number of bits right shift applied to energy                 */
                        const int16_t* x,      /* I   Input vector                                                 */
                        int32_t        len     /* I   Length of input vector                                       */
) {
    int32_t  i, shft;
    uint32_t nrg_tmp;
    int32_t  nrg;

    /* Do a first run with the maximum shift we could have. */
    shft = 31 - silk_CLZ32(len);
    /* Let's be conservative with rounding and start with nrg=len. */
    nrg = len;
    for (i = 0; i < len - 1; i += 2) {
        nrg_tmp = silk_SMULBB(x[i], x[i]);
        nrg_tmp = silk_SMLABB_ovflw(nrg_tmp, x[i + 1], x[i + 1]);
        nrg = (int32_t)silk_ADD_RSHIFT_uint(nrg, nrg_tmp, shft);
    }
    if (i < len) {
        /* One sample left to process */
        nrg_tmp = silk_SMULBB(x[i], x[i]);
        nrg = (int32_t)silk_ADD_RSHIFT_uint(nrg, nrg_tmp, shft);
    }
    assert(nrg >= 0);
    /* Make sure the result will fit in a 32-bit signed integer with two bits
       of headroom. */
    shft = silk_max_32(0, shft + 3 - silk_CLZ32(nrg));
    nrg = 0;
    for (i = 0; i < len - 1; i += 2) {
        nrg_tmp = silk_SMULBB(x[i], x[i]);
        nrg_tmp = silk_SMLABB_ovflw(nrg_tmp, x[i + 1], x[i + 1]);
        nrg = (int32_t)silk_ADD_RSHIFT_uint(nrg, nrg_tmp, shft);
    }
    if (i < len) {
        /* One sample left to process */
        nrg_tmp = silk_SMULBB(x[i], x[i]);
        nrg = (int32_t)silk_ADD_RSHIFT_uint(nrg, nrg_tmp, shft);
    }

    assert(nrg >= 0);

    /* Output arguments */
    *shift = shft;
    *energy = nrg;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
void silk_VQ_WMat_EC_c(int8_t*        ind,          /* O    index of best codebook vector               */
                       int32_t*       res_nrg_Q15,  /* O    best residual energy                        */
                       int32_t*       rate_dist_Q8, /* O    best total bitrate                          */
                       int32_t*       gain_Q7,      /* O    sum of absolute LTP coefficients            */
                       const int32_t* XX_Q17,       /* I    correlation matrix                          */
                       const int32_t* xX_Q17,       /* I    correlation vector                          */
                       const int8_t*  cb_Q7,        /* I    codebook                                    */
                       const uint8_t* cb_gain_Q7,   /* I    codebook effective gain                     */
                       const uint8_t* cl_Q5,        /* I    code length for each codebook vector        */
                       const int32_t  subfr_len,    /* I    number of samples per subframe              */
                       const int32_t  max_gain_Q7,  /* I    maximum sum of absolute LTP coefficients    */
                       const int32_t  L             /* I    number of vectors in codebook               */
) {
    int32_t       k, gain_tmp_Q7;
    const int8_t* cb_row_Q7;
    int32_t       neg_xX_Q24[5];
    int32_t       sum1_Q15, sum2_Q24;
    int32_t       bits_res_Q8, bits_tot_Q8;

    /* Negate and convert to new Q domain */
    neg_xX_Q24[0] = -silk_LSHIFT32(xX_Q17[0], 7);
    neg_xX_Q24[1] = -silk_LSHIFT32(xX_Q17[1], 7);
    neg_xX_Q24[2] = -silk_LSHIFT32(xX_Q17[2], 7);
    neg_xX_Q24[3] = -silk_LSHIFT32(xX_Q17[3], 7);
    neg_xX_Q24[4] = -silk_LSHIFT32(xX_Q17[4], 7);

    /* Loop over codebook */
    *rate_dist_Q8 = silk_int32_MAX;
    *res_nrg_Q15 = silk_int32_MAX;
    cb_row_Q7 = cb_Q7;
    /* In things go really bad, at least *ind is set to something safe. */
    *ind = 0;
    for (k = 0; k < L; k++) {
        int32_t penalty;
        gain_tmp_Q7 = cb_gain_Q7[k];
        /* Weighted rate */
        /* Quantization error: 1 - 2 * xX * cb + cb' * XX * cb */
        sum1_Q15 = SILK_FIX_CONST(1.001, 15);

        /* Penalty for too large gain */
        penalty = silk_LSHIFT32(silk_max(silk_SUB32(gain_tmp_Q7, max_gain_Q7), 0), 11);

        /* first row of XX_Q17 */
        sum2_Q24 = silk_MLA(neg_xX_Q24[0], XX_Q17[1], cb_row_Q7[1]);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[2], cb_row_Q7[2]);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[3], cb_row_Q7[3]);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[4], cb_row_Q7[4]);
        sum2_Q24 = silk_LSHIFT32(sum2_Q24, 1);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[0], cb_row_Q7[0]);
        sum1_Q15 = silk_SMLAWB(sum1_Q15, sum2_Q24, cb_row_Q7[0]);

        /* second row of XX_Q17 */
        sum2_Q24 = silk_MLA(neg_xX_Q24[1], XX_Q17[7], cb_row_Q7[2]);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[8], cb_row_Q7[3]);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[9], cb_row_Q7[4]);
        sum2_Q24 = silk_LSHIFT32(sum2_Q24, 1);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[6], cb_row_Q7[1]);
        sum1_Q15 = silk_SMLAWB(sum1_Q15, sum2_Q24, cb_row_Q7[1]);

        /* third row of XX_Q17 */
        sum2_Q24 = silk_MLA(neg_xX_Q24[2], XX_Q17[13], cb_row_Q7[3]);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[14], cb_row_Q7[4]);
        sum2_Q24 = silk_LSHIFT32(sum2_Q24, 1);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[12], cb_row_Q7[2]);
        sum1_Q15 = silk_SMLAWB(sum1_Q15, sum2_Q24, cb_row_Q7[2]);

        /* fourth row of XX_Q17 */
        sum2_Q24 = silk_MLA(neg_xX_Q24[3], XX_Q17[19], cb_row_Q7[4]);
        sum2_Q24 = silk_LSHIFT32(sum2_Q24, 1);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[18], cb_row_Q7[3]);
        sum1_Q15 = silk_SMLAWB(sum1_Q15, sum2_Q24, cb_row_Q7[3]);

        /* last row of XX_Q17 */
        sum2_Q24 = silk_LSHIFT32(neg_xX_Q24[4], 1);
        sum2_Q24 = silk_MLA(sum2_Q24, XX_Q17[24], cb_row_Q7[4]);
        sum1_Q15 = silk_SMLAWB(sum1_Q15, sum2_Q24, cb_row_Q7[4]);

        /* find best */
        if (sum1_Q15 >= 0) {
            /* Translate residual energy to bits using high-rate assumption (6 dB ==> 1 bit/sample) */
            bits_res_Q8 = silk_SMULBB(subfr_len, silk_lin2log(sum1_Q15 + penalty) - (15 << 7));
            /* In the following line we reduce the codelength component by half ("-1"); seems to slghtly improve quality
             */
            bits_tot_Q8 = silk_ADD_LSHIFT32(bits_res_Q8, cl_Q5[k], 3 - 1);
            if (bits_tot_Q8 <= *rate_dist_Q8) {
                *rate_dist_Q8 = bits_tot_Q8;
                *res_nrg_Q15 = sum1_Q15 + penalty;
                *ind = (int8_t)k;
                *gain_Q7 = gain_tmp_Q7;
            }
        }

        /* Go to next cbk vector */
        cb_row_Q7 += LTP_ORDER;
    }
}
//-----------------------------------------------------------------------------------------------------------
/* Find least-squares prediction gain for one signal based on another and quantize it */
int32_t silk_stereo_find_predictor(                                /* O    Returns predictor in Q13                    */
                                   int32_t*      ratio_Q14,        /* O    Ratio of residual and mid energies          */
                                   const int16_t x[],              /* I    Basis signal                                */
                                   const int16_t y[],              /* I    Target signal                               */
                                   int32_t       mid_res_amp_Q0[], /* I/O  Smoothed mid, residual norms                */
                                   int32_t       length,           /* I    Number of samples                           */
                                   int32_t       smooth_coef_Q16   /* I    Smoothing coefficient                       */
) {
    int32_t scale, scale1, scale2;
    int32_t nrgx, nrgy, corr, pred_Q13, pred2_Q10;

    /* Find  predictor */
    silk_sum_sqr_shift(&nrgx, &scale1, x, length);
    silk_sum_sqr_shift(&nrgy, &scale2, y, length);
    scale = silk_max_int(scale1, scale2);
    scale = scale + (scale & 1); /* make even */
    nrgy = silk_RSHIFT32(nrgy, scale - scale2);
    nrgx = silk_RSHIFT32(nrgx, scale - scale1);
    nrgx = silk_max_int(nrgx, 1);
    corr = silk_inner_prod_aligned_scale(x, y, scale, length);
    pred_Q13 = silk_DIV32_varQ(corr, nrgx, 13);
    pred_Q13 = silk_LIMIT(pred_Q13, -(1 << 14), 1 << 14);
    pred2_Q10 = silk_SMULWB(pred_Q13, pred_Q13);

    /* Faster update for signals with large prediction parameters */
    smooth_coef_Q16 = (int32_t)silk_max_int(smooth_coef_Q16, silk_abs(pred2_Q10));

    /* Smoothed mid and residual norms */
    assert(smooth_coef_Q16 < 32768);
    scale = silk_RSHIFT(scale, 1);
    mid_res_amp_Q0[0] = silk_SMLAWB(mid_res_amp_Q0[0], silk_LSHIFT(silk_SQRT_APPROX(nrgx), scale) - mid_res_amp_Q0[0], smooth_coef_Q16);
    /* Residual energy = nrgy - 2 * pred * corr + pred^2 * nrgx */
    nrgy = silk_SUB_LSHIFT32(nrgy, silk_SMULWB(corr, pred_Q13), 3 + 1);
    nrgy = silk_ADD_LSHIFT32(nrgy, silk_SMULWB(nrgx, pred2_Q10), 6);
    mid_res_amp_Q0[1] = silk_SMLAWB(mid_res_amp_Q0[1], silk_LSHIFT(silk_SQRT_APPROX(nrgy), scale) - mid_res_amp_Q0[1], smooth_coef_Q16);

    /* Ratio of smoothed residual and mid norms */
    *ratio_Q14 = silk_DIV32_varQ(mid_res_amp_Q0[1], silk_max(mid_res_amp_Q0[0], 1), 14);
    *ratio_Q14 = silk_LIMIT(*ratio_Q14, 0, 32767);

    return pred_Q13;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Convert adaptive Mid/Side representation to Left/Right stereo signal */
void silk_stereo_MS_to_LR(stereo_dec_state* state,       /* I/O  State                                       */
                          int16_t           x1[],        /* I/O  Left input signal, becomes mid signal       */
                          int16_t           x2[],        /* I/O  Right input signal, becomes side signal     */
                          const int32_t     pred_Q13[],  /* I    Predictors                                  */
                          int32_t           fs_kHz,      /* I    Samples rate (kHz)                          */
                          int32_t           frame_length /* I    Number of samples                           */
) {
    int32_t n, denom_Q16, delta0_Q13, delta1_Q13;
    int32_t sum, diff, pred0_Q13, pred1_Q13;

    /* Buffering */
    memcpy(x1, state->sMid, 2 * sizeof(int16_t));
    memcpy(x2, state->sSide, 2 * sizeof(int16_t));
    memcpy(state->sMid, &x1[frame_length], 2 * sizeof(int16_t));
    memcpy(state->sSide, &x2[frame_length], 2 * sizeof(int16_t));

    /* Interpolate predictors and add prediction to side channel */
    pred0_Q13 = state->pred_prev_Q13[0];
    pred1_Q13 = state->pred_prev_Q13[1];
    denom_Q16 = silk_DIV32_16((int32_t)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz);
    delta0_Q13 = silk_RSHIFT_ROUND(silk_SMULBB(pred_Q13[0] - state->pred_prev_Q13[0], denom_Q16), 16);
    delta1_Q13 = silk_RSHIFT_ROUND(silk_SMULBB(pred_Q13[1] - state->pred_prev_Q13[1], denom_Q16), 16);
    for (n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++) {
        pred0_Q13 += delta0_Q13;
        pred1_Q13 += delta1_Q13;
        sum = silk_LSHIFT(silk_ADD_LSHIFT(x1[n] + x1[n + 2], x1[n + 1], 1), 9); /* Q11 */
        sum = silk_SMLAWB(silk_LSHIFT((int32_t)x2[n + 1], 8), sum, pred0_Q13);  /* Q8  */
        sum = silk_SMLAWB(sum, silk_LSHIFT((int32_t)x1[n + 1], 11), pred1_Q13); /* Q8  */
        x2[n + 1] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(sum, 8));
    }
    pred0_Q13 = pred_Q13[0];
    pred1_Q13 = pred_Q13[1];
    for (n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++) {
        sum = silk_LSHIFT(silk_ADD_LSHIFT(x1[n] + x1[n + 2], x1[n + 1], 1), 9); /* Q11 */
        sum = silk_SMLAWB(silk_LSHIFT((int32_t)x2[n + 1], 8), sum, pred0_Q13);  /* Q8  */
        sum = silk_SMLAWB(sum, silk_LSHIFT((int32_t)x1[n + 1], 11), pred1_Q13); /* Q8  */
        x2[n + 1] = (int16_t)silk_SAT16(silk_RSHIFT_ROUND(sum, 8));
    }
    state->pred_prev_Q13[0] = pred_Q13[0];
    state->pred_prev_Q13[1] = pred_Q13[1];

    /* Convert to left/right signals */
    for (n = 0; n < frame_length; n++) {
        sum = x1[n + 1] + (int32_t)x2[n + 1];
        diff = x1[n + 1] - (int32_t)x2[n + 1];
        x1[n + 1] = (int16_t)silk_SAT16(sum);
        x2[n + 1] = (int16_t)silk_SAT16(diff);
    }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Initialization of the Silk VAD */
int32_t silk_VAD_Init(                           /* O    Return value, 0 if success                  */
                      silk_VAD_state* psSilk_VAD /* I/O  Pointer to Silk VAD state                   */
) {
    int32_t b, ret = 0;

    /* reset state memory */
    memset(psSilk_VAD, 0, sizeof(silk_VAD_state));

    /* init noise levels */
    /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */
    for (b = 0; b < VAD_N_BANDS; b++) { psSilk_VAD->NoiseLevelBias[b] = silk_max_32(silk_DIV32_16(VAD_NOISE_LEVELS_BIAS, b + 1), 1); }

    /* Initialize state */
    for (b = 0; b < VAD_N_BANDS; b++) {
        psSilk_VAD->NL[b] = silk_MUL(100, psSilk_VAD->NoiseLevelBias[b]);
        psSilk_VAD->inv_NL[b] = silk_DIV32(silk_int32_MAX, psSilk_VAD->NL[b]);
    }
    psSilk_VAD->counter = 15;

    /* init smoothed energy-to-noise ratio*/
    for (b = 0; b < VAD_N_BANDS; b++) { psSilk_VAD->NrgRatioSmth_Q8[b] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ }

    return (ret);
}
