#include "lmath_acdc.h"
#include "lmath_internal.h"
#include <stdlib.h>


t_lmath_errs lmath_acdc_estimation_with_window(const double *src,
                                               const t_lmath_window_ctx winctx,
                                               double *tmp_buf,
                                               double *dc, double *ac) {

    int i;
    double avg = 0;
    t_lmath_errs err = (src == NULL) || (winctx == NULL) || (tmp_buf == NULL)
             || ((ac != NULL) && (tmp_buf == src)) ?
                LMATH_ERR_INVALID_PARAMS : LMATH_ERR_OK;


    if (!err) {
        /* сперва накладываем окно на исходный сигнал для рассчета DC */
        err = lmath_window_apply(src, winctx, tmp_buf);
    }

    if (!err) {
        int size = lmath_window_size(winctx);
        double cog_gain_sqrt = lmath_window_coherent_gain_sqrt(winctx);


        for (i = 0; i < size; i++) {
            avg+=tmp_buf[i];
        }
        avg/=(size*cog_gain_sqrt);

        if (dc != NULL)
            *dc = avg;


        if (!err && (ac != NULL)) {
            double inh_gain = lmath_window_inherent_gain(winctx);
            double rms = 0;
            /* далее для рассчета AC заменяем сигнал на исходный без DC */
            for (i=0; i < size; i++) {
                tmp_buf[i]=(src[i] - avg);
            }

            /* накладываем окно на сигнал без DC */
            err = lmath_window_apply(tmp_buf, winctx, tmp_buf);
            for (i = 0; i < size; i++) {
                rms+= tmp_buf[i]*tmp_buf[i];
            }

            rms/=(size*inh_gain);
            rms = sqrt(rms);
            if (!err)
                *ac = rms;
        }
    }

    return err;
}

t_lmath_errs lmath_acdc_estimation(const double *src, int size, double *dc, double *ac) {
    t_lmath_errs err = LMATH_ERR_OK;
    double *tmp_arr = (double *)malloc(sizeof(tmp_arr[0])*(unsigned)size);
    t_lmath_window_ctx winctx = lmath_window_ctx_create(LMATH_WINTYPE_BH_4TERM, 0, size);


    if ((tmp_arr==NULL) || (winctx == NULL)) {
        err = LMATH_ERR_MEMORY_ALLOC;
    } else {
        /* сперва накладываем окно на исходный сигнал для рассчета DC */
        err = lmath_acdc_estimation_with_window(src, winctx, tmp_arr, dc, ac);
    }

    free(tmp_arr);
    lmath_window_ctx_destroy(winctx);

    return err;
}
