java中的简单带通滤波器
我正试图按照中的说明编写一个简单的带通滤波器。我的代码创建了一个blackman窗口,并结合了两个低通滤波器内核,以使用光谱反转创建一个带通滤波器内核,如第二个示例(表16-2)所述 我正在测试我的代码,将其与在matlab中得到的结果进行比较。当我分别测试创建blackman窗口和低通滤波器内核的方法时,我得到的结果与我在matlab中看到的结果非常接近(小数点后的一些数字-我将错误归因于java双变量舍入问题),但我的带通滤波器内核是不正确的 我运行的测试:java中的简单带通滤波器,java,matlab,signal-processing,Java,Matlab,Signal Processing,我正试图按照中的说明编写一个简单的带通滤波器。我的代码创建了一个blackman窗口,并结合了两个低通滤波器内核,以使用光谱反转创建一个带通滤波器内核,如第二个示例(表16-2)所述 我正在测试我的代码,将其与在matlab中得到的结果进行比较。当我分别测试创建blackman窗口和低通滤波器内核的方法时,我得到的结果与我在matlab中看到的结果非常接近(小数点后的一些数字-我将错误归因于java双变量舍入问题),但我的带通滤波器内核是不正确的 我运行的测试: 创建了一个blackman窗口
- 创建了一个blackman窗口,并将其与我在matlab中得到的结果进行了比较-都很好
- 使用我的代码和
fir1(N,Fc1/(Fs/2),win,flag),使用此窗口创建低通滤波器代码>在matlab中(请参阅下面的完整代码)。我认为结果是正确的,尽管误差越大,Fc1越大(为什么?)
- 使用我的代码和
fir1(N[Fc1 Fc2]/(Fs/2),“带通”,win,flag)创建了一个泛通滤波器代码>在matlab中-结果完全关闭
- 使用我的代码和matlab生成的内核过滤我的数据-都很好
Fs = 200; % Sampling Frequency
N = 10; % Order
Fc1 = 1.5; % First Cutoff Frequency
Fc2 = 7.5; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
% Create the window vector for the design algorithm.
win = blackman(N+1);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
res = filter(Hd, data);
这是我的java代码(我相信错误在bandPassKernel中):
我最终用Java实现了Matlab的fir1函数。我的结果非常准确。有一个实现-也许您可以检查您的算法是否符合此要求?对于任何可能搜索fir1函数的人,可以在此处阅读:请注意,倍频程的真实repo及其信号包位于SourceForge上。
/**
* See - http://www.mathworks.com/help/signal/ref/blackman.html
* @param length
* @return
*/
private static double[] blackmanWindow(int length) {
double[] window = new double[length];
double factor = Math.PI / (length - 1);
for (int i = 0; i < window.length; ++i) {
window[i] = 0.42d - (0.5d * Math.cos(2 * factor * i)) + (0.08d * Math.cos(4 * factor * i));
}
return window;
}
private static double[] lowPassKernel(int length, double cutoffFreq, double[] window) {
double[] ker = new double[length + 1];
double factor = Math.PI * cutoffFreq * 2;
double sum = 0;
for (int i = 0; i < ker.length; i++) {
double d = i - length/2;
if (d == 0) ker[i] = factor;
else ker[i] = Math.sin(factor * d) / d;
ker[i] *= window[i];
sum += ker[i];
}
// Normalize the kernel
for (int i = 0; i < ker.length; ++i) {
ker[i] /= sum;
}
return ker;
}
private static double[] bandPassKernel(int length, double lowFreq, double highFreq) {
double[] ker = new double[length + 1];
double[] window = blackmanWindow(length + 1);
// Create a band reject filter kernel using a high pass and a low pass filter kernel
double[] lowPass = lowPassKernel(length, lowFreq, window);
// Create a high pass kernel for the high frequency
// by inverting a low pass kernel
double[] highPass = lowPassKernel(length, highFreq, window);
for (int i = 0; i < highPass.length; ++i) highPass[i] = -highPass[i];
highPass[length / 2] += 1;
// Combine the filters and invert to create a bandpass filter kernel
for (int i = 0; i < ker.length; ++i) ker[i] = -(lowPass[i] + highPass[i]);
ker[length / 2] += 1;
return ker;
}
private static double[] filter(double[] signal, double[] kernel) {
double[] res = new double[signal.length];
for (int r = 0; r < res.length; ++r) {
int M = Math.min(kernel.length, r + 1);
for (int k = 0; k < M; ++k) {
res[r] += kernel[k] * signal[r - k];
}
}
return res;
}
double[] kernel = bandPassKernel(10, 1.5d / (200/2), 7.5d / (200/2));
double[] res = filter(data, kernel);