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

📄 filterdesign.~cpp

📁 脑电信号分析软件
💻 ~CPP
📖 第 1 页 / 共 3 页
字号:
        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];
    }
}

void ChebyOne::Num_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]=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];
    }
}

/*!----------------------------------------------------------------------------
 * \param passType 通带类型, 高通 低通
 * \param fs 采样率
 * \param lowFre 过渡带的低频
 * \param heightFre 过渡带的高频
 * \param aPass 最大通带衰减
 * \param aStop 最小止带衰减
 *
 * ----------------------------------------------------------------------------*/
ChebyTwo::ChebyTwo(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 使用默认值
 *
 * ----------------------------------------------------------------------------*/
ChebyTwo::ChebyTwo(PassType passType, double fs, double lowFre, double heightFre)
			: IIRFilterDesign(passType, fs)
{
	Init(lowFre, heightFre, 1, 60);

	GenerateCoe();
}

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

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

	Ap = aPass;
	As = aStop;
}

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

		case HEIGHT_PASS:
			GenerateHeightCoe();
			break;

		default:
			break;
	}
}
/*!----------------------------------------------------------------------------
 * \brief 生成低通系数
 *
 * ----------------------------------------------------------------------------*/
void ChebyTwo::GenerateLowCoe()
{
	Cheby2_Lowpass_N();
                       
	AllocateArray();
    Den_Cheby2_Lowpass();
	Num_Cheby2_Lowpass();

}

/*!----------------------------------------------------------------------------
 * \brief 生成高通系数
 *
 * ----------------------------------------------------------------------------*/ 
void ChebyTwo::GenerateHeightCoe()
{
	Cheby2_Highpass_N();

	AllocateArray();
	Den_Cheby2_Highpass();
	Num_Cheby2_Highpass();
}

/*!----------------------------------------------------------------------------
 * \brief 
 *     幅频函数
 *
 * Chebyshev II 的幅频响应函数
 * \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]
 *
 * \f$C_{N} \f$ 为切比雪夫多项式, 见IIRFilterDesign::CN(int N,double x);
 *
 * \param freq 要求的频率点
 *
 * \return 幅频
 *
 * ----------------------------------------------------------------------------*/
double ChebyTwo::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, Wstop/freqW), 2);

	range = CN_2/(CN_2 + pow(Estop, 2));
	//range = sqrt(CN_2/(CN_2 + pow(Estop, 2)));
	
	return range;
}

/*!----------------------------------------------------------------------------
 * \brief 计算阶数
 *
 * a 和 \f$ \Omega_{0} \f$ 由下面公式算出
 * \f[
 *   a = \frac{1}{N}\ln(\varepsilon_{stop} + 
 *       \sqrt{\varepsilon_{stop}^{\phantom{stop}{2}} + 1})
 * \f]
 * \f[
 *   \Omega_{0} = \frac{\Omega_{stop}}{\sinh a}
 * \f]
 *
 * 其它参考 ChebyOne::Cheby_Lowpass_N() 
 * 
 * ----------------------------------------------------------------------------*/
void ChebyTwo::Cheby2_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(Estop+sqrt(pow(Estop,2)+1))/order;
    OMEGA=Wstop/sinh(a);
}

/*!----------------------------------------------------------------------------
 * \brief  Chebyshev II 低通分母
 *
 * 先根据阶数的奇偶进行初始化:
 * 如果阶数为奇:
 * \f[
 *   H_{0}(z) = \left\{ \begin{array}{ll} $1$& \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} \quad,\quad 
 *   a_{01} = \frac{\Omega_{0} - 1}{\Omega{0} + 1}
 * \f]
 *
 * 如果为偶,二阶节公式(求分母部分):
 * \f[ 
 *   H_{i}(z) = \frac{G_{i}(1+b_{i1}z^{-1}+z^{-2})}{1+a_{i1}z^{-1}+a_{i2}z^{-2}}
 *              \quad,\quad i = 1,2,\ldots,K
 * \f]
 *
 * 变量H[1]:
 * \f[ 
 *   a_{i1} = \frac{2(1 - \Omega_{0}^{\phantom{0}{-2}} - 
 *            \Omega_{i}^{\phantom{i}{-2}})}{1 - 2\Omega_{0}^{\phantom{0}{-1}}\cos\theta_{i} + 
 *            \Omega_{0}^{\phantom{0}{-2}} + \Omega_{i}^{\phantom{i}{-2}}}
 * \f]
 * 变量H[2]:
 * \f[ 
 *   a_{i2} = \frac{1 + 2\Omega_{0}^{\phantom{0}{-1}}\cos\theta_{i} + 
 *            \Omega_{0}^{\phantom{0}{-2}} + \Omega_{i}^{\phantom{i}{-2}}}{1 - 
 *            2\Omega_{0}^{\phantom{0}{-1}}\cos\theta_{i} + 
 *            \Omega_{0}^{\phantom{0}{-2}} + \Omega_{i}^{\phantom{i}{-2}}}
 * \f]
 * 变量Wi:
 * \f[ 
 *   \Omega_{i} = \frac{\Omega_{stop}}{\sin \theta_{i}} \quad,\quad 
 *   i = 1,2,\ldots,K
 * \f]
 * 最后卷积求出分母系数
 *
 * ----------------------------------------------------------------------------*/
