[数字信号处理]C语言设计数字低通滤波器IIR滤波器(可以出图)

iIR数字滤波器设计在工程实践中具有十分重要的作用,使用C语言实现对深化理解滤波器设计的理论和功能具有深远的意义,凡是选择本项目并能达到项目基本要求可以获得90分以上的成绩。
要求:报告中必须有能够实现以下设计指标的数字低通滤波器的证明:通带和阻带截止频率分别为0.2π和0.35π,通带最大衰减为1dB,阻带最小衰减为10dB。
提示:理论知识参考《数字信号处理》教材。

这是c语言课程设计,写一个文章来记录一下,方便以后查漏补缺,

基础知识

低通滤波器的主要性能指标有以下几个:通带截止频率fp、阻带截止频率fs、通带衰减 ( Ap)、阻带衰减 ( As) 以及归一化频率时需要用到的-3dB的转折频率fc。

根据给定的参数设计模拟滤波器,然后进行变数变换,求取数字滤波器的方法,称为滤波器的间接设计。做为数字滤波器的设计基础的模拟滤波器,称之为原型滤波器。
低通滤波器的主要性能指标
设计方法

模拟滤波器的设计

巴特沃斯滤波器因其在通带内的幅值特性具有最大平坦的特性而闻名,是四种经典滤波器中最简单的,巴特沃斯滤波器只需要两个参数表征,滤波器的阶数N和-3dB处的截止频率
。其幅度平方函数为:
在这里插入图片描述

在这里插入图片描述

N是滤波器的阶数,从幅度平方函数可以看出,N阶滤波器有2N个极点,而且这2N个极点均布在一个圆上,圆的半径为,称之为巴特沃斯圆,巴特沃斯滤波器系统是一个线性系统,要使其稳定,其极点必须位于S平面的左半平面,所以取左半平面内的N个极点作为滤波器的极点,滤波器就是稳定的了,求出极点之后,计算模拟滤波器的系数as、bs,然后通过双线性变换(不懂得自行查书)由模拟域到数字域,求出系数az和bz 。最后通过差分方程就可以计算滤波结果了。
在这里插入图片描述

次数N的计算为
在这里插入图片描述

巴特沃斯低通滤波器的传递函数,可由其振幅特性的分母多项式求得。其分母多项式

在这里插入图片描述

根据S解开,可以得到极点。这里,为了方便处理,我们分为两种情况去解这个方程。当N为偶数的时候,

在这里插入图片描述

这里,使用了欧拉公式在这里插入图片描述
。同样的,当N为奇数的时候,
在这里插入图片描述

同样的,这里也使用了欧拉公式。归纳以上,极点的解为

在这里插入图片描述

上式所求得的极点,是在s平面内,在半径为Ωc的圆上等间距的点,其数量为2N个。为了使得其IIR滤波器稳定,那么,只能选取极点在S平面左半平面的点。选定了稳定的极点之后,其模拟滤波器的传递函数就可由下式求得。

在这里插入图片描述
变换为Z域
在这里插入图片描述
然后通过差分方程就可以计算滤波结果了
在这里插入图片描述

C语言的实现

1.求阶数

在这里插入图片描述
代码:

N = ceil(0.5*( log10 (( pow (10, Stopband_attenuation/10) - 1)/
	   ( pow (10, Passband_attenuation/10) - 1)) / log10 (Stopband/Passband) ));

2.求极点

在这里插入图片描述

for(k = 0;k <= ((2*N)-1) ; k++)
    {
		if(Cutoff*cos((2*k+N-1)*(pi/(2*N))) < 0.0)
         {	   
            poles[count].x = -Cutoff*cos((2*k+N-1)*(pi/(2*N)));
			poles[count].y = -Cutoff*sin((2*k+N-1)*(pi/(2*N)));	  
			 count++;
	        if (count == N) break;
         }
    } 

这里面 poles 是复数类型_complex

_Complex是C99新增的关键字,表示一种基本数据类型——复数

该类型的出现主要是为了解决工程和数学计算上很多涉及到复数计算的情况

3.求模拟滤波器系数

计算出稳定的极点之后,就可以进行传递函数的计算了。传递的函数的计算,就像下式一样
在这里插入图片描述
这里,为了得到模拟滤波器的系数,需要将分母乘开。很显然,这里的极点不一定是整数,或者来说,这里的乘开需要做复数运算。其复数的乘法代码如下,


//复数乘
_complex ComplexMul(_complex a, _complex b)
{
	_complex c;
	c.x = a.x*b.x - a.y*b.y;
	c.y = a.y*b.x + a.x*b.y;
	return c;
}

有了乘法代码之后,我们现在简单的情况下,看看其如何计算其滤波器系数。我们做如下假设`
在这里插入图片描述

这个时候,其传递函数为

在这里插入图片描述

将其乘开,其大致的关系就像下图所示一样。
在这里插入图片描述
计算的关系一目了然,这样的话,实现就简单多了。高阶的情况下也一样,重复这种计算就可以了。其代码为

     Res[0].x = poles[0].x; 
     Res[0].y = poles[0].y;
 
     Res[1].x = 1; 
     Res[1].y= 0;
 
    for(count_1 = 0;count_1 < N-1;count_1++)//N个极点相乘次数
    {
	     for(count = 0;count <= count_1 + 2;count++)
	     {
	          if(0 == count)
			  {
 	              Res_Save[count] = ComplexMul( Res[count], poles[count_1+1] );  
			  }
 
	          else if((count_1 + 2) == count)
	          {
	                Res_Save[count].x += Res[count - 1].x;
					Res_Save[count].y += Res[count - 1].y;	
	          }		  
		    else 
		    {
				Res_Save[count] = ComplexMul( Res[count], poles[count_1+1] );	               				
			    Res_Save[count].x += Res[count - 1].x;
			    Res_Save[count].y += Res[count - 1].y;	
		    }
	     }
 
	     for(count = 0;count <= N;count++)//Res[i]=a(i),i越大次数越高
	     {
			Res[count].x = Res_Save[count].x; 
			Res[count].y = Res_Save[count].y;
				 
		    *(a + N - count) = Res[count].x;
	     }				 
	}
 
     *(b+N) = *(a+N);

到此,我们就可以得到一个模拟滤波器巴特沃斯低通滤波器了。

4.S变Z

公式
在这里插入图片描述
在这里插入图片描述

代码

int Count = 0,Count_1 = 0,Count_2 = 0,Count_Z = 0;
      double *Res, *Res_Save;
	  Res = new double[N+1]();
	  Res_Save = new double[N+1](); 
	  memset(Res, 0, sizeof(double)*(N+1));
	  memset(Res_Save, 0, sizeof(double)*(N+1));
 
      	for(Count_Z = 0;Count_Z <= N;Count_Z++)
		{
            *(az+Count_Z)  = 0;
		    *(bz+Count_Z)  = 0;
		}
 
	
	for(Count = 0;Count<=N;Count++)
	{    	
	      for(Count_Z = 0;Count_Z <= N;Count_Z++)
	      {
	      	    Res[Count_Z] = 0;
				Res_Save[Count_Z] = 0;	 
	      }
          Res_Save [0] = 1;
	
	      for(Count_1 = 0; Count_1 < N-Count;Count_1++)//计算(1-Z^-1)^N-Count的系数,
	      {												//Res_Save[]=Z^-1多项式的系数,从常数项开始
				for(Count_2 = 0; Count_2 <= Count_1+1;Count_2++)
				{
					 if(Count_2 == 0)  
					 {
					   Res[Count_2] += Res_Save[Count_2];
					 } 	
 
					 else if((Count_2 == (Count_1+1))&&(Count_1 != 0))  
					 {
						 Res[Count_2] += -Res_Save[Count_2 - 1];   
					 } 
 
					 else  
					 {
						 Res[Count_2] += Res_Save[Count_2] - Res_Save[Count_2 - 1];
					 }				 
				}
 
		      for(Count_Z = 0;Count_Z<= N;Count_Z++)
		      {
 				   Res_Save[Count_Z]  =  Res[Count_Z] ;
				   Res[Count_Z]  = 0;   
		      }	
	      }
 
		for(Count_1 = (N-Count); Count_1 < N;Count_1++)//计算(1-Z^-1)^N-Count*(1+Z^-1)^Count的系数,
	    {												//Res_Save[]=Z^-1多项式的系数,从常数项开始
                for(Count_2 = 0; Count_2 <= Count_1+1;Count_2++)
				{
	      			 if(Count_2 == 0)  
					 {
					   Res[Count_2] += Res_Save[Count_2];
					 } 	
 
					 else if((Count_2 == (Count_1+1))&&(Count_1 != 0))  
					 {
						 Res[Count_2] += Res_Save[Count_2 - 1];
					  } 
 
					 else  
					 {
						  Res[Count_2] += Res_Save[Count_2] + Res_Save[Count_2 - 1];
					 }				 
				}
 
		      for(Count_Z = 0;Count_Z<= N;Count_Z++)
		      {
 		          Res_Save[Count_Z]  =  Res[Count_Z] ;
			      Res[Count_Z]  = 0;    
		      }
	     }
 
		for(Count_Z = 0;Count_Z<= N;Count_Z++)
		{
            *(az+Count_Z) +=  pow(2,N-Count)  *  (*(as+Count)) * Res_Save[Count_Z];
			*(bz+Count_Z) +=  (*(bs+Count)) * Res_Save[Count_Z];		       
		 }	
 
	}//最外层for循环
   
     for(Count_Z = N;Count_Z >= 0;Count_Z--)
     {
          *(bz+Count_Z) =  (*(bz+Count_Z))/(*(az+0));
          *(az+Count_Z) =  (*(az+Count_Z))/(*(az+0));
     }

5.差分方程计算滤波结果

在这里插入图片描述
采用滤波器直接II型结构,可以减少一半的中间缓存内存,具体代码如下:

double FiltButter(double *pdAz,	//滤波器参数表1
                  double *pdBz,	//滤波器参数表2
				  int	nABLen,	//参数序列的长度
				  double dDataIn,//输入数据
				  double *pdBuf)	//数据缓冲区
{
	int	i;
	int	nALen;
	int nBLen;
	int	nBufLen;
	double	dOut;
 
	if( nABLen<1 )return 0.0;
	//根据参数,自动求取序列有效长度
	nALen = nABLen;
	for( i=nABLen-1; i; --i )
	{
		if( *(pdAz+i) != 0.0 )//从最后一个系数判断是否为0
		{
			nALen = i+1;	
			break;
		}
	}
	//printf("%lf ", nALen);
	if( i==0 ) nALen = 0;
 
	nBLen = nABLen;
	for( i=nABLen-1; i; --i )
	{
		if( *(pdBz+i) != 0.0 )
		{
			nBLen = i+1;
			
			break;
		}
	}
	//printf("%lf ", nBLen);
	if( i==0 ) nBLen = 0;
	//计算缓冲区有效长度
	nBufLen = nALen;
	if( nALen < nBLen)
		nBufLen = nBLen;
 
	//滤波: 与系数a卷乘
	dOut = ( *pdAz ) * dDataIn;  // a(0) * x(i)   
 
	for( i=1; i<nALen; i++)	// a(i) * w(n-i),i=1toN
	{
		dOut -= *(pdAz+i) * *(pdBuf + (nBufLen - 1) - i);
	} 
 
	//卷乘结果保存为缓冲序列的最后一个
	*(pdBuf + nBufLen - 1) = dOut;
	
	//滤波: 与系数b卷乘
	dOut = 0.0;
	for( i=0; i<nBLen; i++)	// b(i) * w(n-i)
	{    	
		dOut += *(pdBz+i) * *(pdBuf + (nBufLen - 1) - i);
	}
 
	//丢弃缓冲序列中最早的一个数, 最后一个数清零
	for( i=0; i<nBufLen-1; i++)
	{
		*(pdBuf + i) = *(pdBuf + i + 1);
	}
	*(pdBuf + nBufLen - 1) = 0;
	
	//返回输出值
	return dOut; 
}

完整程序

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <malloc.h>
#include <graphics.h>
#include<conio.h>//getch()函数头文件
using namespace std;

#define     pi     ((double)3.1415926)

struct DESIGN_SPECIFICATION
{
	double Passband;
	double Stopband;
	double Passband_attenuation;
	double Stopband_attenuation;
};

//复数乘
_complex ComplexMul(_complex a, _complex b)
{
	_complex c;
	c.x = a.x*b.x - a.y*b.y;
	c.y = a.y*b.x + a.x*b.y;
	return c;
}

//复数除
_complex ComplexDiv(_complex a, _complex b)
{
	_complex c;
	double dTmp = b.x * b.x + b.y * b.y;
	//除数太小,防溢出
	if (dTmp < 1.0E-300) {
		c.x = 1.0E300;
		c.y = 1.0E300;
		return c;
	}
	c.x = (a.x * b.x + a.y * b.y) / dTmp;
	c.y = (a.x * b.y - a.y * b.x) / dTmp;
	return c;
}

//计算滤波器阶数N
int Buttord(double Passband,
	double Stopband,
	double Passband_attenuation,
	double Stopband_attenuation)
{
	int N;

	printf("Wp =  %lf  [rad/sec] \n", Passband);
	printf("Ws =  %lf  [rad/sec] \n", Stopband);
	printf("Ap =  %lf  [dB] \n", Passband_attenuation);
	printf("As =  %lf  [dB] \n", Stopband_attenuation);
	printf("--------------------------------------------------------\n");

	N = ceil(0.5*(log10((pow(10, Stopband_attenuation / 10) - 1) /
		(pow(10, Passband_attenuation / 10) - 1)) / log10(Stopband / Passband)));

	return (int)N;
}

//计算S平面的滤波器系数
int Butter(int N, double Cutoff, double *a, double *b)
{
	double dk = 0;
	int k = 0;
	int count = 0, count_1 = 0;

	_complex *poles, *Res, *Res_Save;
	poles = new _complex[N]();
	Res = new _complex[N + 1]();
	Res_Save = new _complex[N + 1]();
	memset(poles, 0, sizeof(_complex)*(N));
	memset(Res, 0, sizeof(_complex)*(N + 1));
	memset(Res_Save, 0, sizeof(_complex)*(N + 1));

	if ((N % 2) == 0) dk = 0.5;
	else dk = 0;

	for (k = 0; k <= ((2 * N) - 1); k++)
	{
		if (Cutoff*cos((2 * k + N - 1)*(pi / (2 * N))) < 0.0)
		{
			poles[count].x = -Cutoff * cos((2 * k + N - 1)*(pi / (2 * N)));
			poles[count].y = -Cutoff * sin((2 * k + N - 1)*(pi / (2 * N)));
			count++;
			if (count == N) break;
		}
	}

	printf("Pk =   \n");

	for (count = 0; count < N; count++)
	{
		printf("(%lf) + (%lf i) \n", -poles[count].x, -poles[count].y);
	}

	printf("--------------------------------------------------------\n");

	Res[0].x = poles[0].x;
	Res[0].y = poles[0].y;

	Res[1].x = 1;
	Res[1].y = 0;

	for (count_1 = 0; count_1 < N - 1; count_1++)//N个极点相乘次数
	{
		for (count = 0; count <= count_1 + 2; count++)
		{
			if (0 == count)
			{
				Res_Save[count] = ComplexMul(Res[count], poles[count_1 + 1]);
			}

			else if ((count_1 + 2) == count)
			{
				Res_Save[count].x += Res[count - 1].x;
				Res_Save[count].y += Res[count - 1].y;
			}
			else
			{
				Res_Save[count] = ComplexMul(Res[count], poles[count_1 + 1]);
				Res_Save[count].x += Res[count - 1].x;
				Res_Save[count].y += Res[count - 1].y;
			}
		}

		for (count = 0; count <= N; count++)//Res[i]=a(i),i越大次数越高
		{
			Res[count].x = Res_Save[count].x;
			Res[count].y = Res_Save[count].y;

			*(a + N - count) = Res[count].x;
		}
	}

	*(b + N) = *(a + N);
	//*(b+N) = pow(Cutoff,N);	
	//------------------------打印  bs  as  ---------------------------------//
	printf("bs =  [");
	for (count = 0; count <= N; count++)
	{
		printf("%lf ", *(b + count));
	}
	printf(" ] \n");

	printf("as =  [");
	for (count = 0; count <= N; count++)
	{
		printf("%lf ", *(a + count));
	}
	printf(" ] \n");

	printf("--------------------------------------------------------\n");

	delete[]poles;
	delete[]Res;
	delete[]Res_Save;

	return (int)1;
}

//双线性Z变换,S->Z
int Bilinear(int N,
	double *as, double *bs,
	double *az, double *bz)
{
	int Count = 0, Count_1 = 0, Count_2 = 0, Count_Z = 0;
	double *Res, *Res_Save;
	Res = new double[N + 1]();
	Res_Save = new double[N + 1]();
	memset(Res, 0, sizeof(double)*(N + 1));
	memset(Res_Save, 0, sizeof(double)*(N + 1));

	for (Count_Z = 0; Count_Z <= N; Count_Z++)
	{
		*(az + Count_Z) = 0;
		*(bz + Count_Z) = 0;
	}


	for (Count = 0; Count <= N; Count++)
	{
		for (Count_Z = 0; Count_Z <= N; Count_Z++)
		{
			Res[Count_Z] = 0;
			Res_Save[Count_Z] = 0;
		}
		Res_Save[0] = 1;

		for (Count_1 = 0; Count_1 < N - Count; Count_1++)//计算(1-Z^-1)^N-Count的系数,
		{												//Res_Save[]=Z^-1多项式的系数,从常数项开始
			for (Count_2 = 0; Count_2 <= Count_1 + 1; Count_2++)
			{
				if (Count_2 == 0)
				{
					Res[Count_2] += Res_Save[Count_2];
				}

				else if ((Count_2 == (Count_1 + 1)) && (Count_1 != 0))
				{
					Res[Count_2] += -Res_Save[Count_2 - 1];
				}

				else
				{
					Res[Count_2] += Res_Save[Count_2] - Res_Save[Count_2 - 1];
				}
			}

			for (Count_Z = 0; Count_Z <= N; Count_Z++)
			{
				Res_Save[Count_Z] = Res[Count_Z];
				Res[Count_Z] = 0;
			}
		}

		for (Count_1 = (N - Count); Count_1 < N; Count_1++)//计算(1-Z^-1)^N-Count*(1+Z^-1)^Count的系数,
		{												//Res_Save[]=Z^-1多项式的系数,从常数项开始
			for (Count_2 = 0; Count_2 <= Count_1 + 1; Count_2++)
			{
				if (Count_2 == 0)
				{
					Res[Count_2] += Res_Save[Count_2];
				}

				else if ((Count_2 == (Count_1 + 1)) && (Count_1 != 0))
				{
					Res[Count_2] += Res_Save[Count_2 - 1];
				}

				else
				{
					Res[Count_2] += Res_Save[Count_2] + Res_Save[Count_2 - 1];
				}
			}

			for (Count_Z = 0; Count_Z <= N; Count_Z++)
			{
				Res_Save[Count_Z] = Res[Count_Z];
				Res[Count_Z] = 0;
			}
		}

		for (Count_Z = 0; Count_Z <= N; Count_Z++)
		{
			*(az + Count_Z) += pow(2, N - Count)  *  (*(as + Count)) * Res_Save[Count_Z];
			*(bz + Count_Z) += (*(bs + Count)) * Res_Save[Count_Z];
		}

	}//最外层for循环

	for (Count_Z = N; Count_Z >= 0; Count_Z--)
	{
		*(bz + Count_Z) = (*(bz + Count_Z)) / (*(az + 0));
		*(az + Count_Z) = (*(az + Count_Z)) / (*(az + 0));
	}


	//------------------------display---------------------------------//
	printf("bz =  [");
	for (Count_Z = 0; Count_Z <= N; Count_Z++)
	{
		printf("%lf ", *(bz + Count_Z));
	}
	printf(" ] \n");
	printf("az =  [");
	for (Count_Z = 0; Count_Z <= N; Count_Z++)
	{
		printf("%lf ", *(az + Count_Z));
	}
	printf(" ] \n");
	printf("--------------------------------------------------------\n");

	delete[]Res;
	delete[]Res_Save;
	return (int)1;
}

// 执行滤波
// 返回值: 滤波处理后的数
double FiltButter(double *pdAz,	//滤波器参数表1
	double *pdBz,	//滤波器参数表2
	int	nABLen,	//参数序列的长度
	double dDataIn,//输入数据
	double *pdBuf)	//数据缓冲区
{
	int	i;
	int	nALen;
	int nBLen;
	int	nBufLen;
	double	dOut;

	if (nABLen < 1)return 0.0;
	//根据参数,自动求取序列有效长度
	nALen = nABLen;
	for (i = nABLen - 1; i; --i)
	{
		if (*(pdAz + i) != 0.0)//从最后一个系数判断是否为0
		{
			nALen = i + 1;
			break;
		}
	}
	//printf("%lf ", nALen);
	if (i == 0) nALen = 0;

	nBLen = nABLen;
	for (i = nABLen - 1; i; --i)
	{
		if (*(pdBz + i) != 0.0)
		{
			nBLen = i + 1;

			break;
		}
	}
	//printf("%lf ", nBLen);
	if (i == 0) nBLen = 0;
	//计算缓冲区有效长度
	nBufLen = nALen;
	if (nALen < nBLen)
		nBufLen = nBLen;

	//滤波: 与系数a卷乘
	dOut = (*pdAz) * dDataIn;  // a(0) * x(i)   

	for (i = 1; i < nALen; i++)	// a(i) * w(n-i),i=1toN
	{
		dOut -= *(pdAz + i) * *(pdBuf + (nBufLen - 1) - i);
	}

	//卷乘结果保存为缓冲序列的最后一个
	*(pdBuf + nBufLen - 1) = dOut;

	//滤波: 与系数b卷乘
	dOut = 0.0;
	for (i = 0; i < nBLen; i++)	// b(i) * w(n-i)
	{
		dOut += *(pdBz + i) * *(pdBuf + (nBufLen - 1) - i);
	}

	//丢弃缓冲序列中最早的一个数, 最后一个数清零
	for (i = 0; i < nBufLen - 1; i++)
	{
		*(pdBuf + i) = *(pdBuf + i + 1);
	}
	*(pdBuf + nBufLen - 1) = 0;

	//返回输出值
	return dOut;
}

int main(void)
{
	int count;
	double Fcutoff;

	struct DESIGN_SPECIFICATION IIR_Filter;

	IIR_Filter.Passband = (double)((pi*2)/10);   //通带截止频率[rad]
	IIR_Filter.Stopband = (double)(( pi*35)/100);   //阻带截止频率[rad]
	IIR_Filter.Passband_attenuation = 1;        //通带最大衰减[dB]
	IIR_Filter.Stopband_attenuation = 10;       //阻带最小衰减[dB]

	int N;

	IIR_Filter.Passband = 2 * tan((IIR_Filter.Passband) / 2);   //[rad/sec]
	IIR_Filter.Stopband = 2 * tan((IIR_Filter.Stopband) / 2);   //[rad/sec]

	N = Buttord(IIR_Filter.Passband,
		IIR_Filter.Stopband,
		IIR_Filter.Passband_attenuation,
		IIR_Filter.Stopband_attenuation);
	printf("N:  %d  \n", N);

	Fcutoff = IIR_Filter.Passband / (pow((pow(10, 0.1*IIR_Filter.Passband_attenuation) - 1), 1.0 / (2 * N)));

	printf("Wc:  %lf  \n", Fcutoff);
	printf("--------------------------------------------------------\n");

	double *as = new double[N + 1]();
	double *bs = new double[N + 1]();
	memset(as, 0, sizeof(double)*(N + 1));
	memset(bs, 0, sizeof(double)*(N + 1));

	Butter(N, Fcutoff, as, bs);//计算模拟滤波器系数

	double *az;
	double *bz;
	az = new double[N + 1]();
	bz = new double[N + 1]();
	memset(az, 0, sizeof(double)*(N + 1));
	memset(bz, 0, sizeof(double)*(N + 1));

	Bilinear(N, as, bs, az, bz);	//模拟变为数字滤波器

	//生成叠加信号
	printf("	请输入信号1频率			单位 Hz	\n");
	double  w1, w2;
	scanf("%lf", &w1);  
	printf("	请输入信号2频率			单位 Hz	\n");  
	scanf("%lf", &w2);  
	printf("采样频率为 10kHz \n");
	FILE* Input_Data1;
	Input_Data1 = fopen("E:\\yssj.txt", "w");
	printf("生成原始叠加信号并且保存到E:\\yssj.txt\n");
	double t, s1;
	for (int i = 0; i < 10000; i++)//4秒,产生更多数据
	{
		t = i / 10000.0;				//采样频率
		s1 = sin(2 * pi *w1 * t) + sin(2 * pi *w2* t);//设定频率为w1Hz+w2hz
		fprintf(Input_Data1, "%lf,\n", s1);
	}

	fclose(Input_Data1);

	char   s[100];
	int    length;
	double *data_Buffer;
	data_Buffer = (double *)malloc(sizeof(double)*(N + 1));
	memset(data_Buffer, 0, sizeof(double)*(N + 1));

	double Output = 0;

	FILE* Input_Data;
	FILE* Output_Data;
	Input_Data = fopen("E:\\yssj.txt", "r");
	Output_Data = fopen("E:\\lbh.txt", "w");

	length = N + 1;
	long DataCnt = 0;
	for (long j = 0; !feof(Input_Data); j++)
	{

		fscanf(Input_Data, "%s\n", &s);
		DataCnt++;
	}
//	cout<<DataCnt<<"\n";
	rewind(Input_Data);

	double *D = new double[DataCnt]();

	for (int i = 0; i < DataCnt; i++)
	{
		fscanf(Input_Data, "%s\n", &s);
		D[i] = atof(s);
		Output = FiltButter(az,bz,length,D[i],data_Buffer);
		fprintf(Output_Data, "%lf\n", Output);
		//cout<<Output<<"\n";
	}

	free(data_Buffer);
	fclose(Input_Data);
	fclose(Output_Data);
	cout << "按任意键绘制图形" << "\n";

	_getch();

	Input_Data = fopen("E:\\yssj.txt", "r");
	Input_Data1 = fopen("E:\\lbh.txt", "r");
	char   s11[100];
	
	long DataCnt1 = 0;
	for (long j = 0; !feof(Input_Data); j++)
	{

		fscanf(Input_Data, "%s\n", &s);
		DataCnt++;
	}
	for (long j = 0; !feof(Input_Data1); j++)
	{

		fscanf(Input_Data1, "%s\n", &s11);
		DataCnt1++;
	}
	rewind(Input_Data);
	rewind(Input_Data1);
	double y1=0, x1=0;
	double *D1 = new double[DataCnt]();
	initgraph(800, 1080); // 初始化640x480的绘图屏幕
	for (int i = 0; i < DataCnt; i++)
	{
		fscanf(Input_Data, "%s\n", &s);
		D1[i] = atof(s);
		s1 = D1[i];
		t = i / 10000.0;				//采样频率
		line(x1 * 50000, 200 + y1 * 100, t * 50000, 200 + s1 * 100);
		x1 = t;
		y1 = s1;
	}
	y1 = 0;
	x1 = 0;

	for (int i = 0; i < DataCnt1; i++)
	{
		fscanf(Input_Data1, "%s\n", &s);
		D1[i] = atof(s);
		s1 = D1[i];
		t = i / 10000.0;				//采样频率
		line(x1 * 50000, 600 + y1 * 100, t * 50000, 600 + s1 * 100);
		x1 = t;
		y1 = s1;
	}
//	printf("Finish \n");
	delete[]D;
	delete[]as;
	delete[]bs;
	delete[]az;
	delete[]bz;


	_getch();
	closegraph();
	fclose(Input_Data);
	fclose(Input_Data1);
	return (int)0;

}

运行结果

在这里插入图片描述

在这里插入图片描述

参考资料:http://blog.csdn.net/zhoufan900428/article/details/9069475
具体源码 : https://download.csdn.net/download/qq_37131451/13767299

  • 21
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
IIR滤波器是一种数字滤波器,它可以用于对数字信号进行滤波处理。切比雪夫I型低通滤波器是一种常见的IIR滤波器,它的特点是在通带内具有最小的幅度波动,但在截止频率附近存在较大的幅度波动。 下面是C语言实现切比雪夫I型低通滤波器的代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define N 4 // 滤波器阶数 #define PI 3.1415926 // 计算切比雪夫I型低通滤波器的系数 void chebyshev1_lowpass(float fc, float epsilon, float *a, float *b) { int i, j; float theta, sn, cs, omega, beta, gamma, den; float *c, *d; c = (float *)malloc((N+1)*sizeof(float)); d = (float *)malloc((N+1)*sizeof(float)); // 计算极点 for (i = 1; i <= N; i++) { theta = PI*(2*i-1)/(2*N); sn = sin(theta); cs = cos(theta); omega = sin(PI*fc)*sin(theta); beta = 1/(1-epsilon*epsilon*omega*omega); gamma = 2*epsilon*omega; a[i] = -beta*(gamma + cs); b[i] = beta*sn; } // 计算常数项 c[0] = 1; c[1] = -a[1]; for (i = 2; i <= N; i++) { c[i] = 0; for (j = 1; j <= i; j++) { c[i] += a[j]*c[i-j] - b[j]*d[i-j]; } c[i] /= 1 - b[i]*b[i]; d[i] = c[i] - b[i]*d[i-1]; } // 归一化 den = c[N]; for (i = 0; i <= N; i++) { a[i] /= den; b[i] /= den; } free(c); free(d); } // 切比雪夫I型低通滤波器滤波 void chebyshev1_filter(float *x, float *y, int len, float *a, float *b) { int i, j; float *u, *v; u = (float *)malloc((N+1)*sizeof(float)); v = (float *)malloc((N+1)*sizeof(float)); // 初始化 for (i = 0; i <= N; i++) { u[i] = v[i] = 0; } // 滤波 for (i = 0; i < len; i++) { y[i] = 0; for (j = 0; j <= N; j++) { if (i-j >= 0) { y[i] += a[j]*u[j] - b[j]*v[j]; } } for (j = N; j >= 1; j--) { u[j] = u[j-1]; v[j] = v[j-1]; } u[0] = x[i]; v[0] = y[i]; } free(u); free(v); } int main() { float fc = 1000; // 截止频率 float epsilon = 0.5; // 通带最大衰减量 float *a, *b, *x, *y; int len = 1000; // 信号长度 int i; a = (float *)malloc((N+1)*sizeof(float)); b = (float *)malloc((N+1)*sizeof(float)); x = (float *)malloc(len*sizeof(float)); y = (float *)malloc(len*sizeof(float)); // 生成测试信号 for (i = 0; i < len; i++) { x[i] = sin(2*PI*100*i/len) + sin(2*PI*500*i/len) + sin(2*PI*1000*i/len); } // 计算滤波器系数 chebyshev1_lowpass(fc/(len/2), epsilon, a, b); // 滤波信号 chebyshev1_filter(x, y, len, a, b); // 输出结果 for (i = 0; i < len; i++) { printf("%f,%f\n", x[i], y[i]); } free(a); free(b); free(x); free(y); return 0; } ``` 在这个例子中,我们生成了一个包含三个正弦信号的测试信号,并使用切比雪夫I型低通滤波器将其滤波。在输出结果中,我们可以看到滤波后的信号已经去除了截止频率以上的高频成分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值