/*
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jitsi.impl.neomedia.codec.audio.silk;

/**
 * This class contains a number of defines that controls the operation of SILK.
 * Most of these should be left alone for ensuring proper operation. However, a
 * few can be changed if operation different from the default is desired.
 *
 * @author Jing Dai
 * @author Dingxin Xu
 */
public class Define
{
    static final int MAX_FRAMES_PER_PACKET =                  5;

    /* MAX DELTA LAG used for multiframe packets */
    static final int MAX_DELTA_LAG =                          10;

    /* Lower limit on bitrate for each mode */
    static final int MIN_TARGET_RATE_NB_BPS =                 5000;
    static final int MIN_TARGET_RATE_MB_BPS =                 7000;
    static final int MIN_TARGET_RATE_WB_BPS =                 8000;
    static final int MIN_TARGET_RATE_SWB_BPS =                20000;

    /* Transition bitrates between modes */
    static final int SWB2WB_BITRATE_BPS =                     26000;
    static final int WB2SWB_BITRATE_BPS =                     32000;
    static final int WB2MB_BITRATE_BPS  =                     15000;
    static final int MB2WB_BITRATE_BPS  =                     20000;
    static final int MB2NB_BITRATE_BPS  =                     10000;
    static final int NB2MB_BITRATE_BPS  =                     14000;

    /* Integration/hysteresis threshold for lowering internal sample frequency */
    /* 30000000 -> 6 sec if bitrate is 5000 bps below limit; 3 sec if bitrate is 10000 bps below limit */
    static final int ACCUM_BITS_DIFF_THRESHOLD =              30000000;
    static final int TARGET_RATE_TAB_SZ =                     8;

    /* DTX settings                                 */
    static final int NO_SPEECH_FRAMES_BEFORE_DTX =            5;       /* eq 100 ms */
    static final int MAX_CONSECUTIVE_DTX =                    20;      /* eq 400 ms */

    static final int USE_LBRR =                               1;

    /* Amount of concecutive no FEC packets before telling JB */
    static final int NO_LBRR_THRES =                          10;

    /* Maximum delay between real packet and LBRR packet */
    static final int MAX_LBRR_DELAY =                         2;
    static final int LBRR_IDX_MASK  =                         1;

    static final int INBAND_FEC_MIN_RATE_BPS =                18000;  /* Dont use inband FEC below this total target rate  */
    static final int LBRR_LOSS_THRES =                        2;   /* Start adding LBRR at this loss rate (needs tuning)   */

    /* LBRR usage defines */
    static final int SKP_SILK_NO_LBRR =                       0;   /* No LBRR information for this packet                  */
    static final int SKP_SILK_ADD_LBRR_TO_PLUS1 =             1;   /* Add LBRR for this packet to packet n + 1             */
    static final int SKP_SILK_ADD_LBRR_TO_PLUS2 =             2;   /* Add LBRR for this packet to packet n + 2             */

    /* Frame termination indicator defines */
    static final int SKP_SILK_LAST_FRAME =                    0;   /* Last frames in packet                                */
    static final int SKP_SILK_MORE_FRAMES =                   1;   /* More frames to follow this one                       */
    static final int SKP_SILK_LBRR_VER1 =                     2;  /* LBRR information from packet n - 1                   */
    static final int SKP_SILK_LBRR_VER2 =                     3;   /* LBRR information from packet n - 2                   */
    static final int SKP_SILK_EXT_LAYER =                     4;   /* Extension layers added                               */

    /* Number of Second order Sections for SWB detection HP filter */
    static final int NB_SOS =                                 3;
    static final int HP_8_KHZ_THRES=                          10;          /* average energy per sample, above 8 kHz       */
    static final int CONCEC_SWB_SMPLS_THRES=                  480 * 15;    /* 300 ms                                       */
    static final int WB_DETECT_ACTIVE_SPEECH_MS_THRES =       15000;       /* ms of active speech needed for WB detection  */

    /* Low complexity setting */
    static final boolean LOW_COMPLEXITY_ONLY = false;

    /* Activate bandwidth transition filtering for mode switching */
    static final int SWITCH_TRANSITION_FILTERING =            1;

    /* Decoder Parameters */
    static final int DEC_HP_ORDER =                           2;

    /* Maximum sampling frequency, should be 16 for embedded */
    static final int MAX_FS_KHZ =                             24;
    static final int MAX_API_FS_KHZ=                          48;

    /* Signal Types used by silk */
    static final int SIG_TYPE_VOICED =                        0;
    static final int SIG_TYPE_UNVOICED =                      1;

    /* VAD Types used by silk */
    static final int NO_VOICE_ACTIVITY =                      0;
    static final int VOICE_ACTIVITY =                         1;

    /* Number of samples per frame */
    static final int FRAME_LENGTH_MS =                        20; /* 20 ms */
    static final int MAX_FRAME_LENGTH =                       (FRAME_LENGTH_MS * MAX_FS_KHZ);

