⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filterdesign.~cpp

📁 脑电信号分析软件
💻 ~CPP
📖 第 1 页 / 共 3 页
字号:
    double Angle;
    int X_Length,H_Length;

    if (order%2==0)
    {
        X[0]=1;
        X_Length=1;
    }
    else
    {
        X[0]=OMEGA/(OMEGA+1);
        X[1]=X[0];
        X_Length=2;

		pNum[0] = X[0];
		pNum[1] = X[1];
    }
    for (int i=1;i<=K;i++)
    {
        Angle=PI*(order-1+2*i)/(2*order);

        H[0]=pow(OMEGA,2)/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2));
        H[1]=2*H[0];
        H[2]=H[0];

        H_Length=3;

        X_Length=Conv(H_Length,H,X_Length,X,pNum);

        for (int j=0;j<X_Length;j++)
            X[j]=pNum[j];
    }
/*
	X[0] = 1;
	X_Length = 1;
	
	if(order % 2 == 0)
	{
		for (int i=1;i<=K;i++)
		{
			Angle=PI*(order-1+2*i)/(2*order);

			H[0]=pow(OMEGA,2)/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2));
			H[1]=2*H[0];
			H[2]=H[0];

			H_Length=3;

			X_Length=Conv(H_Length,H,X_Length,X,pNum);

			for (int j=0;j<X_Length;j++)
				X[j]=pNum[j];
		}

	}
	else
	{
        H[0]=OMEGA/(OMEGA+1);
        H[1]=H[0];
        H_Length=2;

		for(int i = 1; i <= K; i++)
		{
			X_Length=Conv(H_Length,H,X_Length,X,pNum);

			for (int j=0;j<X_Length;j++)
				X[j]=pNum[j];
		}

	}*/

}

/*!----------------------------------------------------------------------------
 * \brief 生成 butterworth  heightpass 的阶数
 *
 * 做预畸和lowpass 不同 其它参考 Butter::Butter_Lowpass_N:
 * \f[
 *    \omega_{pass} = \frac{1.0}{\tan(\frac{\omega_{pass}}{2})} \qquad,\qquad
 *    \omega_{stop} = \frac{1.0}{\tan(\frac{\omega_{stop}}{2})}
 * \f]
 *
 * ----------------------------------------------------------------------------*/ 
void Butter::Butter_Highpass_N()
{
    double wpass;
    double wstop;
    double Wpass;
    double Wstop;
    double e,w;

    wpass=2*PI*heightFre/fs;
    wstop=2*PI*lowFre/fs;

    Wpass=1.0/tan(wpass/2);
    Wstop=1.0/tan(wstop/2);

    e=sqrt(pow(10,As/10)-1)/sqrt(pow(10,Ap/10)-1);
    w=Wstop/Wpass;
    order=int(log(e)/log(w))+1;

    if(order > 16)
    {
        throw std::logic_error("设计的滤波器不稳定!请重试!");
    }

    OMEGA=Wpass/pow(pow(10,Ap/10)-1,1.0/(2*order));
}

/*!----------------------------------------------------------------------------
 * \brief 求高通的分母
 *
 * 和低通的区别只在于把方程中的z 换成-z。参考 Butter::Den_Butter_Lowpass
 *
 * ----------------------------------------------------------------------------*/ 
void Butter::Den_Butter_Highpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    int X_Length,H_Length;

    if (order%2==0)
    {
        X[0]=1;
        X_Length=1;
    }
    else
    {
        X[0]=1;
        X[1]=-(OMEGA-1)/(OMEGA+1);
        X_Length=2;

		pDen[0] = X[0];
		pDen[1] = X[1];
    }
    for (int i=1;i<=K;i++)
    {
        Angle=PI*(order-1+2*i)/(2*order);

        H[0]=1;
        H[1]=-2*(pow(OMEGA,2)-1)/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2));
        H[2]=(1+2*OMEGA*cos(Angle)+pow(OMEGA,2))/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2));
        H_Length=3;

        X_Length=Conv(H_Length,H,X_Length,X,pDen);
        for (int j=0;j<X_Length;j++)
            X[j]=pDen[j];
    }
}

/*!----------------------------------------------------------------------------
 * \brief 求高通的分子
 *
 * 和低通的区别只在于把方程中的z 换成-z。参考 Butter::Num_Butter_Lowpass
 *
 * ----------------------------------------------------------------------------*/ 
