
#ifndef	SV_GEVBF_H
#define SV_GEVBF_H

#define ENABLE_2CH_SUPPORT 1
#define ENABLE_3CH_SUPPORT 0
#define ENABLE_4CH_SUPPORT 0

////*************************************************************************
////  Definations
////*************************************************************************
#define BF_Q 16
#define GEV_DIAGONAL_ENABLE 0
#define GEV_UPDATE_INTERVAL 40
#define SPEECH_COV_FORGETTING_FACTOR 31129
#define NOISE_COV_FORGETTING_FACTOR 29490
#define UPDATE_DELAYED_BUFFER_LEN 0

typedef long long INT64;
#define SMULL(a, b) ((INT64)(a)*(INT64)(b))
#define SMLAL(c, a, b) (c + ((INT64)(a)*(INT64)(b)))
//#define MAX(a, b) ((a)>(b)?(a):(b))
//#define MIN(a, b) ((a)<(b)?(a):(b))

static short update_position[GEV_UPDATE_INTERVAL] = {
#if GEV_UPDATE_INTERVAL == 30
	0, 9, 17, 26, 34, 43, 51, 60, 68, 77, 85, 94, 102, 111, 119, 128, 137, 145, 154, 162, 171, 179, 188, 196, 205, 213, 222, 230, 239, 247,
#elif GEV_UPDATE_INTERVAL == 40
	0, 6, 13, 19, 26, 32, 38, 45, 51, 58, 64, 70, 77, 83, 90, 96, 102, 109, 115, 122, 128, 134, 141, 147, 154, 160, 166, 173, 179, 186, 192, 198, 205, 211, 218, 224, 230, 237, 243, 250,
#elif if GEV_UPDATE_INTERVAL == 50
	0, 5, 10, 15, 20, 26, 31, 36, 41, 46, 51, 56, 61, 67, 72, 77, 82, 87, 92, 97, 102, 108, 113, 118, 123, 128, 133, 138, 143, 148, 154, 159, 164, 169, 174, 179, 184, 189, 195, 200, 205, 210, 215, 220, 225, 230, 236, 241, 246, 251,
#endif
};



////*************************************************************************
////  Generic math operations
////*************************************************************************
//return in Q16, input in same Q value
int SV_div_l(int a, int b);
//return in Q(BF_Q), input in same Q value
int SV_div_l2(int a, int b);
//Input in the range [0.25,1) in Q16, output in Q14
//short SV_rsqrt_limit(int x);
//Input in Q16, output in Q16
int SV_rsqrt(int x);
//Input in Q(BF_Q), output in Q(BF_Q)
int SV_rsqrt2(int x);



////*************************************************************************
////  Generic vector and matrix operations
////*************************************************************************
int SV_vec_norm(int *out, int *vec, int len, int headroom);
void SV_cmplx_vec_conj(int *out, int *vec, int len);
void SV_cmplx_order1_vec_mul(int *out, int *a, int *b, int shift);
void SV_cmplx_order2_vec_mul(int *out, int *a, int *b, int shift);
void SV_cmplx_order3_vec_mul(int *out, int *a, int *b, int shift);
void SV_cmplx_order4_vec_mul(int *out, int *a, int *b, int shift);
void SV_cmplx_order2_calc_autocorr_matrix(int *out, int *vec);
void SV_cmplx_order3_calc_autocorr_matrix(int *out, int *vec);
void SV_cmplx_order4_calc_autocorr_matrix(int *out, int *vec);
void SV_cmplx_order2_matrix_inverse(int *out, int *mat);
void SV_cmplx_order3_matrix_inverse(int *out, int *mat);
void SV_cmplx_order4_hermite_matrix_inverse(int *out, int *mat);
void SV_cmplx_order2_matrix_diagonal_loading(int *mat, int threshold);
void SV_cmplx_order3_matrix_diagonal_loading(int *mat, int threshold);
void SV_cmplx_order4_matrix_diagonal_loading(int *mat, int threshold);
void SV_cmplx_order2_matrix_hermiten_correct(int *mat);
void SV_cmplx_order3_matrix_hermiten_correct(int *mat);
void SV_cmplx_order4_matrix_hermiten_correct(int *mat);



