// Speaker.h: interface for the CSpeaker class.
//


#pragma once

#include "Device.h"
#include "BKSound_Defines.h"

#define AUTOGAIN_BUFFER_MASK 0xfff
#define AUTOGAIN_BUFFER_LEN (AUTOGAIN_BUFFER_MASK+1)


//длина ких фильтра. нечётная
#define FIR_LENGTH 127

class CSpeaker : public CDevice
{
		static const double m_dSpeakerValues[8];

		enum FILTER_WINDOW_TYPE
		{
			RECTANGULAR = 0,    // Rectangular window function
			BARTLETT,           // Bartlett (triangular) window
			HANNING,            // Hanning window
			HAMMING,            // Hamming window
			BLACKMAN,           // Blackman window
			BLACKMAN_HARRIS,    // Blackman-Harris window
			BLACKMAN_NUTTAL,    // Blackman-Nuttal window
			NUTTAL              // Nuttal window
		};

	protected:
		enum FILTER_TYPE
		{
			NONE = 0,
			LOWPASS,    //ФНЧ
			HIGHPASS,   //ФВЧ
			BANDSTOP,   //ФПЗ
			BANDPASS    //ФПП
		};

		enum            {DEFAULT_SIZE = 2 * 1024 * 1014};

		bool            m_bEnableSound;
		bool            m_bFilter;
		int             m_ips;
		SAMPLE_TYPE    *m_pRecieveSamples; //массив данных получаемых с ленты, из которых узнается, что там прочлось
		SAMPLE_TYPE     m_nAverage;

		int             m_nBufferPosL, m_nBufferPosR;
		double          m_dAvgL, m_dAvgR;
		double         *m_pdBufferL;
		double         *m_pdBufferR;

		double          *m_pH; //коэффициенты КИХ

		double          m_LeftBuf[FIR_LENGTH]; //буферы для фильтра
		double          m_RightBuf[FIR_LENGTH]; //в перспективе - динамические
		int             m_nLeftBufPos;
		int             m_nRightBufPos;

		//накопители значения сэмпла, значимо только последнее на момент выборки значение
		double          m_dLeftAcc, m_dRightAcc;
		//эмулятор конденсатора
		bool            m_bRCProc; // флаг, обозначает, что идёт в данный момент false - разряд true - заряд
		double          m_ft; //аккумулятор временного интервала
		double          m_fmaxvol;
		double          m_fminvol;
		double          m_fdeltavol;
		double          m_fUi_prev;

		double          AutoGain(register double sample, register double &fAvg, register double *pBuf, register int &nBufPos);
		void            CalcFIR(double *pH, int nN, double dFs1, double dFs2, FILTER_TYPE nFilterType);
		double          getWindow(int i, int n, FILTER_WINDOW_TYPE window);
		double          FIRFilter(register double sample, register double *pBuf, register int &nBufPos);

		inline double   RCSHIMCalc();
	public:

		CSpeaker();
		virtual ~CSpeaker() override;
		virtual void ReInit();

		void            SetSampleBuffer(int ips);
		inline LONGLONG GetSampleCount()
		{
			return m_tickCount;
		}
		void            ReceiveSamples(void *pBuff, int length);
		inline void     EnableSound(bool bEnable)
		{
			m_bEnableSound = bEnable;
		}
		inline bool     IsSoundEnabled()
		{
			return m_bEnableSound;
		}

		inline void     SetFilter(bool b)
		{
			m_bFilter = b;
		}
		inline bool     GetFilter()
		{
			return m_bFilter;
		}
		virtual void    SetSample(WORD inVal);
		virtual bool    GetSample(double &sampleL, double &sampleR);
		void RCSHIM(double fTime);
		// Virtual method called after reset command
		virtual void    OnReset() override;

		// Methods for Set/Get byte/word
		virtual void    GetByte(WORD addr, BYTE *pValue) override
		{
			ASSERT(FALSE);
		}
		virtual void    GetWord(WORD addr, WORD *pValue) override
		{
			ASSERT(FALSE);
		}
		virtual void    SetByte(WORD addr, BYTE value) override
		{
			ASSERT(FALSE);
		}
		virtual void    SetWord(WORD addr, WORD value) override
		{
			ASSERT(FALSE);
		}
};
