MATLAB里面的filter和filtfilt的C语言源代码

MATLAB里面的filter和filtfilt的C语言源代码

嗯,算法非常简单,就是网上搜不到C代码实现。filter是个很万能的数字滤波器函数,只要有滤波器的差分方程系数,IIR呀FIR呀都能通过它实现。在MATLAB里面,filter最常用的格式是这两个:

[y,zf] = filter(b,a,X)
[y,zf] = filter(b,a,X,zi)

其中b和a就是差分方程的系数,X是输入向量,zi是“初始状态”。可能这么说明还是不很清晰,那么请看图(注意,a(1)为1,这个可以通过差分方程所有系数除以a(1)所得):

嗯,这样子很轻松地就能把各个y值给算出来了,哦注意上面式子里面的n是“向量a或者b中最长的长度”,在实际编程的时候,如果a和b长度不一样,短者显然是要用0补齐的。对于那个初始状态zi,忽略的时候,比如(顺便提醒一句MATLAB的下标从1开始)

y(1)=b(1)x(1)

y(2)=b(1)x(2)+Z1(1)= b(1)x(2) + b(2)x(1) - a(2)y(1)

不忽略的时候

y(1)=b(1)x(1) + Z1(0)

y(2)=b(1)x(2)+Z1(1)= b(1)x(2) + b(2)x(1) - a(2)y(1) + Z2(0)

因为实际程序中自己定义的东西比较多(=,=|||这也是没办法的事情不是),而filtfilt这个超级无敌的“零相移滤波函数”更是复杂到稍微调用了一下自己写的矩阵运算函数,所以代码全部贴上来实在是太乱。等这次工程做完会大概地把代码打包发一下。现在就先贴点代码片段好了……但愿我的代码风格没那么难懂……

#include "filter.h"
#include <string.h>

//Transposed Direct-Form II Realization
//initial conditions: zi, length==nfilt-1. ignore when zi==NULL


#ifndef EPS
#define EPS 0.000001
#endif

void
filter(const double* x, double* y, int xlen, double* a, double* b, int nfilt, double* zi){
    double tmp;
    int i,j;

    //normalization
    if( (*a-1.0>EPS) || (*a-1.0<-EPS) ){
        tmp=*a;
        for(i=0;i<nfilt;i++){
            b[i]/=tmp;
            a[i]/=tmp;
        }
    }

    memset(y,0,xlen*sizeof(double));

    a[0]=0.0;
    for(i=0;i<xlen;i++){
        for(j=0;i>=j&&j<nfilt;j++){
            y[i] += (b[j]*x[i-j]-a[j]*y[i-j]);
        }
        if(zi&&i<nfilt-1) y[i] += zi[i];
    }
    a[0]=1.0;

}

OK,接下来是神奇的零相移滤波filtfilt,操作上不复杂,原理上小小有点复杂。它主要是先找到一个“合理的”初始状态Zi,使得无论先从反向滤波还是先从正向滤波结果一致,然后filter一次,逆向,再filter一次,再逆向,就是结果了。这里面包括3个要点:

1. Zi的确定。

2. 边缘效应的消除。

3. 正反向滤波的数学原理。

