日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/2 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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計算結果完全一致:

總結

以上是生活随笔為你收集整理的MATLAB里面的filter和filtfilt的C语言源代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: av在线免费网址 | 亚洲精视频 | 岛国精品一区二区 | 国产黄色小视频在线观看 | 不卡在线一区二区 | 亚洲精品77777 | 色妇av | 不卡中文av | 奇米精品一区二区三区在线观看一 | аⅴ资源新版在线天堂 | 国产网址 | 一级黄色a | 国产午夜精品久久久久 | 一本色道久久综合亚洲精品图片 | 日本精品视频网站 | 香蕉视频链接 | 开心色站| 国产精品白丝喷水在线观看 | 国产一级在线视频 | 国产精品无码乱伦 | 九九综合视频 | 久久夜色av| 婷婷丁香在线 | 国产麻豆一区二区三区在线观看 | 啪啪免费网址 | 国内成人自拍 | 一级大片儿 | 一出一进一爽一粗一大视频 | 国产精品资源在线观看 | 一本色道久久综合熟妇 | 久久激情av | 久草中文在线 | 玩弄人妻少妇500系列 | 在线观看视频一区二区三区 | 天堂色网| 第一页综合| 色哟哟网站入口 | 潘金莲一级淫片aaaaa武则天 | 有码在线视频 | 欧美色香蕉 | 美女被艹视频网站 | 久久在线电影 | 国产美女91 | 欧美激情小视频 | va欧美| 日韩久久精品一区二区 | 天天操操操操操 | 黄色视屏免费 | 日本午夜视频在线观看 | 91在线免费视频观看 | 成年免费视频 | 黄色录像三级 | 久久午夜影院 | 熟妇的味道hd中文字幕 | 亚洲成人av一区二区 | 亚洲日本久久久 | 日本免费专区 | jizz性欧美23 | 欧美日本在线观看 | 国产精品夜夜夜爽张柏芝 | 欧美电影一区二区三区 | 黄色大片中文字幕 | 樱花影院最新免费观看攻略 | 大香焦久久 | 日本sm调教—视频|vk | 成人羞羞国产免费 | 欧美一级在线视频 | 亚洲国产视频网站 | 日日操夜夜爽 | 欧美爱爱一区二区 | 亚洲网站视频 | 黄色国产在线观看 | 欧美4区| 久久久99精品国产一区二区三区 | 私人影院毛片 | 国产精品专区在线观看 | 国产精品国产三级国产aⅴ浪潮 | 一级成人av | 国产精品超碰 | 五十路妻 | 99性视频| 国产免费的av | 欧美日韩一区二区视频在线观看 | 青青视频免费看 | 男人天堂伊人 | 日本热久久 | 91一级片 | 中文字幕日韩一区 | 麻豆免费av| 91黄免费 | 成人免费黄色网址 | 啪免费视频 | 国产精品一区在线播放 | 久草视频免费在线播放 | 亚洲熟女乱色综合亚洲av | 色乱码一区二区三在线看 | 五月天中文字幕在线 | 日韩无 | 成年丰满熟妇午夜免费视频 |