0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FIR频域重叠相加法

安费诺传感器学堂 来源:安费诺传感器学堂 2024-09-09 11:29 次阅读

[编者按]传感器信号处理仅一线之隔,信号的前后端合理搭配,是我们更准确地感知这个世界的一种基本态度和方式。

FIR频域重叠相加法

还记得我们(此处有重复之嫌)之前的发文《FIR连续采样分段卷积时域重叠相加法》?不过那是在时域处理的模拟仿真。这次我们的内容是用C++在频域实现的滤波卷积法,仍然是重叠相加法,届时大家可以比较一下两种方式的差异。

基本是通过两个处理过程。

(1)频域的重叠相加法示意图再拿来用一下。如下图所示[1]。

image.png

(2)再借用一下的时域卷积经傅里叶FFT变换后,在频域成为对应的相乘;然后再通过IFFT将中间结果转换回时域时序结果。

image.png

让我们直接跳进话题,先看模拟测试结果,后看C++源码。

模拟情节设定

50Hz选频滤波,信号中混有110Hz和210H在的干扰信号和幅值为1的直流DC

模拟信号及其频谱的输出请查看我们前面的文章。这里的代码只提供将模拟信号进行了频域重叠相加处理,生成的滤波前后模拟信号和被滤波处理后的数据波形的比较(见下图)。

还记得我们(此处重复)之前用C++来模拟时域处理的滤波模拟程序吗?

你又猜对了,又是那个滤波器,又被用上了!但,是不同的实现处理方式。

image.png

滤波处理之前的波形和频谱图

滤波之后,直流和其他频率的信号已经不见,只留下50Hz的正弦波(见下图)。

image.png

频域重叠相加滤波前后的波形比较

图由csv文件处理后生成。又见此图,是不是有熟悉的感觉?

频域连续滤波模拟和验证C++源码

