Use C++ to design filters (low-pass filter, high-pass filter, band-pass filter)

simple low pass filter

The following is a sample code of a basic low-pass filter written in C++ language, which can filter the input signal to reduce high-frequency components:

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

// 低通滤波器类
class LowPassFilter {
public:
    LowPassFilter(double sample_rate, double cutoff_frequency) {
        double dt = 1.0 / sample_rate;
        double RC = 1.0 / (cutoff_frequency * 2.0 * M_PI);
        alpha_ = dt / (dt + RC);
        prev_output_ = 0.0;
    }

    // 更新滤波器输出
    double update(double input) {
        double output = alpha_ * input + (1.0 - alpha_) * prev_output_;
        prev_output_ = output;
        return output;
    }

private:
    double alpha_;
    double prev_output_;
};

int main() {
    // 输入信号
    vector<double> input_signal = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};

    // 采样率和截止频率
    double sample_rate = 100.0;
    double cutoff_frequency = 10.0;

    // 创建低通滤波器
    LowPassFilter filter(sample_rate, cutoff_frequency);

    // 对输入信号进行滤波
    vector<double> output_signal;
    for (double input : input_signal) {
        double output = filter.update(input);
        output_signal.push_back(output);
    }

    // 输出滤波结果
    for (double output : output_signal) {
        cout << output << " ";
    }
    cout << endl;

    return 0;
}

In this example, we use a first-order filter to implement a low-pass filter. The filter has a cutoff frequency above which all signal components are filtered out. In the constructor, we calculate the alpha coefficient of the filter based on the sampling rate and cutoff frequency, which is used to control the balance of the signal between the input and output. Then, we use the input signal and alpha coefficients in the update function to calculate the output of the filter, and save the output in prev_output_ for use in the next update.

In the main function, we create an input signal vector and create a low-pass filter object. Then, we use a for loop to pass each element in the input signal to the filter for processing, and save the output in a new vector. Finally, we output the filtered output vector to the console.

FIR low pass filter

The following is a sample code written in C++ for a basic FIR filter that filters an input signal for frequency selectivity:

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

// 创建一个函数,用于生成低通滤波器的系数
vector<double> createLowpassFilter(int M, double fc, double fs) {
    vector<double> h(M + 1);
    for (int n = 0; n <= M; ++n) {
        if (n == M / 2) {
            h[n] = 2.0 * fc / fs;
        } else {
            h[n] = sin(2.0 * M_PI * fc * (n - M / 2.0) / fs) / (M_PI * (n - M / 2.0));
        }
        h[n] *= 0.54 - 0.46 * cos(2.0 * M_PI * n / M);
    }
    return h;
}

// FIR滤波器类
class FirFilter {
public:
    FirFilter(const vector<double>& taps) : taps_(taps), buffer_(taps.size(), 0.0) {}

    // 更新滤波器输出
    double update(double input) {
        // 将新的输入添加到环形缓冲区中
        buffer_.insert(buffer_.begin(), input);
        buffer_.pop_back();

        // 计算输出值
        double output = 0.0;
        for (int i = 0; i < taps_.size(); ++i) {
            output += taps_[i] * buffer_[i];
        }
        return output;
    }

private:
    vector<double> taps_;  // 滤波器系数
    vector<double> buffer_;  // 环形缓冲区
};

int main() {
    // 创建低通滤波器系数
    int M = 31;  // 系数数量
    double fc = 1000.0;  // 截止频率
    double fs = 44100.0;  // 采样率
    vector<double> taps = createLowpassFilter(M, fc, fs);

    // 输入信号
    vector<double> input_signal = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};

    // 创建FIR滤波器
    FirFilter filter(taps);

    // 对输入信号进行滤波
    vector<double> output_signal;
    for (double input : input_signal) {
        double output = filter.update(input);
        output_signal.push_back(output);
    }

    // 输出滤波结果
    for (double output : output_signal) {
        cout << output << " ";
    }
    cout << endl;

    return 0;
}

In this example, we create a function called createLowpassFilter to generate the coefficients of a FIR lowpass filter. The function accepts three parameters: the length M of the filter , the cutoff frequency fc and the sampling rate fs .

IIR low pass filter

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

