/*
** このファイルはAndroid版HARKの共通ヘッダファイルです
**
**
*/

#ifndef _INCLUDE_ANDROID_HARK_H_
#define _INCLUDE_ANDROID_HARK_H_

//// TAKIGAHIRA
////#include "mode_config.h"
////#define AUDIO_BITS _BIT_VAL_  /* オーディオデバイスのデータbit数 */
#include "config.h"
#include "header.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _COMPLEX_FLOAT_
{
    float real;
    float imag;
} COMPLEX_FLOAT;

/* FFTデータを受け渡しをするための構造体 */
typedef struct 
{
    int count;
    COMPLEX_FLOAT **data;
} FFT_DATA_ARY_t;

enum TFDIM
{
    TF_HEIGHT = 0,
    TF_DIRECTION = 1,
    TF_RANGE = 2,
    DUMMY = -1
};

/* 個々の音源位置データを格納する構造体 */
//  2013.10.16 M.Takigahira TFINDEX対応追加
typedef struct _SOURCE_
{
    float x[3];
    float power;
    int   id;
    float remaining;
    //double remaining;     //double type obsolete in original HARK.
    int   count;            // (Added Ver3.0.0) for TFINDEX
    int   last_found_count; // (Added Ver3.0.0) for TFINDEX
    int   tfindex[3];       // (Added Ver3.0.0) for TFINDEX
    int   tfindex_max[3];   // (Added Ver3.0.0) for TFINDEX
    int   tfindex_min[3];   // (Added Ver3.0.0) for TFINDEX
    int   mask;             // (Added Ver2.4.0) for source filtering by mask (fast SourceByDirection)
    
    int   dir_id;           // 2017.08.18 K.Takagi UART

} SOURCE_t;

static inline int _ha_iabs(int a){ // (-INT_MIN == INT_MIN) case supported fast abs()
    return ((a < 0) ? ((-a < 0) ? -(a+1) : -a) : a);
}

static inline int _ha_imin(int a, int b){
    return ((a < b) ? a : b);
}

static int tfindex_distance_base(const int* x, const int* y, const int* min, const int* max)
{
    int maxdist, tmpdist, i;
    maxdist = 0;
    i = 2;
    while(i>=0){
        if(x[i] > y[i]){
            tmpdist = _ha_imin(_ha_iabs(x[i] - y[i]),
                               _ha_iabs(x[i] - max[i]) + _ha_iabs(y[i] - min[i]));
        }
        else{
            tmpdist = _ha_imin(_ha_iabs(x[i] - y[i]),
                               _ha_iabs(x[i] - min[i]) + _ha_iabs(y[i] - max[i]));
        }
        maxdist = (maxdist < tmpdist) ? tmpdist : maxdist;
        i--;
    }
    return maxdist;
}

static int tfindex_distance(SOURCE_t* src1, SOURCE_t* src2)
{
    return tfindex_distance_base(src1->tfindex, src2->tfindex, src1->tfindex_min, src1->tfindex_max);
}

