实时(按帧)处理的低通滤波C语言实现

news/2024/9/18 20:24:14/ 标签: c语言

写在前面:

低通滤波采用一般的FIR滤波器,因为本次任务,允许的延迟较多,或者说前面损失的信号可以较多,因此,涉及一个很高阶的FIR滤波器,信号起始段的信号点可以不处理,以及,考虑延时,当前时刻向前推一个时刻(当前帧处理的最后一点的时刻)之后的点,当前帧也先不处理。

因为FIR也有延时,经过稍加设计后,这个延时和信号本身的延时差不多一致,这样能将性能和延时兼顾。

简单来说,信号采样率256,延时2秒,第2秒处理第0.5秒到1.5秒的数据,下一秒即第3秒,再处理1.5秒到2.5秒的数据。

设置滤波器长度为128。

对前2秒数据,计算第0.5秒到1.5秒数据,即第128点到384点,为消除滤波延时,滤波数据起始点设置在第128(数据起点)+64(滤波器半长)+ 1=193点,易知此点前有192点,远大于滤波器长的128点;滤波数据终点在第384+64=448点,也没取到最后的512点,即,首尾取点还有64点的盈余。

当然,按照上述分析,我们完全可以将滤波器长度设置为128*2,即256,此时则刚好将延时和数据点最大偏移用完,即滤波数据起点为第1点,终点为最后的512点。但是,滤波器越长,计算量越大。matlab看滤波路效果,128阶的够用了。因此就用128阶的。

下面直接上代码了:

C代码:

Lowpass.h

#pragma once
#include"stdint.h"extern void Lowpass_init();
extern uint8_t Lowpass(int16_t* data_frame, int16_t* data_frame_out, int16_t SampleRate);

Lowpass.c