void ChebyTwo::Den_Cheby2_Lowpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wstop=tan(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=Wstop/sin(Angle);
        H[0]=1;
        H[1]=2*(1-pow(OMEGA,-2)-pow(Wi,-2))/(1-2*cos(Angle)/OMEGA+pow(OMEGA,-2)+pow(Wi,-2));
        H[2]=(1+2*cos(Angle)/OMEGA+pow(OMEGA,-2)+pow(Wi,-2))/
             (1-2*cos(Angle)/OMEGA+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  生成低通分子
 *
 * 参考 ChebyTwo::Den_Cheby2_Lowpass()
 *
 * 分子中:
 * \f[ 
 *   G_{i} = \frac{1 + \Omega_{i}^{\phantom{i}{-2}}}{1 - 
 *           2\Omega_{0}^{\phantom{0}{-1}}\cos\theta_{i} + 
 *           \Omega_{0}^{\phantom{0}{-2}} + \Omega_{i}^{\phantom{i}{-2}}}
 * \f] 
 * \f[ 
 *   b_{i1} = 2\frac{1 - \Omega_{i}^{\phantom{i}{-2}}}{1 + \Omega_{i}^{\phantom{i}{-2}}}
 * \f]
 *
 * ----------------------------------------------------------------------------*/
void ChebyTwo::Num_Cheby2_Lowpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wstop=tan(PI*heightFre/fs);
    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);
        Wi=Wstop/sin(Angle);

        H[0]=(1+pow(Wi,-2))/(1-2*cos(Angle)/OMEGA+pow(OMEGA,-2)+pow(Wi,-2));
        H[1]=H[0]*2*(1-pow(Wi,-2))/(1+pow(Wi,-2));
        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 ChebyTwo::Cheby2_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(Estop+sqrt(pow(Estop,2)+1))/order;
    OMEGA=Wstop/sinh(a);
}

void ChebyTwo::Den_Cheby2_Highpass()
{
    int K=order/2;

    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wstop=cos(PI*lowFre/fs)/sin(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=Wstop/sin(Angle);

        H[0]=1;
        H[1]=-2*(1-pow(OMEGA,-2)-pow(Wi,-2))/(1-2*cos(Angle)/OMEGA+pow(OMEGA,-2)+pow(Wi,-2));
        H[2]=(1+2*cos(Angle)/OMEGA+pow(OMEGA,-2)+pow(Wi,-2))/
             (1-2*cos(Angle)/OMEGA+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];
    }
}

void ChebyTwo::Num_Cheby2_Highpass()
{
    int K=order/2;
    double X[20];
    double H[3];
    double Angle;
    double Wi;
    double Wstop=cos(PI*lowFre/fs)/sin(PI*lowFre/fs);
    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);
        Wi=Wstop/sin(Angle);

        H[0]=(1+pow(Wi,-2))/(1-2*cos(Angle)/OMEGA+pow(OMEGA,-2)+pow(Wi,-2));
        H[1]=-2*H[0]*(1-pow(Wi,-2))/(1+pow(Wi,-2));
        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];
    }
}

Notch::Notch(PassType passType, double fs, double fre)
		:IIRFilterDesign(passType, fs)
{
	this->fre = fre;

	GenerateCoe();
}

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

void Notch::GenerateCoe()
{
	order = 2;
	AllocateArray();

	GenerateNotch();
}

/*!----------------------------------------------------------------------------
 * \brief 
 *
 * 陷波器的中心频率是:
 * \f[ 
 *   \omega_{0} = \frac{2\pi f_{0}}{f_{s}}
 * \f] 
 *   
 * 陷波器只有两阶:
 * \f[ 
 *   b_{1} = -2r\cos\omega_{0} \quad,\quad b_{2} = r^{2}
 * \f] 
 * \f[ 
 *   a_{1} = -2R\cos\omega_{0} \quad,\quad a_{2} = R^{2}
 * \f] 
 *
 * ----------------------------------------------------------------------------*/ 
void Notch::GenerateNotch()
{
    int f=fre;
    double R=SETR; //越接近1,陷波器宽度越窄
    double r=SETr; //越接近1,陷波器衰减越厉害

    OMEGA=2*PI*f/fs;
    pDen[1]=-2*R*cos(OMEGA);
    pDen[2]=pow(R,2);
    pNum[0]=1;
    pNum[1]=-2*r*cos(OMEGA);
    pNum[2]=pow(r,2);
}


/*!----------------------------------------------------------------------------
 * \brief 
 *     幅频函数
 *
 * Notch 的幅频响应函数
 * \f[ 
 *   \frac{(1 - 2r\cos(\omega - \Omega_{0}) + r^2)
 *         (1 - 2r\cos(\omega + \Omega_{0}) + r^2)} 
 *        {(1 - 2R\cos(\omega - \Omega_{0}) + R^2)
 *         (1 - 2R\cos(\omega + \Omega_{0}) + R^2)}
 * \f]
 *
 * \param freq 要求的频率点
 *
 * \return 幅频
 *
 * ----------------------------------------------------------------------------*/ 
double Notch::MagResponse(double freq)
{
	double range = 0.0;
	double r = SETr;
	double R = SETR;

	double freqw = (2*PI*freq)/fs;

	range = (1-2*r*cos(freqw-OMEGA)+pow(r,2))*(1-2*r*cos(freqw+OMEGA)+pow(r,2))
                    /((1-2*R*cos(freqw-OMEGA)+pow(R,2))*(1-2*R*cos(freqw+OMEGA)+pow(R,2)));	

	return range;
}
#endif

⌨️ 快捷键说明

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