    /* Milliseconds of lookahead for pitch analysis */
    static final int LA_PITCH_MS =                            3;
    static final int LA_PITCH_MAX =                           (LA_PITCH_MS * MAX_FS_KHZ);

    /* Milliseconds of lookahead for noise shape analysis */
    static final int LA_SHAPE_MS  =                           5;
    static final int LA_SHAPE_MAX =                           (LA_SHAPE_MS * MAX_FS_KHZ);

    /* Order of LPC used in find pitch */
    static final int FIND_PITCH_LPC_ORDER_MAX =               16;

    /* Length of LPC window used in find pitch */
    static final int FIND_PITCH_LPC_WIN_MS =                  (30 + (LA_PITCH_MS << 1));
    static final int FIND_PITCH_LPC_WIN_MAX =                 (FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ);

    static final int PITCH_EST_COMPLEXITY_HC_MODE =           SigProcFIX.SKP_Silk_PITCH_EST_MAX_COMPLEX;
    static final int PITCH_EST_COMPLEXITY_MC_MODE =           SigProcFIX.SKP_Silk_PITCH_EST_MID_COMPLEX;
    static final int PITCH_EST_COMPLEXITY_LC_MODE =           SigProcFIX.SKP_Silk_PITCH_EST_MIN_COMPLEX;


    /* Max number of bytes in payload output buffer (may contain multiple frames) */
    static final int MAX_ARITHM_BYTES =                       1024;

    static final int RANGE_CODER_WRITE_BEYOND_BUFFER =        -1;
    static final int RANGE_CODER_CDF_OUT_OF_RANGE =           -2;
    static final int RANGE_CODER_NORMALIZATION_FAILED =       -3;
    static final int RANGE_CODER_ZERO_INTERVAL_WIDTH =        -4;
    static final int RANGE_CODER_DECODER_CHECK_FAILED =       -5;
    static final int RANGE_CODER_READ_BEYOND_BUFFER =         -6;
    static final int RANGE_CODER_ILLEGAL_SAMPLING_RATE =      -7;
    static final int RANGE_CODER_DEC_PAYLOAD_TOO_LONG =       -8;

    /* dB level of lowest gain quantization level */
    static final int MIN_QGAIN_DB =                           6;
    /* dB level of highest gain quantization level */
    static final int MAX_QGAIN_DB =                           86;
    /* Number of gain quantization levels */
    static final int N_LEVELS_QGAIN  =                        64;
    /* Max increase in gain quantization index */
    static final int MAX_DELTA_GAIN_QUANT =                   40;
    /* Max decrease in gain quantization index */
    static final int MIN_DELTA_GAIN_QUANT =                   -4;

    /* Quantization offsets (multiples of 4) */
    static final int OFFSET_VL_Q10 =                          32;
    static final int OFFSET_VH_Q10 =                          100;
    static final int OFFSET_UVL_Q10 =                         100;
    static final int OFFSET_UVH_Q10 =                         256;

    /* Maximum numbers of iterations used to stabilize a LPC vector */
    static final int MAX_LPC_STABILIZE_ITERATIONS =           20;

    static final int MAX_LPC_ORDER =                          16;
    static final int MIN_LPC_ORDER =                          10;

    /* Find Pred Coef defines */
    static final int LTP_ORDER =                              5;

    /* LTP quantization settings */
    static final int NB_LTP_CBKS =                            3;

    /* Number of subframes */
    static final int NB_SUBFR =                               4;

    /* Flag to use harmonic noise shaping */
    static final int USE_HARM_SHAPING  =                      1;

    /* Max LPC order of noise shaping filters */
    static final int SHAPE_LPC_ORDER_MAX =                    16;

    static final int HARM_SHAPE_FIR_TAPS =                    3;

    /* Length of LPC window used in noise shape analysis */
    static final int SHAPE_LPC_WIN_MS =                       15;
    static final int SHAPE_LPC_WIN_16_KHZ =                   (SHAPE_LPC_WIN_MS * 16);
    static final int SHAPE_LPC_WIN_24_KHZ =                   (SHAPE_LPC_WIN_MS * 24);
    static final int SHAPE_LPC_WIN_MAX =                      (SHAPE_LPC_WIN_MS * MAX_FS_KHZ);

    /* Maximum number of delayed decision states */
    static final int DEL_DEC_STATES_MAX =                     4;

    static final int LTP_BUF_LENGTH =                         512;
    static final int LTP_MASK =                               (LTP_BUF_LENGTH - 1);

    static final int DECISION_DELAY =                         32;
    static final int DECISION_DELAY_MASK =                    (DECISION_DELAY - 1);

    /* number of subframes for excitation entropy coding */
    static final int SHELL_CODEC_FRAME_LENGTH =               16;
    static final int MAX_NB_SHELL_BLOCKS =                    (MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH);

    /* number of rate levels, for entropy coding of excitation */
    static final int N_RATE_LEVELS =                          10;

    /* maximum sum of pulses per shell coding frame */
    static final int MAX_PULSES =                             18;

    static final int MAX_MATRIX_SIZE =                        MAX_LPC_ORDER; /* Max of LPC Order and LTP order */