/* Source.h 's angle() :: input is SOURCE_t x, y; func(x.x, y.x) */
static float src_cos_theta(const float* x, const float* y)
{
    float prod;
    /*
    prod = (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
         / sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])
         / sqrt(y[0]*y[0]+y[1]*y[1]+y[2]*y[2]);
    */
    prod = (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
         / sqrtf((x[0]*x[0]+x[1]*x[1]+x[2]*x[2]) * (y[0]*y[0]+y[1]*y[1]+y[2]*y[2]));
    return prod;
}

static float coordinates_angle(const float* x, const float* y)
{
    float cos_theta;
    cos_theta = src_cos_theta(x, y);
    return acosf((cos_theta < -1.0f ? -1.0f : (cos_theta > 1.0f ? 1.0f : cos_theta)));
    // It is within the range of -1<=theta<=1 for acos(theta).
}

static float src_angle(SOURCE_t* src1, SOURCE_t* src2)
{
    return coordinates_angle(src1->x, src2->x);
}

/* 音源位置データを受け渡しするための構造体 */
typedef struct 
{
    int count;
    int source_num;
    //SOURCE_t data[16];
    SOURCE_t data[18*2]; // 360度/20度x2 = 18 x 2
} SOURCE_DATA_ARY_t;


/*****************************************
** 音声入力部のモジュール用のパラメータ
**
** Audio Stream From MIC / Wave
**
*/

typedef struct
{
    //// cancel //// int device_type;
    int  length;                     //
    int  advance;                    //  _ADVANCE_VAL_
    int  channel_count;              //  _DEV_CH_VAL_
    int  logical_channel_count;      //  _CH_VAL_
    int  channel_offset;             //  _CH_OFFSET_VAL_     for Easy implementation of ChannelSelector like function.
    int  sampling_rate;              //
    int  nbits;                      //  _BIT_VAL_           Number of sample bits for audio device.
} Param_AudioStreamFromMic_t;

typedef struct
{
    int  length;
    int  advance;
    char wave_file_name[256];
} Param_AudioStreamFromWave_t;

/*****************************************
** FFTモジュールのパラメータ
**
** MultiFFT
**
*/

/* FFT Window Type */
enum WINDOW_TYPE 
{
    UNKNOWN_WINDOW,
    CONJ_WINDOW,
    RECTANGLE_WINDOW,
    HAMMING_WINDOW,
    HANNING_WINDOW
};

typedef struct
{
    int length;
    int window_type;
    int window_length;
} Param_MultiFFT_t;


/*****************************************
** SemiBlindICAモジュールのパラメータ
**
** SemiBlindICA
**
*/

typedef struct
{
    int   channel;
    int   length;
    int   interval;
    int   tap_lower;
    int   tap_upper;
    float lambda;
    float mu_v;
    float mu_s;
    float mu_n;
    float is_zero;
    int   output_freq;
} Param_SemiBlindICA_t;


/*****************************************
** 音源定位モジュールのパラメータ
**
** Localize MUSIC
**
*/

enum MUSIC_ALGORITHM
{
    SEVD,
    GEVD,
    GSVD
};

enum SPECTRUM_WEIGHT_TYPE
{
    Uniform,
    A_Characteristic,
    Manual_Spline,
    Manual_Square
};

typedef struct
{
    int   music_algorithm;
    int   tf_channel_num;
    int   tf_channel_selection[16];
    int   length;
    int   sampling_rate;
    char  a_matrix[256];
    float elevation;
    int   window;
    int   period;
    int   num_source;
    int   export_num_source;
    int   min_deg;
    int   max_deg;
    int   low_bound_frequency;
    int   upper_bound_frequency;
    int   spectrum_weight_type;
    int   enable_eigenvalue_weight;
    
    /* spectrum_weight_type = A_Characteristic */
    float a_char_scaling;
    
    /* spectrum_weight_type = Manual_Spline */
    int   spline_num;
    float manual_weight_spline[2][32];
    
    /* spectrum_weight_type = Manual_Square */
    int   square_num;
    float manual_weight_square[32];
} Param_LocalizeMUSIC_t;

/*
** NormalizeMUSIC
*/

typedef struct
{
    float initial_threshold;
    float active_prop;
    int   update_interval;
    float prior_weight;
    int   max_source_num;
    int   particle_num;
    float local_peak_margin;
} Param_NormalizeMUSIC_t;

/*
** ConstantLocalization
*/

enum SRC_MASK_TYPE
{
    Mask_None           = 0x0000, //MASK is used the NONE.
    Mask_Use_Localize   = 0x0001, //MASK is USEd in the LOCALIZE.
    Mask_Use_Separation = 0x0002, //MASK is USEd in the SEPARATION.
    Mask_Use_Output     = 0x0004, //MASK is USEd in the OUTPUT.
    Mask_Dummy          = 0x0008  //prepare MASK of DUMMY for clarity that this enumerate structure is indicate a flag status.
};

typedef struct
{
    int source_num;
    float angle[16];
    float elevations[16];
    int mask[16]; // SRC_MASK_TYPE
} Param_ConstantLocalization_t;

/*
** ExtendedSourceTracker
*/

enum COMPARE_MODE
{
    DEG     = 0, //
    TFINDEX = 1  //
};

enum REMOVED_SOURCE_ALGORITHM
{
    LATEST = 0, //
    OLDEST = 1  //
};

typedef struct
{
    float thresh;
    int   pause_length;
    int   remove_length;
    int   remove_check_length;
    int   compare_mode;            // COMPARE_MODE    0:DEG, 1:TFINDEX
    float min_src_interval;
    int   min_tfindex_interval;
    int   preroll_length;
    int   max_num_source;
    int   removed_source_algorithm; // REMOVED_SOURCE_ALGORITHM    0:LATEST, 1:OLDEST
    int   min_id;
} Param_ExtendedSourceTracker_t; // (Added AndroidHARK Ver3.0.0)


/*
** SourceTracker
*/

typedef struct
{
    float thresh;
    float pause_length;
    int   compare_mode;         // (Added AndroidHARK Ver3.0.0) COMPARE_MODE    0:DEG, 1:TFINDEX
    float min_src_interval;
    int   min_tfindex_interval; // (Added AndroidHARK Ver3.0.0)
    int   min_id;
} Param_SourceTracker_t;


/*
** SourceIntervalExtender
*/

typedef struct
{
    int preroll_length;
} Param_SourceIntervalExtender_t;


/*****************************************
** 音源分離モジュールのパラメータ
**
** GHDSS
**
*/

typedef struct 
{
    int   length;
    int   advance;
    int   sampling_rate;
    int   lower_bound_frequency;
    int   upper_bound_frequency;
    char  tf_conj[16]; // "CALC" or "DATABASE"
    char  tf_conj_filename[256];
    char  mic_filename[256];
    char  mic_pos_shift[16]; // "FIX" or "SHIFT"
    int   fixed_noise;
    char  fixed_noise_filename[256];
    char  initw_filename[256];
    float speed_of_sound;
    char  ss_method[16]; // "FIX" or "LC_MYU" or "ADAPTIVE"
    float ss_scal;
    float ss_myu;
    float noise_floor;
    char  lc_const[16]; // "FULL" or "DIAG"
    char  lc_method[16]; // "FIX" or "ADAPTIVE"
    float lc_myu;
    char  update_method_tf_conj[16]; // "ID" or "POS"
    char  update_method_w[16]; // "ID" or "POS" or "ID_POS"
    float update_accept_angle;
    int   export_w;
    char  export_w_filename[256];
    char  update[16]; // "STEP" or "TOTAL"
} Param_GHDSS_t;

/*****************************************
** 音源分離モジュールのパラメータ
**
** Beamform（共通）現状、LCMVのみが使用する
** [INFO] INIT_W/EXPORT_Wは使用しないので不要変数をコメントアウト済（オリジナルHARKにも実装が無い）
**
*/

enum SS_METHOD_TYPE // GSS, GHDSS, GICA only
{
    SS_STEP_ADAPTIVE =  0, // SS myu calculate method is adaptive.
    SS_STEP_FIX      =  1, // SS myu calculate method is fix value.
    SS_STEP_LC_MYU   =  2  // SS myu calculate method is same as lc myu value.
};

enum LC_METHOD_TYPE
{
    LC_STEP_ADAPTIVE =  0, // LC myu calculate method is adaptive.
    LC_STEP_FIX      =  1  // LC myu calculate method is fix value.
};

enum BF_NLFUNC_TYPE
{
    NLFUNC_DUMMY     =  0, // dummy.
    NLFUNC_TANH      =  1, // tanh.
    NLFUNC_CUBE      =  2  // cube.
};

/* pending :: current definition from HA_server/HA_params.h #define pragma */
enum BF_METHOD
{
    SEP_NONE  = 0x00, // None
    SEP_GHDSS = 0x01, // GHDSS
    SEP_LCMV  = 0x02, // LCMV
    SEP_GJ    = 0x03, // GJ (Not implement)
    SEP_MSNR  = 0x04, // MSNR (Not implement)
    SEP_GSS   = 0x05, // GSS (Not implement)
    SEP_GICA  = 0x06, // GICA (Not implement)
    SEP_DS    = 0x07, // DS (Not implement)
    SEP_WDS   = 0x08, // WDS (Not implement)
    SEP_NULL  = 0x09, // NULL (Not implement)
    SEP_ILSE  = 0x0A, // ILSE (Not implement)
    SEP_ML    = 0x0B  // ML (Not implement)
};

typedef struct 
{
    int   bf_method;               // Select separation algorithm for beamforming node
    int   length;
    int   advance;
    int   sampling_rate;
    char  tf_conj_filename[256];
    //float speed_of_sound;        // obsolete, because this variable need only for TF calculation. this change same as svn Revision.6488
    int   nl_func;
    int   ss_method;               // SS_METHOD_TYPE (GSS, GHDSS, GICA only)
    float ss_scal;                 // (GSS, GHDSS, GICA only)
    float ss_myu;                  // (GSS, GHDSS, GICA only)
    int   lc_method;               // LC_METHOD_TYPE
    float lc_myu;
    int   decomposition_algorithm; // (MSNR only) add from svn Revision.6469 : 固有値分解アルゴリズムはMUSIC_ALGORITHMと同じ列挙体を用いる
    float alpha;                   // (MSNR only)
    //int   period;                // (ML only) obsolete from svn Revision.6432
    int   reg_factor;              // (ML only)
    //char  init_w_filename[256];  // not used
    //int   export_w;              // not used
    //char  export_w_filename[256];// not used
} Param_BF_t;


/*****************************************
** フィルタモジュールのパラメータ
**
** HRLE
**
*/

typedef struct
{
	int   fft_length; // FFT長
    float lx;         // 正規化累積頻度
    float tr;         // 時定数
    float min_lv;     // ヒストグラムの最少レベル
    float step_lv;    // ヒストグラムの便の幅
    int   num_bin;    // ヒストグラムのビン数
} Param_HRLE_t;

/*****************************************
** モジュールのパラメータ
**
** WhiteNoiseAdder
**
*/

typedef struct
{
    int   length;     // レングス
    int   fft_length; // FFT長
    float wn_level;   // ホワイトノイズレベル
} Param_WhiteNoiseAdder_t;

/*****************************************
** モジュールのパラメータ
**
** EstimateLeak
**
*/

typedef struct
{
    int   fft_length;    // FFT長
    float leak_factor;   // 漏れ係数(ただし、LEAK_FACTOR*OVER_CANCEL_FACTORの値とする)
} Param_EstimateLeak_t;

/*****************************************
** モジュールのパラメータ
**
** MSLSExtraction
**
*/

typedef struct
{
    int   fbank;         // バンク数
    int   normalization; // ノーマライズモード
    int   power;         // パワー項使用
    int   fft_length;    // FFT長(パワー項使用時のみ有効)
} Param_MSLSExtraction_t;

/*****************************************
** モジュールのパラメータ
**
** MelFilterBank
**
*/

typedef struct
{
    int   fbank;   // バンク数
    int   length;        // レングス
    int   fft_length;    // FFT長
    int   sampling_rate; // サンプリングレート
    int   cutoff;       // カットオフ
    int   min_frequency; // 最小
    int   max_frequency; // 最大
} Param_MelFilterBank_t;

/*****************************************
** モジュールのパラメータ
**
** PreEmphasis
**
*/

enum INPUT_TYPE
{
    WAV = 1,
    SPECTRUM = 2
};

typedef struct
{
    int   length;        // レングス
    int   fft_length;    // FFT長
    int   sampling_rate; // サンプリングレート
    int   cutoff;       // カットオフ
    float preem_coef; // PreEmphasis coefficient
} Param_PreEmphasis_t;

/*****************************************
** モジュールのパラメータ
**
** Synthesize
**
*/

typedef struct
{
    int   length;
    int   fft_length;
    int   min_freq;
    int   max_freq;
    int   tlength;
    float output_gain;
} Param_Synthesize_t;

/*****************************************
** モジュールのパラメータ
**
** Bluetooth
**
*/

typedef struct
{
  int mic_enable;
  int min_deg;
  int max_deg;
} Param_Bluetooth_t;


/*****************************************
** モジュールのパラメータ
**
** FLAC
**
*/

typedef struct
{
  int blocksize;

  int mic_enable;
  int mic_max_lpc_order;
  int mic_rice_partition_order;

  int sep_enable;
  char sep_hostname[256];
  int sep_max_lpc_order;
  int sep_rice_partition_order;

} Param_Flac_t;

#ifdef __cplusplus
}
#endif


#endif /* End of _INCLUDE_ANDROID_HARK_H_ */

/* EOF */