////*************************************************************************
////  Generic operations used by various channel beamformer
////*************************************************************************
void SV_GEVBF_compensate_output(int *out, int *a, int len);
short SV_GEVBF_calcGainForPowerConstraint(INT64 OutPwr, INT64 refPwr);
void SV_GEVBF_update_corr_matrix(int *dst, int *pQ_dst, int *mat, int q_vec, short alpha, int len);
#if ENABLE_2CH_SUPPORT == 1
void SV_GEVBF_2CH_update_fgev(int *fgev, int *Rxx, int *rRnn);
void SV_GEVBF_2CH_wbm_weight_normalization(int *wbm, int *wbf, int *Rnn);
void SV_GEVBF_2CH_updata_bf_bm(int *wbf, int *wbm, int *fgev, int *Rnn);
#endif
#if ENABLE_3CH_SUPPORT == 1
void SV_GEVBF_3CH_update_fgev(int *fgev, int *Rxx, int *rRnn);
void SV_GEVBF_3CH_wbm_weight_normalization(int *wbm, int *wbf, int *Rnn);
void SV_GEVBF_3CH_wbm_weight_normalization_with_q(int *wbm, const int bm_q, int *wbf, const int bf_q, int *Rnn);
void SV_GEVBF_3CH_updata_bf_bm(int *wbf, int *wbm, int *fgev, int *Rnn);
void SV_GEVBF_3CH_phase_correction(int *wbf, int *wbf_prev);
#endif
#if ENABLE_4CH_SUPPORT == 1
void SV_GEVBF_4CH_update_fgev(int *fgev, int *Rxx, int *rRnn);
void SV_GEVBF_4CH_wbm_weight_normalization(int *wbm, int *wbf, int *Rnn);
void SV_GEVBF_4CH_updata_bf_bm(int *wbf, int *wbm, int *fgev, int *Rnn);
#endif




////*************************************************************************
////  Interface
////*************************************************************************
//// 2 channel GEV interface
#if ENABLE_2CH_SUPPORT == 1
int	SV_GEVBF_2CH_Init(void **varsPtr, short band_num, char *scratch_mem_ptr);
void SV_GEVBF_2CH_Exe(void *void_vars, int *main_mic, int *aux_mic, int *bf_out, int *bm_out);
void SV_GEVBF_2CH_Update(void *void_vars, int *main_mic, int *aux_mic, int *SMask, int *NMask, short Salpha, short Nalpha);

// for tracking only covariance (w/o calculating filter coefficient)
int SV_GEVBF_2CH_SimpleInit_V1(void **varsPtr, short band_num, char *scratch_mem_ptr);
void SV_GEVBF_2CH_UpdateCov(void *void_vars, int *main_mic, int *aux_mic, int *SMask, int *NMask, short Salpha, short Nalpha);

void SV_GEVBF_2CH_CalcGainForInEar(int *gain, void *void_2ch_vars, void *void_inEar_vars, int *innerCoef, int q, int weight_bais, int init_point, int end_point);
void SV_GEVBF_2CH_CalcGainForBM(int *gain, void *void_2ch_vars, void *void_inEar_vars, int *innerCoef, int q, int weight_bais, int init_point, int end_point);
int* SV_GEVBF_2CH_GetMaskSum(void *void_ptr, int type);
void SV_GEVBF_2CH_ResetFrmCnt(void *void_vars);
#endif

//// 3 channel GEV interface
#if ENABLE_3CH_SUPPORT == 1
int SV_GEVBF_3CH_Init(void **varsPtr, short band_num, char *scratch_mem_ptr);
void SV_GEVBF_3CH_Exe(void *void_vars, int *main_mic, int *aux_mic, int *thd_mic, int *bf_out, int *bm_out);
void SV_GEVBF_3CH_Update(void *void_vars, int *main_mic, int *aux_mic, int *thd_mic, int *SMask, int *NMask, short Salpha, short Nalpha);
//// bm normalization (ref: InEar output)
void SV_GEVBF_bm_norm_to_InEarOut(void *void_vars, int *innerCoef, int q, int weight_bais, int size); //!!!
#endif

//// 4 channel GEV interface
#if ENABLE_4CH_SUPPORT == 1
int SV_GEVBF_4CH_Init(void **varsPtr, short band_num, char *scratch_mem_ptr);
void SV_GEVBF_4CH_Exe(void *void_vars, int *main_mic, int *aux_mic, int *thd_mic, int *forth_mic, int *bf_out, int *bm_out);
void SV_GEVBF_4CH_Update(void *void_vars, int *main_mic, int *aux_mic, int *thd_mic, int *forth_mic, int *SMask, int *NMask, short Salpha, short Nalpha);
#endif


#endif //SV_GEVBF_H