void Butter::Num_Butter_Highpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    int X_Length,H_Length;

    if (order%2==0)
    {
        X[0]=1;
        X_Length=1;
    }
    else
    {
        X[0]=OMEGA/(OMEGA+1);
        X[1]=-X[0];

        X_Length=2;

		pNum[0] = X[0];
		pNum[1] = X[1];
    }
    for (int i=1;i<=K;i++)
    {
        Angle=PI*(order-1+2*i)/(2*order);

        H[0]=pow(OMEGA,2)/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2));
        H[1]=-2*H[0];
        H[2]=H[0];

        H_Length=3;
        X_Length=Conv(H_Length,H,X_Length,X,pNum);

        for (int j=0;j<X_Length;j++)
            X[j]=pNum[j];
    }
}

/*!----------------------------------------------------------------------------
 * \param passType 通带类型, 高通 低通
 * \param fs 采样率
 * \param lowFre 过渡带的低频
 * \param heightFre 过渡带的高频
 * \param aPass 最大通带衰减
 * \param aStop 最小止带衰减
 *
 * ----------------------------------------------------------------------------*/
ChebyOne::ChebyOne(PassType passType, double fs, double lowFre, double heightFre,
	   	double aPass, double aStop) 
		: IIRFilterDesign(passType, fs)
{
	Init(lowFre, heightFre, aPass, aStop);
	
	GenerateCoe();
}

/*!----------------------------------------------------------------------------
 * \param passtype 通带类型, 高通 低通
 * \param fs 采样率
 * \param lowfre 过渡带的低频
 * \param heightfre 过渡带的高频
 * \param apass 使用默认 1 db
 * \param astop 使用默认 60 db
 *
 * \warning apass astop 使用默认值
 *
 * ----------------------------------------------------------------------------*/
ChebyOne::ChebyOne(PassType passType, double fs, double lowFre, double heightFre)
			: IIRFilterDesign(passType, fs)
{
	Init(lowFre, heightFre, 1, 60);

	GenerateCoe();
}

ChebyOne::~ChebyOne()
{
	ReleaseArray();
}

void ChebyOne::Init(double lowFre, double heightFre, double aPass, double aStop)
{
	this->lowFre = lowFre;
	this->heightFre = heightFre;

	Ap = aPass;
	As = aStop;
}

void ChebyOne::GenerateCoe()
{
	switch(passType)
	{
		case LOW_PASS:
			GenerateLowCoe();
			break;

		case HEIGHT_PASS:
			GenerateHeightCoe();
			break;

		default:
			break;
	}
}

void ChebyOne::GenerateLowCoe()
{
	Cheby_Lowpass_N();
                       
	AllocateArray();
    Den_Cheby_Lowpass();
	Num_Cheby_Lowpass();
}
void ChebyOne::GenerateHeightCoe()
{
	Cheby_Highpass_N();

	AllocateArray();
	Den_Cheby_Highpass();
	Num_Cheby_Highpass();
}

/*!----------------------------------------------------------------------------
 * \brief 
 *     幅频函数
 *
 * Chebyshev I 的幅频响应函数
 * \f[ 
 *   |H(\Omega)|^2 = 
 *   		\frac{C_{N}^{\phantom{N}{2}}(\frac{\Omega_{stop}}{\Omega})}
 *   					{C_{N}^{\phantom{N}{2}}(\frac{\Omega_{stop}}{\Omega}) + \varepsilon_{stop}^{\phantom{stop}{2}}}
 * \f]
 *
 * \param freq 要求的频率点
 *
 * \return 幅频 
 *
 * ----------------------------------------------------------------------------*/ 
double ChebyOne::MagResponse(double freq)
{
	double range = 0.0;

	double freqW = 0.0;
	double wpass = 0.0;
//	double wstop = 0.0;
	double Wpass = 0.0;
//	double Wstop = 0.0;

	double Epass = 0.0;
//	double Estop = 0.0;

	//TODO: 这里的计算应该和计算阶数的前面部分合起来提到上一层。 做个 xxx(fstop, fpass)的函数;
	if(passType == LOW_PASS)
	{
		wpass=2*PI*lowFre/fs;
//		wstop=2*PI*heightFre/fs;
		Wpass=tan(wpass/2);
//		Wstop=tan(wstop/2);
		freqW = tan((PI*freq)/fs);
	}
	else
	{
		wpass=2*PI*heightFre/fs;
//		wstop=2*PI*lowFre/fs;
		Wpass=cos(wpass/2)/sin(wpass/2);
//		Wstop=cos(wstop/2)/sin(wstop/2);
		freqW = cos((PI*freq)/fs)/sin((PI*freq)/fs);
	}

    Epass= sqrt(pow(10,Ap/10)-1);
//    Estop= sqrt(pow(10,As/10)-1);
	
	double CN_2 = pow(CN(order, freqW/Wpass), 2);

	range = 1.0/sqrt((1 + pow(Epass, 2)*CN_2));
	//range = 1.0/(1 + pow(Epass, 2)*CN_2);
	
		
	return range;
}