class IirFilter {
public:
    IirFilter(double a0, double a1, double a2, double b1, double b2) : a0_(a0), a1_(a1), a2_(a2), b1_(b1), b2_(b2), x1_(0), x2_(0), y1_(0), y2_(0) {}

    // 更新滤波器输出
    double update(double input) {
        double output = a0_ * input + a1_ * x1_ + a2_ * x2_ - b1_ * y1_ - b2_ * y2_;
        x2_ = x1_;
        x1_ = input;
        y2_ = y1_;
        y1_ = output;
        return output;
    }

private:
    double a0_, a1_, a2_, b1_, b2_;  // 滤波器系数
    double x1_, x2_, y1_, y2_;  // 状态变量
};

int main() {
    // 设计IIR低通滤波器
    double fc = 1000.0;  // 截止频率
    double fs = 44100.0;  // 采样率
    double wc = 2.0 * M_PI * fc / fs;
    double Q = 0.707;  // 品质因数
    double alpha = sin(wc) / (2.0 * Q);
    double a0 = 1.0 + alpha;
    double a1 = -2.0 * cos(wc);
    double a2 = 1.0 - alpha;
    double b0 = (1.0 - cos(wc)) / 2.0;
    double b1 = 1.0 - cos(wc);
    double b2 = (1.0 - cos(wc)) / 2.0;

    // 创建IIR低通滤波器
    IirFilter filter(a0, a1, a2, b1, b2);

    // 输入信号
    vector<double> input_signal = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};

    // 对输入信号进行滤波
    vector<double> output_signal;
    for (double input : input_signal) {
        double output = filter.update(input);
        output_signal.push_back(output);
    }

    // 输出滤波结果
    for (double output : output_signal) {
        cout << output << " ";
    }
    cout << endl;

    return 0;
}

In this example, we use the IirFilter class to implement an IIR low-pass filter. This class accepts five parameters, which are the coefficients a0 , a1 , a2 , b1 and b2 .

Simple Bandpass Filter

The following is an example of a simple C++ implementation of a bandpass filter. The code uses the Discrete Fourier Transform (DFT) to compute the signal's spectrum and then filters the spectrum.

#include <cmath>
#include <vector>

using namespace std;

const double PI = 3.14159265358979323846;

// 计算离散傅里叶变换
void dft(const vector<double>& input, vector<complex<double>>& output) {
    int n = input.size();
    output.resize(n);
    for (int k = 0; k < n; k++) {
        complex<double> sum(0, 0);
        for (int j = 0; j < n; j++) {
            double angle = 2 * PI * k * j / n;
            sum += input[j] * exp(complex<double>(0, -angle));
        }
        output[k] = sum;
    }
}

// 计算滤波器的频率响应
void filter(vector<double>& spectrum, double f1, double f2, double fs) {
    int n = spectrum.size();
    for (int k = 0; k < n; k++) {
        double freq = k * fs / n;
        if (freq < f1 || freq > f2) {
            spectrum[k] = 0;
        }
    }
}

// 带通滤波器
void bandpass_filter(vector<double>& signal, double f1, double f2, double fs) {
    int n = signal.size();

    // 计算信号的频谱
    vector<complex<double>> spectrum;
    dft(signal, spectrum);

    // 对频谱进行滤波
    filter(spectrum, f1, f2, fs);

    // 计算滤波后的信号
    vector<double> filtered_signal;
    filtered_signal.resize(n);
    for (int i = 0; i < n; i++) {
        double sum = 0;
        for (int k = 0; k < n; k++) {
            double angle = 2 * PI * i * k / n;
            sum += spectrum[k].real() * cos(angle) - spectrum[k].imag() * sin(angle);
        }
        filtered_signal[i] = sum / n;
    }

    // 将滤波后的信号复制回原信号
    for (int i = 0; i < n; i++) {
        signal[i] = filtered_signal[i];
    }
}

In this implementation, the bandpass filter is defined as the bandpass_filter function. It accepts three parameters: input signal signal , cutoff frequencies f1 and f2 , and sampling frequency fs . The function modifies the value of the input signal so that it is bandpass filtered.

Among them, the dft function calculates the discrete Fourier transform of the signal, the filter function calculates the frequency response of the filter, and the filtered_signal array stores the filtered signal.

FIR bandpass filter