对于要点1,可以参阅Fredrik Gustafsson的论文Determining the Initial States in Forward-backward Filtering的数学证明。要点2,filtfilt对数据两头做了镜像拓延,最后滤完波再截掉头尾。要点3,这个貌似不大难推(

#include <stdlib.h>
#include "filter.h"
#include "mulMat.h"
#include "invMat.h"

int
filtfilt(const double* x, double* y, int xlen, double* a, double* b, int nfilt){
    int nfact;
    int tlen;    //length of tx
    int i;
    double *tx,*tx1,*p,*t,*end;
    double *sp,*tvec,*zi;
    double tmp,tmp1;

    nfact=nfilt-1;    //3*nfact: length of edge transients
    
    if(xlen<=3*nfact || nfilt<2) return -1;    //too short input x or a,b
    
    //Extrapolate beginning and end of data sequence using a "reflection
    //method". Slopes of original and extrapolated sequences match at
    //the end points.
    //This reduces end effects.
    tlen=6*nfact+xlen;
    tx=malloc(tlen*sizeof(double));
    tx1=malloc(tlen*sizeof(double));

    sp=malloc( sizeof(double) * nfact * nfact );
    tvec=malloc( sizeof(double) * nfact );
    zi=malloc( sizeof(double) * nfact );

    if( !tx || !tx1 || !sp || !tvec || !zi ){
        free(tx);
        free(tx1);
        free(sp);
        free(tvec);
        free(zi);
        return 1;
    }
    
    tmp=x[0];
    for(p=x+3*nfact,t=tx;p>x;--p,++t) *t=2.0*tmp-*p;
    for(end=x+xlen;p<end;++p,++t) *t=*p;
    tmp=x[xlen-1];
    for(end=tx+tlen,p-=2;t<end;--p,++t) *t=2.0*tmp-*p;
    //now tx is ok.

    end = sp + nfact*nfact;
    p=sp;
    while(p<end) *p++ = 0.0L; //clear sp
    sp[0]=1.0+a[1];
    for(i=1;i<nfact;i++){
        sp[i*nfact]=a[i+1];
        sp[i*nfact+i]=1.0L;
        sp[(i-1)*nfact+i]=-1.0L;
    }

    for(i=0;i<nfact;i++){
        tvec[i]=b[i+1]-a[i+1]*b[0];
    }

    if(invMat(sp,nfact)){
        free(zi);
        zi=NULL;
    }
    else{
        mulMat(sp,tvec,zi,nfact,nfact,1);
    }//zi is ok

    free(sp);free(tvec);

    //filtering tx, save it in tx1
    tmp1=tx[0];
    if(zi)
        for( p=zi,end=zi+nfact; p<end;) *(p++) *= tmp1;
    filter(tx,tx1,tlen,a,b,nfilt,zi);

    //reverse tx1
    for( p=tx1,end=tx1+tlen-1; p<end; p++,end--){
        tmp = *p;
        *p = *end;
        *end = tmp;
    }

    //filter again
    tmp1 = (*tx1)/tmp1;
    if(zi)
        for( p=zi,end=zi+nfact; p<end;) *(p++) *= tmp1;
    filter(tx1,tx,tlen,a,b,nfilt,zi);

    //reverse to y
    end = y+xlen;
    p = tx+3*nfact+xlen-1;
    while(y<end){
        *y++ = *p--;
    }

    free(zi);
    free(tx);
    free(tx1);

    return 0;
}

与MATLAB对比(MATLAB代码):

x=[1 2 3 4 5 6 7 8];
a=[1 2 3];
b=[4 5 6];
t=filtfilt(b,a,x);
for i=1:8, fprintf(1,'%f\n',t(i)), end;

结果为:

-6731884.250000
7501778.750000
-2757230.250000
-662443.250000
1360955.750000
-686678.250000
4135.750000
227147.750000

这个例子用上面给出的C语言版的filtfilt计算结果完全一致:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20172302『Java程序设计』课程 结对编程练习_四则运算第二周阶段总结

一.结对对象 姓名&#xff1a;周亚杰学号&#xff1a;20172302担任角色&#xff1a;驾驶员&#xff08;周亚杰&#xff09;伙伴第二周博客地址二.本周内容 (一)继续编写上周未完成代码 1.本周继续编写代码&#xff0c;使代码支持分数类计算 2.相关过程截图 a.下图是上周编写的生…

实践中的弹性基础架构

几周前&#xff0c;我获得了一个难得的机会&#xff0c;可以在基础设施领域弄脏双手。 在JVM内部的深入了解下&#xff0c;我每天的工作经历发生了有趣的变化&#xff0c;我想与您分享动机和成果。 希望它可以启发类似的问题类别。 背景 我将从解释需要解决方案的上下文开始。…

notepad++插件实现json、xml格式化

notepad比较出色的免费的数据编辑、格式化工具。。。 现在json、xml文件很流行、格式化也是必须的&#xff0c;方便查看关键信息&#xff01; 01、下载notepad及相关插件 npp_7.5.5-x86&#xff1a; https://files.cnblogs.com/files/xiaochina/npp_7.5.5-x86.zip npp-json:…

ActiveMQ 5.x中的消息持久性

我被问了很多关于ActiveMQ如何存储消息&#xff08;或在某些情况下不存储&#xff09;的基本知识。 这是它的高级解释。 注意&#xff0c;上下文在JMS中。 如果您使用ActiveMQ的非JMS客户端&#xff08;即STOMP&#xff0c;AMQP&#xff0c;MQTT等&#xff09;&#xff0c;则在…

一个select元素自定义设计的新思路:appearance: none之后利用符号制造小箭头

最近工作时解决了一个前端小问题&#xff08;如下图所示&#xff09;&#xff1a;在Safari中&#xff0c;select的控件之上有不和谐的灰色部分。 刚开始时我以为是backgrand或是border设置不当之类产生的问题&#xff0c;在搜索了很久之后终于找到了问题所在&#xff1a;这个灰…

调整HashMap的大小:未来的危险

最近&#xff0c;我偶然发现了一个错误&#xff0c;该错误是由于多个线程对java.util.HashMap的使用不当引起的。 该错误是抽象泄漏的一个很好的例子。 只有了解数据结构的实现级别详细信息&#xff0c;才能帮助我解决当前的问题。 因此&#xff0c;我希望分享我所面临的问题将…

别的程序员是怎么读你的简历的

别的程序员是怎么读你的简历的 2009年11月9日 陈皓 下面这个图片来源国外&#xff0c;是一个关于程序员面试时的简历&#xff0c;被人事部门和程序员本身评审的角度不同的图片。当然&#xff0c;这是一个从国外面试的视角制作的图片&#xff0c;不过&#xff0c;可以看出&#…

Zabbix linux agent 安装

系统&#xff1a;Linux Centos 7.3 x64 服务&#xff1a;Zabbix_agent 3.0.16 一.安装Zabbix_agent 服务 1.安装zabbix 3.0 yum源 rpm -ivh http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-release-3.0-1.el7.noarch.rpm 2.安装Zabbix_agent yum install zabbix-agen…

直接在apk中添加资源的研究

原文 http://blog.votzone.com/2018/05/12/apk-merge.html 之前接手过一个sdk的开发工作&#xff0c;在开发过程中有一个很重要的点就是尽量使用代码来创建控件&#xff0c;资源文件最好放到assets目录下&#xff0c;如果必须使用res资源&#xff0c;需要通过 getResources().g…

JavaFX实际应用程序:SkedPal

“真实世界的应用程序”系列中的一个新条目。 这次是SkedPal &#xff0c;这是一个用于智能管理忙人生活的应用程序。 我一直在咨询SkedPal团队有关JavaFX的事宜&#xff0c;并且在他们决定开始使用我的CalendarFX框架来满足他们的日历要求时&#xff0c;我也在咨询他们。 在下…

chromium之histogram.h

histogram不知道是干啥的 // Histogram is an object that aggregates statistics, and can summarize them in // various forms, including ASCII graphical, HTML, and numerically (as a // vector of numbers corresponding to each of the aggregating buckets). google翻…

viewobject_只读ViewObject和声明性SQL模式

viewobject介绍 声明式SQL模式被认为是基于实体的视图对象的最有价值的优点之一。 在这种模式下&#xff0c;根据UI中显示的属性在运行时生成VOSQL。 例如&#xff0c;如果某个页面包含一个只有两列EmployeeId和FirstName的表&#xff0c;则查询将生成为“从Employees中选择Emp…

MyEclipse6.0 安装axis2插件, 调用加密的SAP webservice

MyEclipse6.0 安装axis2插件, 调用加密的SAP webservice 6人收藏此文章, 我要收藏 发表于1个月前(2013-06-06 09:41) , 已有116次阅读 &#xff0c;共0个评论 首先鄙视一下自己&#xff0c;还在用myeclipse,竟然还是6.0版本&#xff0c;没办法&#xff0c;用习惯了&#xff0c…

Eclipse中要导出jar包中引用了第三方jar包怎么办

Eclipse中要导出jar包中引用了第三方jar包怎么办 (2009-07-20 15:28:44) 转载▼标签&#xff1a; it 分类&#xff1a; Eclipse 今天做个小的java程序&#xff0c;想要先将其导出成一个可执行的jar包&#xff01;向往常一样&#xff0c;单击菜单栏中的 File -> export,弹出…

拖动滑块拼图背景图没显示_计划B? 那是计划N…没什么。 拼图于2015年问世

拖动滑块拼图背景图没显示真是一天 当典型的欧洲人逐渐破产时&#xff0c;美国的人们开始喝咖啡。 这就是为什么我在Mark Reinhold最近的新闻中睡个好觉的原因。 他在题为“ Project Jigsaw&#xff1a;火车晚点 ”的帖子中建议将Project Jigsaw推迟到下一个版本Java 9。 在最近…

java keytool证书工具使用小结

Keytool 是一个Java数据证书的管理工具 ,Keytool将密钥&#xff08;key&#xff09;和证书&#xff08;certificates&#xff09;存在一个称为keystore的文件中在keystore里&#xff0c;包含两种数据:密钥实体&#xff08;Key entity&#xff09;-密钥&#xff08;secret key&a…

在Kafka中发布订阅模型

这是第四个柱中的一系列关于同步客户端集成与异步系统&#xff08; 1&#xff0c; 2&#xff0c; 3 &#xff09;。 在这里&#xff0c;我们将尝试了解Kafka的工作方式&#xff0c;以便正确利用其发布-订阅实现。 卡夫卡概念 根据官方文件 &#xff1a; Kafka是一种分布式的&…

深入理解C++中的mutable关键字

2006-12-16 05:00 来源&#xff1a;BLOG 作者&#xff1a;寒星轩 责任编辑&#xff1a;方舟yesky 评论(32)推荐&#xff1a;经典教程专区mutalbe的中文意思是“可变的&#xff0c;易变的”&#xff0c;跟constant&#xff08;既C中的const&#xff09;是反义词。在C中&…

使用Boxfuse为您的REST API设置https

在我的上 一篇 文章中&#xff0c;我展示了在Boxfuse的帮助下&#xff0c;基于Spring Boot框架建立REST API并在AWS上运行非常容易 。 下一步是利用SSL与API进行通信。 通过使用SSL&#xff0c;我们确保在REST API服务器和API客户端之间的传输过程中保存了数据 。 要为Spring B…

Python类与对象实验

一、任务描述 本实验任务主要对Python类与对象进行一些基本操作&#xff0c;通过完成本实验任务&#xff0c;要求学生熟练掌握Python类与对象的关系&#xff0c;并对Python类与对象的基本操作进行整理并填写工作任务报告。 二、任务目标 1、掌握Python类的创建 2、掌握类对象 三…