IIR滤波器的表达式为:
y(n)+∑i=1Na(i)y(n−i)=∑k=0Mb(k)x(n−k)
所以首要任务是确定系数a,b,在这里我选择直接使用MATLAB生成系数a,b
在MATLAB命令行中输入fdatool,打开fdatool
在fdatool里面可以设置参数,我在这里设置采样率是250hz,fs是55hz,fp60hz
选择好之后生成滤波器,选择File->Export
在工作区就会得到两个向量SOS和G,使用命令语句转换成a,b
将a和b导出生成.txt文件
a和b可以直接复制到.java文件的数组内,以下是IIR滤波器算法
package highpass;
public class highpass {
private static double[] a={在这里复制a};
private static double[] b={在这里复制b};
private static double[] in;
private static double[] out;
private static double[] outData;
public double[] IIRFilter (double[] signal) {
in=new double[b.length];
out=new double[a.length-1];
outData=new double[signal.length];
for (int i = 0; i < signal.length; i++) {
System.arraycopy(in, 0, in, 1, in.length - 1); //in[1]=in[0],in[2]=in[1]...
in[0] = signal[i];
//calculate y based on a and b coefficients
//and in and out.
double y = 0;
for(int j = 0 ; j < b.length ; j++){
y += b[j] * in[j];
}
for(int j = 0;j < a.length-1;j++){
y -= a[j+1] * out[j];
}
//shift the out array
System.arraycopy(out, 0, out, 1, out.length - 1);
out[0] = y;
outData[i] = y;
}
return outData;
}
}
接下来我们测试一下算法是否工作正常
首先在MATLAB里生成一个45hz和65hz相加的数组x,并将x导出成txt文件
Fs=250;
t=(1:2048)/Fs;
x=sin(2*pi*45*t)+cos(2*pi*65*t);
fid=fopen('x.txt','wt');
fprintf(fid,'%g\n',x);
fclose(fid);
然后在eclipse里写一个main函数,把x.txt复制到输入数组,在设定的路径下就可以得到滤波后的结果:
public static void main(String[] args) throws IOException {
File file=null;
FileWriter fw=null;
file=new File("F:\\result.txt");
fw= new FileWriter(file);
highpass a=new highpass();
double[] in= {复制x.txt};
double[] out=a.IIRFilter(in);
for(int i=0;i<out.length;i++) {
fw.write(String.valueOf(out[i]));
fw.write("\r\n");
}
fw.flush();
}
将result.txt文件里的数据进行频谱分析,可惜最终发现滤波后发生了震荡,由于数字不是我的研究方向,代码是没有问题的,但是我也分析不出来为什么震荡了,有可能是保留的有效数字的问题,所以果断转向FIR,见下一篇。