/*!----------------------------------------------------------------------------
 * \brief 
 *
 * 阶数N由下面公式求出:
 * \f[ 
 *   N_{exact} = \frac{\ln(e + \sqrt{e^{2} - 1})}{\ln(w + \sqrt{w^{2} - 1})}
 * \f] 
 *   
 * 定义a:
 * \f[ 
 *   a = \frac{1}{N}\ln(\frac{1}{\varepsilon_{pass}} + 
 *       \sqrt{\frac{1}{\varepsilon_{pass}^{\phantom{pass}{2}}} + 1})
 * \f] 
 * \f$ \Omega_{0} \f$ 为:
 * \f[ 
 *   \Omega_{0} = \Omega_{pass}\sinh a
 * \f] 
 *  
 * ----------------------------------------------------------------------------*/
void ChebyOne::Cheby_Lowpass_N()
{
    double wpass;
    double wstop;
    double Wpass;
    double Wstop;
    double Epass;
    double Estop;
    double e,w;
    double a;

    wpass=2*PI*lowFre/fs;
    wstop=2*PI*heightFre/fs;

    Wpass=tan(wpass/2);
    Wstop=tan(wstop/2);

    Epass= sqrt(pow(10,Ap/10)-1);
    Estop= sqrt(pow(10,As/10)-1);

    e=Estop/Epass;
    w=Wstop/Wpass;

    order=int(log(e+sqrt(pow(e,2)-1))/log(w+sqrt(pow(w,2)-1)))+1;

    if(order > 16)
    {
        throw std::logic_error("设计的滤波器不稳定!请重试!");
    }

    a=log(1.0/Epass+sqrt(1.0/pow(Epass,2)+1))/order;
    OMEGA=Wpass*sinh(a);
}

/*!----------------------------------------------------------------------------
 * \brief  生成低通系数分母
 *
 * 二阶基本节:
 * \f[
 * H_{i}(z) = \frac{G_{i}(1 + z^{-1})^2}{1 + a_{i1}z^{-1} +
 *            a_{i2}z^{-2}} \qquad i = 1,2,\ldots,K.
 * \f]
 *
 * 当阶数为奇的时候:
 * \f[
 * H_{0}(z) = \left\{ \begin{array}{ll}
 *            \sqrt{\frac{1}{1 + \varepsilon_{pass}^{\phantom{pass}{2}}}}& \textrm{当 ~N = 2K}\\
 *            \frac{G_{0}(1 + z^{-1})}{1 + a_{01}z^{-1}} & \textrm{当~N = 2K + 1}\\
 *            \end{array} \right.
 * \f]
 * 其中:
 * \f[
 *   G_{0} = \frac{\Omega_{0}}{\Omega_{0} + 1} \qquad, \qquad
 *   a_{01} = \frac{\Omega_{0} - 1}{\Omega_{0} + 1}
 * \f]
 *
 * 定义\f$ \theta_{i} \f$
 * \f[
 *   \theta_{i} = \frac{\pi}{2N}(N - 1 + 2i)
 * \f]
 *
 * \f$ a_{i1} a_{i2} \f$为:
 * \f[
 *   a_{i1} = \frac{2(\Omega_{0}^{\phantom{0}{2}} +
 *            \Omega_{i}^{\phantom{i}{2}} - 1)}{1 - 2\Omega_{0}\cos{\theta_{i}}
 *            + \Omega_{0}^{\phantom{0}{2}} + \Omega_{i}^{\phantom{i}{2}}}
 * \f]
 * \f[
 *   a_{i2} = \frac{1 + 2\Omega_{0}\cos\theta_{i} +
 *            \Omega_{0}^{\phantom{0}{2}} + 
 *            \Omega_{i}^{\phantom{i}{2}}}{1 -
 *            2\Omega_{0}\cos{\theta_{i}} +
 *            \Omega_{0}^{\phantom{0}{2}} + \Omega_{i}^{\phantom{i}{2}}}
 * \f]
 * 
 * ----------------------------------------------------------------------------*/