/*
Project Name: Demonstration & Validation for signal filtering via the 
"Overlap-Add" method implemented through FFT/IFFT based on Fast Fourier Transform (FFT)
based on the Cooley-Tukey algorithm.
Copyright(c)2024AmphenolSensors
Author: L.L.


This software is provided 'as-is', without any express or implied
warrantyandforsimulation/demostrationpurpose.Innoeventwilltheauthorsbeheldliableforanydamages
arising from the use of this software.


Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:


The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


const double PI = 3.1415926535897932384;
const double SAMPLE_RATE = 1000.0;      // 1000Hz
const int N = 1024;                     // 假设采样分段数为1024


using namespace std; // 声明使用std命名空间


#define SEL_FFT     0
#define SEL_IFFT    1
#define SEL_FFTIFFT 2


#define SIM_CYCLE_CNT   3.0


// 模拟信号函数
vector> generateSignal(double sampleRate, double seconds)
{
    size_t signal_len = (size_t)(sampleRate * seconds);
    vector> signal(signal_len); // 定义模拟信号的数组长度
    for (size_t i = 0; i < signal_len; ++i)
    {
        // 包含50Hz和110Hz,210Hz信号,DC
        signal[i].real(1+ sin((2 * PI * (double)i * 50) / sampleRate) + sin((2 * PI * (double)i * 210) / sampleRate) + sin((2 * PI * (double)i * 110) / sampleRate));
        signal[i].imag(0);
    }
    return signal;
}


// 基于Cooley-Tukey算法的FFT
void fft2(vector> &x)
{
    size_t n = x.size();
    if (n <= 1)
        return;


    // 把序列分为奇偶两部分
    vector> even(n / 2), odd(n / 2);
    for (size_t i = 0; 2 * i < n; i++)
    {
        even[i] = x[i * 2];
        odd[i] = x[i * 2 + 1];
    }


    // 递归解决每一个序列
    fft2(even);
    fft2(odd);


    // 结合步骤
    for (size_t i = 0; 2 * i < n; i++)
    {
        complex t = polar(1.0, -2 * PI * (double)i / (double)n) * odd[i];
        x[i] = even[i] + t;
        x[i + n / 2] = even[i] - t;
    }
}
// 基于Cooley-Tukey算法的IFFT
void ifft2(vector> &x)
{
    size_t n = x.size();
    if (n <= 1)
        return;


    vector> even(n / 2), odd(n / 2);
    for (size_t i = 0; 2 * i < n; i++)
    {
        even[i] = x[i * 2];
        odd[i] = x[i * 2 + 1];
    }


    ifft2(even);
    ifft2(odd);


    for (size_t i = 0; 2 * i < n; i++)
    {
        complex t = polar(1.0, 2 * PI * (double)i /(double) n) * odd[i];
        x[i] = even[i] + t;
        x[i + n / 2] = even[i] - t;
    }
    // 最后除以n
    if (n > 1)
    {
        for (size_t i = 0; i < n; i++)
        {
            x[i] /= 2;
        }
    }
}


// 将数据写入文件
void writeToFile(const vector> &Original_signal, const vector> &Proceeded_Signal, const string &filename, int Type_sel)
{
    ofstream file(filename);
    if (Type_sel==SEL_FFTIFFT)
    {
        file << "time(s)" << ", " << "Original Signal"<< ", " << "Filtered Signal" << "
";
        for (size_t i = 0; i < Original_signal.size(); i++)
        {
            file << (double)i / SAMPLE_RATE << ", " < b{0.0010175493084400998, 0.0010954624020866333, 0.001080635650435545, 0.0009293052645812359,
                   0.0005868808563577278, -8.138309855847798e-19, -0.0008644147524968251, -0.0019966389877814107,
                   -0.003323586744207458, -0.004696461345361978, -0.005892320462621699, -0.006633249964255378,
                   -0.006623614506478284, -0.005601944833604465, -0.0034001773970723163, -7.334366341273803e-18,
                   0.004425290874832446, 0.00949426225087417, 0.014634010415364655, 0.019132982942933127,
                   0.022226796444847933, 0.023207550009729024, 0.021541722692400025, 0.01697833945185371,
                   0.009628503914736117, -6.755395515820625e-18, -0.01102370844120733, -0.02226281209657117,
                   -0.032372473621654914, -0.04001099412924139, -0.04402269970024527, -0.043609484958132556,
                   -0.03846490807520255, -0.028848803480728435, -0.015588116829396594, -9.10410551538968e-18,
                   0.016255406162706088, 0.031374390998733945, 0.04363491329762711, 0.051616779739690075,
                   0.05438594145724075, 0.051616779739690075, 0.04363491329762711, 0.031374390998733945,
                   0.016255406162706088, -9.10410551538968e-18, -0.015588116829396594, -0.028848803480728435,
                   -0.03846490807520255, -0.043609484958132556, -0.04402269970024527, -0.0400109941292414,
                   -0.032372473621654914, -0.022262812096571168, -0.01102370844120733, -6.755395515820627e-18,
                   0.009628503914736117, 0.016978339451853702, 0.021541722692400025, 0.023207550009729034,
                   0.022226796444847933, 0.01913298294293312, 0.014634010415364655, 0.009494262250874175,
                   0.004425290874832446, -7.3343663412738e-18, -0.0034001773970723163, -0.005601944833604469,
                   -0.006623614506478284, -0.006633249964255374, -0.005892320462621699, -0.00469646134536198,
                   -0.003323586744207458, -0.001996638987781409, -0.0008644147524968251, -8.138309855847805e-19,
                   0.0005868808563577278, 0.0009293052645812359, 0.001080635650435545, 0.0010954624020866333,
                   0.0010175493084400998};


    // (1) Resize filter coefficients
    vector> H(b.size());


    for(size_t i=0; i< b.size(); i++)
    {
        H[i] = complex(b[i],0);
    }
    H.resize(N, complex(0.0, 0.0));


    // (2)Generate simulation data sequences
    size_t DataSeg_len_L = N - b.size() + 1;                // Data segmeng Length = L


    double daq_duration = (double)DataSeg_len_L * SIM_CYCLE_CNT / SAMPLE_RATE;
    vector>Original_signal = generateSignal(SAMPLE_RATE, daq_duration);     // Generate data sequence, L * 3


    // (3-1) Define a 2-D vector,3 columns, to simulate DAQ and filtering process for 3 rounds
    vector>> seg_Dates(3); 
    // (3-2) Initialize data segment
    for (size_t i = 0; i < seg_Dates.size(); i++)
    {
        seg_Dates[i].resize(DataSeg_len_L,complex(0.0, 0.0));
        // devide Original_signal into 3 parts to simulate consequent DAQ for 3 cycles
        for(size_t j=0; j(0.0, 0.0));                     // resize each data segment to N = L + M - 1
    }


    // (4) Start to FFT/IFFT and generate involution result
    vector> Filtered_signal(DataSeg_len_L * (size_t)(SIM_CYCLE_CNT) +  b.size() -1 );     //L * 3 + (M - 1)
    fft2(H);  


//(4-1)Simulate3cyclesofinvolution:L*3
    for(size_t i=0; i< seg_Dates.size(); i++)
    {
        fft2(seg_Dates[i]);
        for(size_t j = 0; j< seg_Dates[i].size(); j++)
        {
            seg_Dates[i][j] = seg_Dates[i][j] * H[j];
        }


        ifft2(seg_Dates[i]);
        for(size_t k = 0; k< seg_Dates[i].size(); k++)
        {
            Filtered_signal[i*DataSeg_len_L + k] += seg_Dates[i][k];
        }
    }


    // (5) Save Origianl signal & result (data after filtering) into csv file
    writeToFile(Original_signal, Filtered_signal,"output_Filtered2.csv", SEL_FFTIFFT);


    return 0;
}

时间仓促,有些功能和细节并没有考虑太多,这里功能验证是第一。

FFT/IFFT是基于库里-图基的算法,各位可以选用其他的来优化替代;

有些参数可以单独变,有些参数却是关联的。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 传感器
    +关注

    关注

    2541

    文章

    49928

    浏览量

    747376
  • FIR
    FIR
    +关注

    关注

    4

    文章

    145

    浏览量

    32943
  • 频域
    +关注

    关注

    1

    文章

    86

    浏览量

    26225

原文标题:数字滤波器(6)—FIR频域连续滤波“重叠相加法”C++源码

文章出处:【微信号:安费诺传感器学堂,微信公众号:安费诺传感器学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    运算放大器的同相加法器和反相加法

      运算放大器构成加法器 可以分为同相加法器和反相加法
    发表于 08-05 17:17 2.9w次阅读
    运算放大器的同<b class='flag-5'>相加法</b>器和反<b class='flag-5'>相加法</b>器

    什么是加法器?加法器的原理是什么 ?

    什么是加法器?加法器的原理是什么 反相加法器等效原理图解析
    发表于 03-11 06:30

    相加法电路(由LF155组成的)

    相加法电路(由LF155组成的)
    发表于 01-21 14:16 4972次阅读
    同<b class='flag-5'>相加法</b>电路(由LF155组成的)

    相加法电路

    相加法运算电路为若干个输入信号从集成运放的反相输入端引入,输出信号为它们反相按比例放大的代数和。
    发表于 09-22 11:44 3210次阅读
    反<b class='flag-5'>相加法</b>电路

    相加法器电路原理与同相加法器计算

    相加法器输入阻抗高,输出阻抗低 反相加法器输入阻抗低,输出阻抗高.加法器是一种数位电路,其可进行数字的加法计算。当选用同相加法器时,如A输
    发表于 09-13 17:23 5.7w次阅读
    同<b class='flag-5'>相加法</b>器电路原理与同<b class='flag-5'>相加法</b>器计算

    运算电路:同相加法运算电路与反相加法运算电路解析

    加法运算电路能实现多个模拟量的求和运算。图1所示为一个3个输入信号的反相加法运算电路。
    发表于 05-15 09:41 20.5w次阅读
    运算电路:同<b class='flag-5'>相加法</b>运算电路与反<b class='flag-5'>相加法</b>运算电路解析

    加法器与减法器_反相加法器与同相加法

    加法器是产生数的和的装置。加数和被加数为输入,和数与进位为输出的装置为半加器。减法电路是基本集成运放电路的一种,减法电路可以由反相加法电路构成,也可以由差分电路构成。基本集成运放电路有加、减、积分和微分等四种运算。一般是由集成运放外加反馈网络所构成的运算电路来实现。
    发表于 08-16 11:09 16.4w次阅读
    <b class='flag-5'>加法</b>器与减法器_反<b class='flag-5'>相加法</b>器与同<b class='flag-5'>相加法</b>器

    相加法器原理图与电路图

    一、什么是加法加法器是为了实现加法的。即是产生数的和的装置。加数和被加数为输入,和数与进位为输出的装置为半
    的头像 发表于 03-16 15:57 2.1w次阅读
    反<b class='flag-5'>相加法</b>器原理图与电路图

    相加法器EWB电路仿真的详细资料免费下载

    本文档的主要内容详细介绍的是反相加法器EWB电路仿真的详细资料免费下载。
    发表于 09-21 15:38 12次下载
    反<b class='flag-5'>相加法</b>器EWB电路仿真的详细资料免费下载

    相加法器的应用领域

    相加法器(又称为同相组合器、输入能量合成器、同相求和器)是一种电子电路器件,主要应用在通信、信号处理、调试和测量等领域。
    的头像 发表于 06-06 17:21 1352次阅读
    同<b class='flag-5'>相加法</b>器的应用领域

    实用电路分享-同相加法

    相加法器(又称为同相组合器、输入能量合成器、同相求和器)是一种电子电路器件,主要应用在通信、信号处理、调试和测量等领域。
    的头像 发表于 06-13 14:53 1w次阅读
    实用电路分享-同<b class='flag-5'>相加法</b>器

    什么是反相加法运算电路?反相加法运算电路与减法运算电路

    在电子技术的海洋中,有一种电路如同数学中的加法器一样,能够将不同的信号进行相加处理。这就是被广泛应用于信号处理领域的反相加法运算电路。
    的头像 发表于 02-17 15:34 3391次阅读
    什么是反<b class='flag-5'>相加法</b>运算电路?反<b class='flag-5'>相加法</b>运算电路与减法运算电路

    相加法运算电路原理介绍

    相加法运算电路利用运算放大器(通常简称为Op-Amp)的特性来实现多个输入信号的加法运算。每个输入信号都通过一个电阻连接到运算放大器的反相输入端,而运算放大器的同相输入端则接地或虚拟接地。输出电压
    的头像 发表于 01-31 15:53 2423次阅读
    反<b class='flag-5'>相加法</b>运算电路原理介绍

    相加法器和反相加法器的区别是什么

    相加法器和反相加法器是运算放大器在模拟电路设计中常用的两种基本电路结构,它们在信号处理方面有着不同的特性和应用场景。
    的头像 发表于 05-23 14:35 1540次阅读

    FIR连续采样分段卷积时域重叠相加法

    在上一个文档里,我们提到了FIR系统在时域的分段卷积中使用“重叠保留(Overlap-Save)”的处理方式,这里我们续集,说明一下“重叠相加(Overlap-Add)”的处理方式。
    的头像 发表于 06-14 10:30 605次阅读
    <b class='flag-5'>FIR</b>连续采样分段卷积时域<b class='flag-5'>重叠</b><b class='flag-5'>相加法</b>