/*************************************************
*           BK Emulator v3.8 for Windows         *
*************************************************/

/*
File: Speaker.h
Version: 1.0.0
Written by: Yuriy Kalmykov <kalmykov@stoik.com>
    Copyright (c) 2002-2004 Yuriy Kalmykov

    BK Emulator is a program emulated hardware environment for running
code for BK 0010(01) in different configurations.

    This code may be used in compiled form in any way you desire.
This file or it's parts can't be redistributed without the authors
written consent, but can be modified for your private needs.
    Providing that this notice and the authors name and all copyright
notices remains intact.

    Please, an email me to know how you are using it and where. You can
ask me for any information about this below code or any attendant
knowledge.

    This file is provided "as is" with no expressed or implied warranty.
The author accepts no liability for any damage or loss of business that
this product may cause.
*/


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


#pragma once

#include "Device.h"
#include "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();

		void            SetSampleBuffer(int ips);
		inline LONGLONG GetSampleCount()
		{
			return m_tickCount;
		}
		void            ReceiveSamples(BYTE *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();

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