void ChebyOne::Den_Cheby_Lowpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wpass=tan(PI*lowFre/fs);
    int X_Length,H_Length;

    if (order%2==0)
    {
        X[0]=1;
        X_Length=1;
    }
    else
    {
        X[0]=1;
        X[1]=(OMEGA-1)/(OMEGA+1);
        X_Length=2;

		pDen[0] = X[0];
		pDen[1] = X[1];
    }
    for (int i=1;i<=K;i++)
    {
        Angle=PI*(order-1+2*i)/(2*order);
        Wi=Wpass*sin(Angle);

        H[0]=1;
        H[1]=2*(pow(OMEGA,2)+pow(Wi,2)-1)/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2)+pow(Wi,2));
        H[2]=(1+2*OMEGA*cos(Angle)+pow(OMEGA,2)+pow(Wi,2))/
             (1-2*OMEGA*cos(Angle)+pow(OMEGA,2)+pow(Wi,2));
        H_Length=3;

        X_Length=Conv(H_Length,H,X_Length,X,pDen);
        for (int j=0;j<X_Length;j++)
            X[j]=pDen[j];
    }
}

/*!----------------------------------------------------------------------------
 * \brief  求分子的系数, 参照求分母ChebyOne::Den_Cheby_Lowpass()
 *
 * 定义\f$ \Omega_{i} \f$
 * \f[
 *   \Omega_{i} = \Omega_{pass}\sin\theta_{i} \quad, \quad i= 1,2,3\ldots,K
 * \f]
 *
 * \f[
 * G_{i} = \frac{\Omega_{0}^{\phantom{0}{2}} +
 *         \Omega_{i}^{\phantom{i}{2}}}{1 - 2\Omega_{0}\cos{\theta_{i}} +
 *         \Omega_{0}^{\phantom{0}{2}} + \Omega_{i}^{\phantom{i}{2}}}\\
 * \f]
 *
 * 
 * ----------------------------------------------------------------------------*/
void ChebyOne::Num_Cheby_Lowpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wpass=tan(PI*lowFre/fs);
    int X_Length,H_Length;

    if (order%2==0)
    {
        X[0]=sqrt(1.0/pow(10,Ap/10));
        X_Length=1;
    }
    else
    {
        X[0]=OMEGA/(OMEGA+1);
        X[1]=X[0];
        X_Length=2;

		pNum[0] = X[0];
		pNum[1] = X[1];
    }
    for (int i=1;i<=K;i++)
    {
        Angle=PI*(order-1+2*i)/(2*order);
        Wi=Wpass*sin(Angle);

        H[0]=(pow(OMEGA,2)+pow(Wi,2))/(1-2*OMEGA*cos(Angle)+pow(OMEGA,2)+pow(Wi,2));
        H[1]=2*H[0];
        H[2]=H[0];
        H_Length=3;

        X_Length=Conv(H_Length,H,X_Length,X,pNum);
        for (int j=0;j<X_Length;j++)
            X[j]=pNum[j];
    }
}

void ChebyOne::Cheby_Highpass_N()
{
    double wpass;
    double wstop;
    double Wpass;
    double Wstop;
    double Epass;
    double Estop;
    double e,w;
    double a;

    wpass=2*PI*heightFre/fs;
    wstop=2*PI*lowFre/fs;

    Wpass=cos(wpass/2)/sin(wpass/2);
    Wstop=cos(wstop/2)/sin(wstop/2);

    Epass= sqrt(pow(10,Ap/10)-1);
    Estop= sqrt(pow(10,As/10)-1);

    e=Estop/Epass;
    w=Wstop/Wpass;

    order=int(log(e+sqrt(pow(e,2)-1))/log(w+sqrt(pow(w,2)-1)))+1;

    if(order > 16)
    {
        throw std::logic_error("设计的滤波器不稳定!请重试!");
    }

    a=log(1.0/Epass+sqrt(1.0/pow(Epass,2)+1))/order;
    OMEGA=Wpass*sinh(a);
}

void ChebyOne::Den_Cheby_Highpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wpass=cos(PI*heightFre/fs)/sin(PI*heightFre/fs);
    int X_Length,H_Length;

    if (order%2==0)
    {
        X[0]=1;
        X_Length=1;
    }
    else
    {
        X[0]=1;
        X[1]=-(OMEGA-1)/(OMEGA+1);
        X_Length=2;

		pDen[0] = X[0];
		pDen[1] = X[1];
    }
    for (int i=1;i<=K;i++)
    {
        Angle=PI*(order-1+2*i)/(2*order);
        Wi=Wpass*sin(Angle);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -