IIR滤波器软件实现(Matlab+C++)

时间:2023-01-07 17:19:19

使用C++来写一个IIR滤波器

我们首先要在MATLAB中设计一个IIR滤波器,并生成一个头文件,这个头文件中反映了IIR滤波器的频率响应特性


理论支持

IIR滤波叫做递归滤波器,它是一种具有反馈的滤波器。当阶数较大时一般采取多个二阶节滤波进行串联,这样可以提高系统稳定性。

一个二阶节系数规律如图所示:

IIR滤波器软件实现(Matlab+C++)

可以写出第K个二阶节的差分方程

IIR滤波器软件实现(Matlab+C++)

N个二阶节的级联结构如下图所示:

IIR滤波器软件实现(Matlab+C++)

根据二阶节图,把前一级的输出作为后一级的输入,就可以通过软件实现IIR数字滤波的功能。


使用Matlab生成头文件

首先打开MATLAB中Filter Design & Analysis Tool

IIR滤波器软件实现(Matlab+C++)

这里我们先设计一个低通滤波器

Fs代表采样频率,采样频率必须大于原信号最高频率的两倍,

否则会产生频谱混叠。

Fpass为通带频率,Fstop为阻带截止频率

这些参数设置好就可以点击Design Filter

IIR滤波器软件实现(Matlab+C++)

生成的是一个二阶节滤波组合,一共有31阶,也就是多个二阶滤波器的组合

接着在Target选项中生成C Header File

IIR滤波器软件实现(Matlab+C++)

Numerator为分子系数数组的命名,Numerator length为分子系数数组的长度,

Denominator为分母。


对生成头文件进行分析

以下以Fpass为10K,Fstop为12K的低通滤波器举栵

在使用头文件前需要根据情况将Matlab的数据类型转换为C++支持的数据类型,这里我们使用double类型

在分析头文件前先看下Matlab提供的第一节滤波参数

以第一个二阶节的数据举例:

  • Numerator: 1  2  1
  • Denominator: 1  -0.55930961405944157  0.92579835996619642
  • Gain:0.34162218647668868

Numerator为分子的系数,分别为b0,b1,b2

Denominator为分母的系数,分别为a0,a1,a2.

Gain为各节的增益,此项为了稳定各节,稳定信号大小

接着对照头文件,以下为头文件主要部分的一段截取:

