/*
   HARK Library
   Copyright (C) 2021 Honda Research Institute Japan Inc.
 */

#if !defined(_HARKLIB_NODE_SEMIBLIND_ICA_H_INCLUDED_)
#define _HARKLIB_NODE_SEMIBLIND_ICA_H_INCLUDED_ 1

#include "hark-lib/hark-lib.h"
#include "hark-lib/node.h"

#include <complex>
#include <vector>

namespace hark
{
namespace node
{
    class SemiBlindICA: public NodeDef
    {
    private:
        class SBSemiBlindICA {
            int id_i; // for debug
            int id_j; // for debug

            int taps;
            int idx;
            int itvl;
            unsigned long mask;  // for classical ring buffer

            float mu_s;
            float mu_n;

            float n_var;
            float r_var;

            float alpha;
            float is_zero;
            float FLOOR_VALUE;

            std::vector<std::complex<float>> mu_f;
            std::vector<std::complex<float>> buf_s;
            std::vector<std::complex<float>> buf_ns;
            std::vector<std::complex<float>> w;

        public:
            SBSemiBlindICA(int taps, int itvl, float lambda, float mu_s, float mu_v, float mu_n, float is_zero);

            void print() const;
            void save(std::ostream &file) const;
            void load(std::istream &file);
            std::complex<float> update(const std::complex<float> &x, const std::complex<float> &s);
        };

    public:
        SemiBlindICA();

        void initialize(InputDataBundle &input);
        virtual void reset();
        virtual bool operator () (size_t count, InputDataBundle &input, OutputDataBundle &output);

    private:
        void read_header(std::istream &file);
        void write_header(std::ostream &file) const;

    private:
        std::string filter_in_str;
        std::string filter_out_str;

        const char *filter_in_chr;
        const char *filter_out_chr;

        // FILE *filter_in;
        FILE *filter_out;

        int counter;
        int counter_loop;
        int freq;

        int length;
        int nchannel;
        int tap_lower;
        int tap_upper;
        int itvl;

        float mu_v;
        float mu_s;
        float mu_n;
        float lambda;
        float is_zero;

        //vector<SBSemiBlindICA*> sbsbica;
        std::vector<std::vector<SBSemiBlindICA>> sbsbica;    
    };
}
}

#endif /* #if !defined(_HARKLIB_NODE_SEMIBLIND_ICA_H_INCLUDED_) */

/* end of file */
