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

#if !defined(_HARKLIB_NODE_V_AD__ZC_H_INCLUDED_)
#define _HARKLIB_NODE_V_AD__ZC_H_INCLUDED_ 1

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

#include "hark-lib/source.h"

namespace hark
{
namespace node
{
    class VADZC: public NodeDef
    {
    public:
        VADZC();
        virtual void reset();
        virtual bool operator () (size_t count, InputDataBundle &input, OutputDataBundle &output);

    private:
        void update_parameters(InputDataBundle &input);
        void receive(InputDataBundle &input, int count);

    private:
        // params
        int _channel_count;
        int _advance;
        int _length;
        float _split_period; // [msec]
        int _sampling_rate;
        bool _strip_zero;
        bool _zero_mean;
        float _level_threshold;
        int _zerocross_threshold;
        float _head_margin; // in millisec
        float _tail_margin; // in millisec

        // workset
        int _zerocross_threshold_count; // zerocross_threshold をフレーム数で表した値
        int _source_count;       // みつかった音源の通し番号
        int _split_period_frames; // sprit_period をフレーム数で表した値
        int _head_margin_frames; // head_margin をフレーム数で表した値
        int _tail_margin_frames; // tail_margin をフレーム数で表した値
        int _last_frame_index;
        int _channel_buffer_length;
        int _channel_buffer_offset;
        std::map<int, Source>_channel_sources;

        int _count;

        class ZeroCrossCounter {
        public:
            std::vector<float>buffer;
            std::vector<bool>hasPower;
            std::vector<bool>hasZeroCross;
            int size;
            int offset;
            float threshold;
            int zeroCrossCount;

        public:
            ZeroCrossCounter() = default;

        public:
            void reset(int size, float threshold);
            int update(const float *data, int count);
            int getZeroCrossCount() const;

        };

        struct ChannelWorkset {
            std::vector<std::vector<float>>buffer; // channel_buffer[frame_offset][]
            ZeroCrossCounter zerocross_counter;
            int last_active_frame_index;
            float dc;
            bool dc_prepared;
        };
        std::vector<ChannelWorkset>_channel_worksets;
    };
}
}

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

/* end of file */
