#ifndef LMATH_WINDOW_H
#define LMATH_WINDOW_H

#include "lmath_defs.h"

#ifdef __cplusplus
extern "C" {
#endif

/** Контекст окна.
    Содержит рассчитанные коэффициенты окна заданного размера и
    различные параметры окна */
typedef struct st_lmath_win_ctx *t_lmath_window_ctx;



/** Параметры используемого окна. Заполняются при вызове функций
 *  lmath_window()/lmath_scaled_window() и используются другими
 *  функциями при дальнейшей обработке */
typedef struct {
    double inherent_gain; /**< Сумма коэф. окна в квадрате / size */
    double coherent_gain; /**< Квадрат суммы коэф. окна, деленной на size */
    double coherent_gain_sqrt; /**< Сумма коэф. окна, деленной на size */
    double enbw; /**< Equivalent Noise Bandwidth = inherent_gain/coherent_gain */
    int freq_span; /**< Ширина пика одной частоты в спектре */
} t_lmath_window_params;



/** Тип используемого окна */
typedef enum  {
    LMATH_WINTYPE_RECTANGLE         = 0, /**< Прямоугольное */
    LMATH_WINTYPE_HANNING           = 1, /**< Hanning / Hann */
    LMATH_WINTYPE_HAMMING           = 2, /**< Hamming */
    LMATH_WINTYPE_EXACT_BLACKMAN    = 4, /**< Exact Blackman  (a0 = 7938/18608, a1 = 9240/18608, a2 = 1430/18608) */
    LMATH_WINTYPE_BLACKMAN          = 5, /**< Blackman (a0 = 0.42, a1 = 0.5, a2 = 0.08) */
    LMATH_WINTYPE_BH_4TERM          = 7,  /**< 4-Term Blackman Harris */
    LMATH_WINTYPE_BH_7TERM          = 8,  /**< 7-Term Blackman Harris */
    LMATH_WINTYPE_BLACKMAN_NUTTALL  = 11  /**< Blackman Nuttall */
} t_lmath_wintype;



/***************************************************************************//**
    Функция вычисляет параметры окна и его коэффициенты и создает контекст
    окна с этими параметрами для дальнейшего применения.
    Выделенные ресурсы должны быть очищены с помощью lmath_window_ctx_destroy().

    @param[in] wintype      Тип окна (значение из #t_lmath_wintype)
    @param[in] param        Указатель на структуру с параметрами для расчета
                            окна (резерв)
    @param[in] size         Размер окна (количество коэффициентов окна и соответственно
                            количество точек в сигнале, к которому оно может применяться)
    @param[out] win         Массив, в который будут сохранены рассчитанные коэффициенты
                            окна. Должен быть достаточного размера для сохранения
                            size элементов.
    @param[out] win_params  Функция выделяет данную структуру и сохраняет в нее
                            рассчитанные параметры, если передан ненулевой
                            указатель
    @return                 Код ошибки.
    ***************************************************************************/
t_lmath_window_ctx lmath_window_ctx_create(t_lmath_wintype wintype,  void *param, int size);


/***************************************************************************//**
    Уничтожение ранее созданного с помощью lmath_window_ctx_create()
    контекста.
    @param[in] ctx     Контекст с параметрами окна
 ******************************************************************************/
void lmath_window_ctx_destroy(t_lmath_window_ctx winctx);

/* Функции для получения параметров окна по контексту */
int lmath_window_size(const t_lmath_window_ctx winctx);
double lmath_window_inherent_gain(const t_lmath_window_ctx winctx);
double lmath_window_coherent_gain(const t_lmath_window_ctx winctx);
double lmath_window_coherent_gain_sqrt(const t_lmath_window_ctx winctx);
double lmath_window_enbw(const t_lmath_window_ctx winctx);
int lmath_window_freq_span(const t_lmath_window_ctx winctx);
const t_lmath_window_params *lmath_window_params(const t_lmath_window_ctx winctx);
const double *lmath_window_coefs(const t_lmath_window_ctx winctx);

/***************************************************************************//**
    Функция применяет к сигналу окно, параметры которого заранее посчитаны
    с помощью lmath_window_ctx_create().
    По сути просто умножает точки сигнала на рассчитанные коэффициенты окна.
    Нормирование амплитуды выходного сигнала при этом не выполняется.

    @param[in] winctx      Контекст с параметрами окна
    @param[in] src         Массив с отсчетами входного сигнала
    @param[out] res        Массив, в который будут сохранен результирующий сигнал.
                           Должен быть достаточного размера для сохранения точек,
                           соответствующих размеру окна
    @return                Код ошибки.
    ***************************************************************************/
t_lmath_errs lmath_window_apply(const double *src, const t_lmath_window_ctx winctx, double *res);
/***************************************************************************//**
    Функция применяет к сигналу окно, , параметры которого заранее посчитаны
    с помощью lmath_window_ctx_create(),
    и выполняет нормирование амплитуды выходного сигнала

    @param[in] winctx      Контекст с параметрами окна
    @param[in] src         Массив с отсчетами входного сигнала
    @param[out] res        Массив, в который будут сохранен результирующий сигнал.
                           Должен быть достаточного размера для сохранения точек,
                           соответствующих размеру окна
    @return                Код ошибки.
    ***************************************************************************/
t_lmath_errs lmath_window_apply_scaled(const double *src, t_lmath_window_ctx winctx, double *res);



#ifdef __cplusplus
}
#endif

#endif // LMATH_WINDOW_H
