我正在设计一个需要 FIR 滤波器系数生成器功能的系统。我尝试使用 Octave Signal 包中提供的 remez.cc 源文件。
remez.cc 的源代码在这里。我删除了 octave 接口部分(第 757 行 - 结束)和库头(第 34 行),并在第 592 行创建了一个只有 remez 函数的简单头,然后将源代码编译到静态库中。
#pragma once
// remez.h
/********************
* remez
*=======
* Calculates the optimal (in the Chebyshev/minimax sense)
* FIR filter impulse response given a set of band edges,
* the desired response on those bands, and the weight given to
* the error in those bands.
*
* INPUT:
* ------
* int numtaps - Number of filter coefficients
* int numband - Number of bands in filter specification
* double bands[] - User-specified band edges [2 * numband]
* double des[] - User-specified band responses [numband]
* double weight[] - User-specified error weights [numband]
* int type - Type of filter
*
* OUTPUT:
* -------
* double h[] - Impulse response of final filter [numtaps]
* returns - true on success, false on failure to converge
********************/
int remez(double h[], int numtaps,
int numband, const double bands[],
const double des[], const double weight[],
int type, int griddensity);
然后我按照一个 Octave示例进行滤波器设计,并实现了一个 C++ 主函数来试验如何调用 remez 函数。这是我的主要功能。
#include <remez.h>
#include <cmath>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
int numtaps = 52;
vector<double> h(numtaps);
vector<double> bands = { 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 };
int numbands = bands.size() / 2;
vector<double> des = { 1, 1, 0, 0, 0.5, 0.5, 0, 0, 1, 1 }; // designed response for each band
double ripple1 = 1 - pow(10, -0.3 / 20);
double att2 = pow(10, -60 / 20);
double ripple3 = (1 - pow(10, -0.2 / 20)) * 0.5;
double att4 = pow(10, -70 / 20);
double ripple5 = 1 - pow(10, -0.1 / 20);
vector<double> weight = { 1 / ripple1, 1 / att2, 1 / ripple3, 1 / att4, 1 / ripple5 };
int err = remez(h.data(), numtaps, numbands, bands.data(), des.data(), weight.data(), 1, 16);
for (auto &c : h)
cout << c << ", ";
cout << endl;
cout << "error code: " << err << endl;
return 0;
}
这个函数调用会产生一些奇怪的系数。h 向量内的所有值都是 10e144 的东西。这显然是一个溢出,所以我调试了 remez.cc 并追踪了导致这种情况的原因。
remez 函数文档指定 des 数组的大小应为 numband。remez 函数中的 des 数组在第 86 行被传递给 CreateDenseGrid 函数用于网格生成。第 73 行 CreateDenseGrid 的文档表明其参数 des 的大小应为 2*numband。显然,由于我的 des 数组的大小仅为 numband,因此第 110 行发生了一些超出范围的内存访问。
我将 des 向量更改为 {1, 1, 0, 0, 0.5, 0.5, 0, 0, 1, 1} 并再次尝试。系数看起来更好,但是当我在 Octave 中绘制频率响应时,它与我预期的滤波器设计并不接近。
任何人都可以帮助我解决这个问题吗?我的 remez 函数调用有什么问题吗?任何建议在这里表示赞赏。非常感谢你。
顺便一提。我正在使用 vs2015、windows7 64 位、Debug X86 build 进行编译器设置。