#define MWSPT_NSEC 41
int NL[MWSPT_NSEC] = { ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,, };
double NUM[MWSPT_NSEC][] = {
{
0.3416221864767, ,
},
{
, ,
},
{
0.3180955154747, ,
},
{
, ,
},......
MWSPT_NSEC为滤波器阶数,具体的节数在头文件开头的注释中
NL[MWSPT_NSEC]这个数组定义了NUM[MWSPT_NSEC][3]数组每一行的有用数据个数(可以不用)

在NUM[MWSPT_NSEC][3]数组(分子参数)奇数行第一项都为增益项,偶数行为3个系数,分别为b0,b1,b2。

由此可以找出规律,定义K为目前所在的阶数,p为数组的首指针,则,每一节的增益项为(p+6*K),第一个系数为(p+3+6*K),

第二个系数为(p+3+6*K+1),第三个系数为(p+3+6*K+2)。


C++编程实现

在软件设计的过程中,每个二阶节的延迟变量只取 和 , 作为中间变量在过程中直接赋给 。这是因为对于下一个输入数据n+1的延迟变量即为上一个输入数据的 和 ,采用这种方式进行设计,可以节省寄存器的空间。

为了提高处理速度,程序中需要使用指针进行参数传递,特别注意二维数组的首地址传递方式为&a[0][0]->double* a。

滤波函数

double iir(double *a, double *b,double* w, double xin, int N_IIR)

{

int k;

double temp = xin;

for (k = 0; k<N_IIR; k++)

{

*(w+k*3) = temp - *(a + 3+6 * k  + 1) *(*(w + k * 3+1)) - *(a + 3 + 6 * k + 2) *(*(w + k * 3+2));

//这里temp为本二阶节的输入,也是上一个二阶节的输出

temp = *(b + 3 + 6 * k )* (*(w + k * 3)) + *(b + 3 + 6 * k + 1) * (*(w + k * 3+1)) + *(b + 3+6 * k + 2)* (*(w + k * 3+2));

//这里temp为本二阶节的输出,也是下一个二阶节的输入

*(w + k * 3 + 2) = *(w + k * 3 + 1);

*(w + k * 3 + 1) = *(w + k * 3);

temp = temp*(*(b + 6 * k));//放大倍数,稳定信号

}

return temp;

}


实际测试

测试Fpass为10K,Fstop为12K的低通滤波器

在程序中输入三个频率为2K,11K,20K的信号,理论上2k完全通过,11k部分衰减,20K完全滤除。

IIR滤波器软件实现(Matlab+C++)

上图为原信号,下图为滤波后信号。

实际测试发现符合设计要求,而且在过渡带信号也基本完全衰减。

测试用C++程序
void main()
{
const int N = ;
int i,j;
double xn[N];
double w[][];
double yn[N]; for (i = ; i < ; i++)//初始化
{
for (j = ; j < ; j++)
w[i][j] = ;
} for (i = ; i < N; i++)
{
xn[i] = sin( * 3.1416 * / * i)+ sin( * 3.1416 * / * i)+ sin( * 3.1416 * / * i); yn[i]=iir(&DEN[][], &NUM[][], &w[][],xn[i], ); } ofstream SaveFile_a("xn.txt");
for (i = ; i<N; i++)
SaveFile_a << " " << xn[i] << endl;
SaveFile_a.close(); ofstream SaveFile_b("yn.txt");
for (i = ; i<N; i++)
SaveFile_b << " " << yn[i] << endl;
SaveFile_a.close();
} 分析用Matlab程序
xn1=fopen('xn.txt','r');
[xn,count]=fscanf(xn1,'%f');
fclose(xn1); N = length(xn);%求取抽样点数
xn_f = fft(xn);%对信号进行傅里叶变换
xn_f=abs(xn_f(:N/));
f = /N*(:N/-); subplot();
stem(f,abs(xn_f));
xlabel('Frequency / (s)');ylabel('Amplitude'); title('原信号频谱');
grid; yn1=fopen('yn.txt','r');
[yn,count]=fscanf(yn1,'%f');
fclose(yn1); yn_f = fft(yn);%对信号进行傅里叶变换
yn_f=abs(yn_f(:N/));
subplot();
stem(f,abs(yn_f));
xlabel('Frequency / (s)');ylabel('Amplitude');
title('滤波后信号频谱');
grid;

IIR滤波器软件实现(Matlab+C++)的更多相关文章

  1. IIR滤波器设计(调用MATLAB IIR函数来实现)

    转载请注明文章来源 – http://blog.csdn.net/v_hyx ,请勿用于任何商业用途         对于滤波器设计,以前虽然学过相关的理论(现代数字信号处理和DSP设计),但一直不求 ...

  2. IIR滤波器和FIR滤波器的区别与联系zz

      -------------------------------------------------------------------------------------------------- ...

  3. 数字信号处理实验(五)&mdash&semi;&mdash&semi;IIR滤波器的设计

    一.使用自编函数设计IIR滤波器 1.冲激响应法 (1)注给出的数字滤波器指标先化成模拟指标 (2)设计出模拟滤波器: (3)使用冲激响应法转化成数字滤波器 (4)一个demo clear all; ...

  4. 基于FPGA的IIR滤波器

    基于FPGA的IIR滤波器                                                         by方阳 版权声明:本文为博主原创文章,转载请指明转载地址 ...

  5. 杂项-数学软件:MATLAB

    ylbtech-杂项-数学软件:MATLAB MATLAB是美国MathWorks公司出品的商业数学软件,用于算法开发.数据可视化.数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATL ...

  6. 手把手教系列之IIR滤波器设计

    [导读]:在嵌入式系统中经常需要采集模拟信号,采集模拟信号的信号链中难免引入干扰,那么如何滤除干扰呢?今天就来个一步一步描述如何设计部署一个IIR滤波器到你的系统. 何为IIR滤波器? 无限冲激响应( ...

  7. FIR滤波器和IIR滤波器的区别

    数字滤波器广泛应用于硬件电路设计,在离散系统中尤为常见,一般可以分为FIR滤波器和IIR滤波器,那么他们有什么区别和联系呢. FIR滤波器 定义: FIR滤波器是有限长单位冲激响应滤波器,又称为非递归 ...

  8. FIR滤波器与IIR滤波器

    FIR(Finite Impulse Response)滤波器 有限长单位冲激响应滤波器,又称为非递归型滤波器 特点: FIR滤波器的最主要的特点是没有反馈回路,稳定性强,故不存在不稳定的问题: FI ...

  9. &lbrack;math&rsqb;&lbrack;mathematica&rsqb; archlinux 下 mathematica 的安装 &lpar;科学计算软件 mathematica&sol;matlab&sol;sagemath&rpar;

    ONLINE: http://www.wolframalpha.com/ GPL: segamath: http://www.sagemath.org/ famous and not free: ma ...

随机推荐

  1. Java多线程基本概念

    基本概念 线程与任务的概念不一样. 任务:通常是一些抽象的且离散的工作单元,比如在Web请求中,针对用户的请求需要返回相应的页面是一个任务,在Java中实现Runnable接口的类也是一个任务. 线程 ...

  2. yii 验证码的使用

    在HappyController 中加入 public function actions(){ return array( // captcha action renders the CAPTCHA ...

  3. const型类成员

    一.关于const类成员函数有以下几个需要注意的地方: 1. 在普通的非const成员函数中,this的类型是一个指向类类型的const指针,而const成员函数中,this的类型是一个指向const ...

  4. PHP实现微博的同步发送&lpar;转&rpar;

    导读:在设计博客类站点时,有时会需要在发布文章时同步发布在微博上.本文阐述了实现该功能的基本方式. 准备工作   作为新浪微博的开发者,需要有身份验证: 个人身份认证的审核,一般一个工作日: 接着是提 ...

  5. 桶排序&lpar;BucketSort&rpar;

    1 桶排序核心思想是 根据数据规模n划分 m个相同大小的区间 (每个区间为一个桶,桶可理解为容器) 2 每个桶存储区间内的元素(区间为半开区间 例如[0,10) 或者 [200,300) ) 3 将n ...

  6. mysql分页查询优化

    由于MySql的分页机制:并不是跳过 offset 行,而是取 offset + N 行,然后返回放弃前 offset 行,返回N 行, 所以当 offset 特别大的时候,效率就非常的低下,要么控制 ...

  7. 一个帮助理解python星号的例子

  8. 机器学习入门04 - 使用TensorFlow的起始步骤 &lpar;First Steps with TensorFlow&rpar;

    原文链接:https://developers.google.com/machine-learning/crash-course/first-steps-with-tensorflow/ 1- 工具包 ...

  9. springCloud全家桶

    Spring Cloud 入门教程(一): 服务注册 eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳,在默认情况下erureka server也是一个eure ...

  10. EasyUI 分页 简洁代码

    做分页代码,看到网上很多人实现的方法,那是各种调用,各种获取对象.我很不解,因为Easyui已经给我们了分页的具体实现,为什么有些人要画蛇添足呢. 其实真正的分页,在你的代码中,别人可能都没有注意到, ...