    @SuppressWarnings("unused")
    static int NSQ_LPC_BUF_LENGTH()
    {
        return
            (MAX_LPC_ORDER > DECISION_DELAY) ? MAX_LPC_ORDER : DECISION_DELAY;
    }
    /***********************/
    /* High pass filtering */
    /***********************/
    static final boolean HIGH_PASS_INPUT = true;

    /***************************/
    /* Voice activity detector */
    /***************************/
    static final int VAD_N_BANDS =                            4;       /* 0-1, 1-2, 2-4, and 4-8 kHz                       */

    static final int VAD_INTERNAL_SUBFRAMES_LOG2 =            2;
    static final int VAD_INTERNAL_SUBFRAMES =                 (1 << VAD_INTERNAL_SUBFRAMES_LOG2);

    static final int VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 =        1024;    /* Must be <  4096                                  */
    static final int VAD_NOISE_LEVELS_BIAS =                  50 ;

    /* Sigmoid settings */
    static final int VAD_NEGATIVE_OFFSET_Q5 =                 128 ;    /* sigmoid is 0 at -128                             */
    static final int VAD_SNR_FACTOR_Q16 =                     45000 ;

    /* smoothing for SNR measurement */
    static final int VAD_SNR_SMOOTH_COEF_Q18 =                4096;

    /******************/
    /* NLSF quantizer */
    /******************/
    static final int NLSF_MSVQ_MAX_CB_STAGES =                     10;  /* Update manually when changing codebooks      */
    static final int NLSF_MSVQ_MAX_VECTORS_IN_STAGE =              128;/* Update manually when changing codebooks      */
    static final int NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END =   16;  /* Update manually when changing codebooks      */

    static final boolean NLSF_MSVQ_FLUCTUATION_REDUCTION = true;
    static final int MAX_NLSF_MSVQ_SURVIVORS =                16;
    static final int MAX_NLSF_MSVQ_SURVIVORS_LC_MODE =        2;
    static final int MAX_NLSF_MSVQ_SURVIVORS_MC_MODE =        4;

    /* Based on above defines, calculate how much memory is necessary to allocate */
    @SuppressWarnings("unused")
    static int NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE()
    {
        if(NLSF_MSVQ_MAX_VECTORS_IN_STAGE > ( MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END ))
            return NLSF_MSVQ_MAX_VECTORS_IN_STAGE;
        else
            return MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END;
    }

    @SuppressWarnings("unused")
    static int NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED()
    {
        if( NLSF_MSVQ_MAX_VECTORS_IN_STAGE > ( MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END ) )
            return NLSF_MSVQ_MAX_VECTORS_IN_STAGE;
        else
            return MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END;
    }

    static final int NLSF_MSVQ_SURV_MAX_REL_RD  =             4;

    /* Transition filtering for mode switching */
    static final int TRANSITION_TIME_UP_MS =            5120; // 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)
    static final int TRANSITION_TIME_DOWN_MS =          2560; // 2560 = 32 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 32*(20*4)
    static final int TRANSITION_NB =                    3; /* Hardcoded in tables */
    static final int TRANSITION_NA =                    2; /* Hardcoded in tables */
    static final int TRANSITION_INT_NUM =               5; /* Hardcoded in tables */
    static final int TRANSITION_FRAMES_UP =         ( TRANSITION_TIME_UP_MS   / FRAME_LENGTH_MS );
    static final int TRANSITION_FRAMES_DOWN =       ( TRANSITION_TIME_DOWN_MS / FRAME_LENGTH_MS );
    static final int TRANSITION_INT_STEPS_UP =      ( TRANSITION_FRAMES_UP    / ( TRANSITION_INT_NUM - 1 )  );
    static final int TRANSITION_INT_STEPS_DOWN =    ( TRANSITION_FRAMES_DOWN  / ( TRANSITION_INT_NUM - 1 )  );

//TODO:no need to convert from C to Java?
    /* Row based */
//    #define matrix_ptr(Matrix_base_adr, row, column, N)         *(Matrix_base_adr + ((row)*(N)+(column)))
//    #define matrix_adr(Matrix_base_adr, row, column, N)          (Matrix_base_adr + ((row)*(N)+(column)))

    /* Column based */
//    #ifndef matrix_c_ptr
//    #   define matrix_c_ptr(Matrix_base_adr, row, column, M)    *(Matrix_base_adr + ((row)+(M)*(column)))
//    #endif
//    #define matrix_c_adr(Matrix_base_adr, row, column, M)        (Matrix_base_adr + ((row)+(M)*(column)))

    /* BWE factors to apply after packet loss */
    static final int BWE_AFTER_LOSS_Q16 =                             63570;

    /* Defines for CN generation */
    static final int CNG_BUF_MASK_MAX  =                              255;             /* 2^floor(log2(MAX_FRAME_LENGTH))  */
    static final int CNG_GAIN_SMTH_Q16 =                              4634;            /* 0.25^(1/4)                       */
    static final int CNG_NLSF_SMTH_Q16 =                              16348;           /* 0.25                             */
}