A FIR filter is a commonly used type of digital filter that uses a finite number of coefficients (that is, a finite impulse response) in the discrete time domain to implement the filter's function. The FIR bandpass filter can be realized by selecting a bandpass region in the frequency domain of the transfer function. The following is an example of a simple C++ implementation of a FIR bandpass filter:

#include <cmath>
#include <vector>

using namespace std;

const double PI = 3.14159265358979323846;

// FIR带通滤波器
void bandpass_filter(vector<double>& signal, double f1, double f2, double fs, int num_taps) {
    int n = signal.size();

    // 计算滤波器系数
    vector<double> h;
    h.resize(num_taps);
    double hsum = 0;
    for (int i = 0; i < num_taps; i++) {
        double freq = (double)i / num_taps * fs;
        if (freq >= f1 && freq <= f2) {
            h[i] = 2 * (f2 - f1) / fs * cos(2 * PI * (f1 + f2) / 2 / fs * (i - (num_taps - 1) / 2.0)) / PI;
        } else {
            h[i] = 0;
        }
        hsum += h[i];
    }
    for (int i = 0; i < num_taps; i++) {
        h[i] /= hsum;
    }

    // 对信号进行滤波
    vector<double> filtered_signal;
    filtered_signal.resize(n);
    for (int i = 0; i < n; i++) {
        double sum = 0;
        for (int j = 0; j < num_taps; j++) {
            if (i >= j) {
                sum += h[j] * signal[i - j];
            }
        }
        filtered_signal[i] = sum;
    }

    // 将滤波后的信号复制回原信号
    for (int i = 0; i < n; i++) {
        signal[i] = filtered_signal[i];
    }
}

In this implementation, the FIR bandpass filter is defined as the bandpass_filter function. It accepts four parameters: the input signal signal , the cutoff frequencies f1 and f2 , and the sampling frequency fs , as well as the order of the filter (that is, the number of coefficients) num_taps . The function modifies the value of the input signal so that it is bandpass filtered.

Among them, the h array stores the coefficients of the filter, and the filtered_signal array stores the filtered signal. For a given order num_taps , the value of the h array is computed by selecting a bandpass region. The values ​​of the filtered_signal array are computed by convolving the signal with the filter coefficients.

IIR bandpass filter

The IIR filter is a type of digital filter that uses recursive coefficients in the discrete time domain to implement the filter function. Compared with the FIR filter, the IIR filter has a smaller order, faster calculation speed and smoother filtering characteristics. The following is an example of a simple C++ implementation of an IIR bandpass filter:

#include <cmath>
#include <vector>

using namespace std;

const double PI = 3.14159265358979323846;

// IIR带通滤波器
void bandpass_filter(vector<double>& signal, double f1, double f2, double fs, double Q) {
    int n = signal.size();

    // 计算滤波器系数
    double w1 = 2 * PI * f1 / fs;
    double w2 = 2 * PI * f2 / fs;
    double bw = w2 - w1;
    double wc = sqrt(w1 * w2);
    double alpha = sin(bw) / (2 * Q);
    double b0 = alpha;
    double b1 = 0;
    double b2 = -alpha;
    double a0 = 1 + alpha;
    double a1 = -2 * cos(wc);
    double a2 = 1 - alpha;

    // 对信号进行滤波
    double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
    for (int i = 0; i < n; i++) {
        double x0 = signal[i];
        double y0 = (b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2) / a0;
        signal[i] = y0;
        x2 = x1;
        x1 = x0;
        y2 = y1;
        y1 = y0;
    }
}

In this implementation, the IIR bandpass filter is defined as the bandpass_filter function. It accepts four parameters: the input signal signal , the cutoff frequencies f1 and f2 , and the sampling frequency fs , as well as the quality factor Q of the filter . The function modifies the value of the input signal so that it is bandpass filtered.

where b0 , b1 , b2 , a0 , a1 , a2 are the recursive and non-recursive coefficients of the IIR filter, respectively, and their values ​​are calculated by selecting a bandpass region. x1 , x2 , y1 , y2 are historical input and output samples of the IIR filter, which are used to implement the recursive process of the filter. signal[i] is the output sample for the current input sample, computed from recursive and non-recursive coefficients and historical input and output samples.

Guess you like

Origin blog.csdn.net/Q_Linfeng/article/details/129120537