#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"stdint.h"
#include "assert.h" #define  POINT_FRAME  (256)  // (SAMPLERATE*T_FRAME*T_FRAME)typedef struct {float DataBuf[2 * POINT_FRAME];float DataAfFir[POINT_FRAME + (POINT_FRAME >> 1)];uint64_t FrameCnt;  // 
}LowpassPra_t;
LowpassPra_t  LowpassPra = { 0 };// FIR 45Hz低通
#define FIR_LEN  (128)
static float fir_coef_b[FIR_LEN + 1] ={0.001364, -0.001009, -0.001358, -0.000845, 0.000328, 0.000870, 0.000046, -0.001164, -0.001094, 0.000425, 0.001572, 0.000723, -0.001273, -0.001857, -0.000006, 0.002128, 0.001681, -0.001116, -0.002802, -0.000929, 0.002459, 0.002985, -0.000451, -0.003734, -0.002413, 0.002331, 0.004545, 0.000925, -0.004396, -0.004473, 0.001453, 0.006163, 0.003177, -0.004447, -0.007040, -0.000497, 0.007527, 0.006437, -0.003443, -0.009946, -0.003896, 0.008190, 0.010827, -0.000795, -0.012942, -0.009279, 0.007504, 0.016601, 0.004484, -0.015728, -0.017795, 0.004292, 0.024643, 0.014802, -0.017997, -0.033204, -0.004871, 0.039100, 0.040318, -0.019479, -0.078933, -0.045026, 0.108777, 0.295845, 0.380006, 0.295845, 0.108777, -0.045026, -0.078933, -0.019479, 0.040318, 0.039100, -0.004871, -0.033204, -0.017997, 0.014802, 0.024643, 0.004292, -0.017795, -0.015728, 0.004484, 0.016601, 0.007504, -0.009279, -0.012942, -0.000795, 0.010827, 0.008190, -0.003896, -0.009946, -0.003443, 0.006437, 0.007527, -0.000497, -0.007040, -0.004447, 0.003177, 0.006163, 0.001453, -0.004473, -0.004396, 0.000925, 0.004545, 0.002331, -0.002413, -0.003734, -0.000451, 0.002985, 0.002459, -0.000929, -0.002802, -0.001116, 0.001681, 0.002128, -0.000006, -0.001857, -0.001273, 0.000723, 0.001572, 0.000425, -0.001094, -0.001164, 0.000046, 0.000870, 0.000328, -0.000845, -0.001358, -0.001009, 0.001364,
};uint8_t fir_filter_zhh(float* sig_in, float* sig_out, uint16_t sig_len)
{assert(sig_len > 1);uint16_t i, j;for (i = 0; i < sig_len; i++) {sig_out[i] = 0;for (j = 0; j < FIR_LEN; j++) {sig_out[i] += sig_in[i - j] * fir_coef_b[j];}}return 0;
}void Lowpass_init() {//memset(LowpassPra.DataBuf, 0, sizeof(LowpassPra.DataBuf));//memset(LowpassPra.DataAfFir, 0, sizeof(LowpassPra.DataAfFir));LowpassPra.FrameCnt = 0;}// 数据按帧传入,同时要传入帧号
uint8_t Lowpass(int16_t* data_frame, int16_t* data_frame_out, int16_t SampleRate)
{int16_t i;// 限制采样率必须是256if (SampleRate != 256) {//printf("SampleRate error!\n");return 1;}LowpassPra.FrameCnt++;  // 函数里面帧号从1开始计数if (LowpassPra.FrameCnt == 1) {memset(LowpassPra.DataBuf, 0 ,sizeof(LowpassPra.DataBuf));for (i = 0; i < POINT_FRAME;i++) {LowpassPra.DataBuf[i + POINT_FRAME] = (float)data_frame[i];}//memset(LowpassPra.DataAfFir, 0, sizeof(LowpassPra.DataAfFir));//memset(LowpassPra.DataTmp, 0, sizeof(LowpassPra.DataTmp));}else {memcpy(&LowpassPra.DataBuf[0], &LowpassPra.DataBuf[POINT_FRAME], POINT_FRAME * sizeof(LowpassPra.DataBuf[0]));  // 左移for (i = 0; i < POINT_FRAME; i++) {LowpassPra.DataBuf[POINT_FRAME + i] = (float)data_frame[i];}int16_t m = fir_filter_zhh(&LowpassPra.DataBuf[(POINT_FRAME >> 1) + (FIR_LEN >> 1)], &LowpassPra.DataAfFir[0], POINT_FRAME);for (i = 0; i < POINT_FRAME; i++) {data_frame_out[i] = (int16_t)LowpassPra.DataAfFir[i];}}  // if (sensoringCtrlPra.rCnt > 1)return  0;
}

测试代码:

main.c

#include<stdio.h>
#include<stdlib.h>
#include<math.h>#include"Lowpass.h"#define SampleRate (256)#define FrameNum (20)// 读matlab转换采样率为SampleRate后的txt数据文件
int16_t data_in[FrameNum * SampleRate] = { 0 };
int16_t data_out[FrameNum * SampleRate] = { 0 };
int16_t data_size = FrameNum * SampleRate;int8_t main()
{int16_t i;uint8_t ret;int16_t read_data_size = 0;FILE* fp;fp = fopen("Sign_input.txt", "r");if (fp == NULL){return 0;}for (i = 0; i < data_size; i++){ret = fscanf(fp, "%d", data_in + i); // 1:读文件成功,则返回成功读取的项数;2:读文件失败,则返回EOF。if (ret == 1)read_data_size++;}fclose(fp);if ((fp = fopen("data_in.txt", "w")) == NULL){printf("Cannot open the file...");exit(1);}for (i = 0; i < FrameNum * SampleRate; i++){fprintf(fp, "%d\n", data_in[i]);}fclose(fp);Lowpass_init();for (i = 0; i < FrameNum; i++) {ret = Lowpass(data_in + i * SampleRate, data_out + i * SampleRate - (SampleRate >> 1), SampleRate);//ret = Lowpass(data_in + i * SampleRate, data_out + i * SampleRate, SampleRate);if (ret) {return 1;}}if ((fp = fopen("data_out.txt", "w")) == NULL){printf("Cannot open the file...");exit(1);}for (i = 0; i < FrameNum * SampleRate; i++){fprintf(fp, "%d\n", data_out[i]);}fclose(fp);return 0;
}

附带对数据或者说调试的matlab代码:

fir_lowpass_45_50_order128.m

function Hd = fir_lowpass_45_50_order128
%FIR_LOWPASS_45_50_ORDER128 Returns a discrete-time filter object.% MATLAB Code
% Generated by MATLAB(R) 9.5 and Signal Processing Toolbox 8.1.
% Generated on: 11-Sep-2024 11:13:54% Equiripple Lowpass filter designed using the FIRPM function.% All frequency values are in Hz.
Fs = 250;  % Sampling FrequencyN     = 128;  % Order
Fpass = 45;   % Passband Frequency
Fstop = 50;   % Stopband Frequency
Wpass = 1;    % Passband Weight
Wstop = 1;    % Stopband Weight
dens  = 20;   % Density Factor% Calculate the coefficients using the FIRPM function.
b  = firpm(N, [0 Fpass Fstop Fs/2]/(Fs/2), [1 1 0 0], [Wpass Wstop], ...{dens});
Hd = dfilt.dffir(b);% [EOF]

test_vs.m

%%% 和vs对数据程序close all,clear,clc% fs = 200;
% f1 = 3;f2 = 40;
% t = 0:1/fs:1-1/fs;
% x = sin(2*pi*t*f1)+0.25*sin(2*pi*t*f2);load('..\data_in.txt');
load('..\data_out.txt');figure
plot(data_in)
hold on
plot(data_out)fid=fopen('..\data_in.txt'); %D:\zhh\work\VS projects\filter_int_v3
x=fscanf(fid,'%d');
fclose(fid);filename = 'data.txt';
% dlmwrite(filename, x);
fid = fopen(filename, 'w');
for i=1:length(x)fprintf(fid, '%.6f, ', x(i));
end
fclose(fid);%Hd = fir_lowhpass_40_50_equiripple;
Hd = fir_lowpass_45_50_order128;% 直接matlab滤波
[b, a] = tf(Hd);
% b=[1,2,1,3,1 ];
% a=[1,1,1,1,1 ];
y1 = iir_filter_zhh(b,a,x);
figure
plot(x);hold on
plot(y1);y2 = flipud(  filter( b,a,flipud(y1) )  );
figure
plot(x);hold on
plot(y2);filename = 'data_fir.txt';
fid = fopen(filename, 'w');
for i=1:length(x)fprintf(fid, '%.6f\n', y2(i));
end
fclose(fid);zhh = 1;

写在最后:

关于滤波器的幅值校正,或者说增益,这方面的资料很少,还需要进一步研究。


http://www.ppmy.cn/news/1526106.html

相关文章

Spring boot中常用注解解释

Data 是Lombok提供的注解&#xff0c;结合了以下几个常用注解的功能&#xff1a; Getter: 自动为所有字段生成getter方法。 Setter: 自动为所有字段生成setter方法。 ToString: 自动生成toString()方法。 EqualsAndHashCode: 自动生成equals()和hashCode()方法。 RequiredArgs…

HTML5中`<span>`标签深入解析

引言 在HTML5中&#xff0c;<span>标签是一个行内元素&#xff0c;用于对文档中的一小部分文本或内容进行分组&#xff0c;以便于应用CSS样式或JavaScript脚本。与块级元素&#xff08;如<div>&#xff09;不同&#xff0c;<span>不会打断文本的流动&#x…

设计模式之单例模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、单例模式概述2、懒汉式&#xff1a;3、饿汉式4、懒汉式&#xff1a;解决反射、序列化反序列化问题5、懒汉式DCL&#xff08;推荐&#xff09;6、应用场景7、单例线程池实现8、总结 设计模式概述 创建型模式&#xff1a;工厂方法、抽象方法、建造者、原…

conda、anaconda、pip、torch、pytorch、tensorflow到底是什么东西?(转载自本人的知乎回答)

转载自本人的知乎回答&#xff08;截止2024年9月&#xff0c;1700赞同&#xff0c;2400收藏&#xff09; https://www.zhihu.com/question/566592612/answer/3063465880 如果你是一个大四的CS准研究生回去补基础课&#xff0c;假如是科班CS甚至科班EE的话那你基础也太差了。你…

相亲交友程序系统开发产品分析

相亲交友系统是一种专门为单身人士设计的社交平台&#xff0c;旨在帮助他们找到合适的伴侣。这类系统通常包括了线上和线下的多种互动方式&#xff0c;能够让参与者在舒适的环境中相识、相知。编辑&#xff1a;qawsed2466。以下是相亲交友系统的一些关键特点和优势&#xff1a;…

AI算法部署方式对比分析:哪种方案性价比最高?

随着人工智能技术的飞速发展&#xff0c;AI算法在各个领域的应用日益广泛。AI算法的部署方式直接关系到系统的性能、实时性、成本及安全性等多个方面。本文将探讨AI算法分析的三种主要部署方式&#xff1a;本地计算、边缘计算和云计算&#xff0c;并详细分析它们的优劣性。 一、…

计算机毕业设计选题推荐-推拿知识互动平台-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

基于微信小程序的宠物之家的设计与实现

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的宠物之家/宠物综合…

feign client发送Post请求,发送对象参数,服务端接收不到正确参数报错排查

记一次feignclient发送请求服务端接收不到正确参数排查 服务端代码&#xff1a; Operation(summary "Create team")PostMapping("post")RequiresPermissions("team:add")public RestResponse addTeam(Valid Team team) {this.teamService.crea…

『功能项目』切换职业技能面板【49】

我们打开上一篇48切换职业面板的项目&#xff0c; 本章要做的事情是制作第二职业法师技能面板、第三职业面板并且完成切换 双击打开Canvas进入预制体空间 复制三个技能栏面板 重命名 设置第一技能栏 设置第二职业技能栏 设置第三职业技能栏 修改脚本&#xff1a;ChangeProfess…

经纬恒润高压电池管理系统,助力新能源汽车飞速发展

随着新能源汽车行业的快速发展&#xff0c;电池管理系统作为关键技术之一&#xff0c;其重要性日益凸显。经纬恒润自主研发的高压电池管理系统&#xff08;Battery Management System&#xff0c;BMS&#xff09;&#xff0c;凭借卓越的性能与先进的技术&#xff0c;在新能源汽…

Mac清理其他文件:释放存储空间的高效指南

每个Mac用户都可能遇到存储空间不足的问题&#xff0c;尤其是当“其他”文件积累到一定体积时。在Mac上&#xff0c;“其他”文件通常包括各种系统文件、缓存、文档以及不被归类为应用程序、照片、电影或音乐的其他类型的文件。这些文件往往不易被注意&#xff0c;但逐渐占用了…

量化交易的个人见解

程序化交易在国内兴起有些年数了&#xff0c;个人以为&#xff0c;程序化交易与量化投资的关系&#xff0c;在于两者侧重点有差别。程序化交易侧重于下单的动作是机器自动执行的&#xff0c;量化投资则侧重于投资分析的过程是通过一个量化模型来实现的&#xff0c;所以量化投资…

LocalMamba: Visual State Space Model with Windowed Selective Scan 论文总结

题目&#xff1a;LocalMamba: Visual State Space Model&#xff08;视觉状态空间模型&#xff09; with Windowed Selective Scan&#xff08;窗口化的选择扫描&#xff09; 论文&#xff1a;[2403.09338] LocalMamba: Visual State Space Model with Windowed Selective Scan…

iPhone 16即将推出的5项苹果智能功能

在苹果的’Glowtime’ iPhone和Apple Watch发布会上&#xff0c;苹果宣布包括基础版和Pro版在内的iPhone 16从头开始都考虑了Apple Intelligence。这包括更新的Apple Silicon&#xff0c;改进的神经引擎&#xff0c;新硬件控制&#xff0c;以及最快下个月即将推出的操作系统改变…

深度学习驱动的车牌识别:技术演进与未来挑战

一、引言 1.1 研究背景 在当今社会&#xff0c;智能交通系统的发展日益重要&#xff0c;而车牌识别作为其关键组成部分&#xff0c;发挥着至关重要的作用。车牌识别技术广泛应用于交通管理、停车场管理、安防监控等领域。在交通管理中&#xff0c;它可以用于车辆识别、交通违…

Playwright 自动化验证码教程

Playwright 自动化点击验证码教程 在自动化测试中&#xff0c;Playwright 是一个流行的浏览器自动化工具&#xff0c;支持多种浏览器的高效操作。验证码&#xff08;如图片验证码、滑动验证码等&#xff09;是网页中常见的反自动化机制&#xff0c;常常需要特别处理。我们将介…

React学习笔记(1.0)

在使用vite创建react时&#xff0c;有一个语言选项&#xff0c;就是typescript-SWC&#xff0c;这里介绍一下SWC。 SWC&#xff1a;可扩展的Rust的平台&#xff0c;用于下一代快速开发工具&#xff0c;SWC比Babel快20倍。 简单来说&#xff0c;就是用于格式转换的&#xff0c…

Vue: 创建vue项目

目录 一.创建项目 二.项目添加 三.添加成功 一.创建项目 打开本机终端输入npm create vuelatest 二.项目添加 1. 项目名称&#xff1a; Project name: one_vue 2.是否添加TypeScript支持&#xff1a;Add TypeScript? Yes 3.是否添加JSX支持&#xff1a;Add JSX Suppor…

使用transform对html的video播放器窗口放大

核心是使用 <div class"video" style"width: 100%; height:700px;">播放容器</div>$(video).css({transform: scale(2),transform-origin: center top}); 其中 scale 表示放大倍数&#xff0c;可以是小数 transform-origin 表示位置&#…