FIR数字滤波器 C语言实现

一、matlab生成FIR参数

matlab设置FIR低通滤波器;类型为Equiripple;Minimun order;Density Factor:20;FS:48000;Fpass:2000;Fstop:3000
截图如下:
在这里插入图片描述
matlab生成的文件:

/*
 * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool
 * Generated by MATLAB(R) 8.3 and the Signal Processing Toolbox 6.21.
 * Generated on: 09-Apr-2019 19:12:44
 */

/*
 * Discrete-Time FIR Filter (real)
 * -------------------------------
 * Filter Structure  : Direct-Form FIR
 * Filter Length     : 123
 * Stable            : Yes
 * Linear Phase      : Yes (Type 1)
 */

/* General type conversion for MATLAB generated C-code  */
#include "tmwtypes.h"
/* 
 * Expected path to tmwtypes.h 
 * C:\Program Files\MATLAB\R2014a\extern\include\tmwtypes.h 
 */
const int BL = 123;
const real64_T B[123] = {
  0.0001360451914991,0.0002262888817035,0.0003965803319844,0.0006312539200957,
  0.0009355633241083, 0.001309236648182, 0.001744872618442, 0.002226801945518,
   0.002730493014036, 0.003222772025161, 0.003663165534679, 0.004006360217194,
   0.004205541864475, 0.004216556097853, 0.004002816277717, 0.003540330440438,
   0.002822144453948, 0.001862120287894,0.0006973073109746,-0.0006119369920544,
  -0.001983640856593,-0.003318413157519,-0.004506446727724,-0.005435571887282,
  -0.006001870323296,-0.006119947527137,-0.005733568813427,-0.004824520298617,
   -0.00341927651389,-0.001592186502186,0.0005354126982925, 0.002800560784687,
   0.005008607037074, 0.006947276436672, 0.008403971523628, 0.009185160264968,
   0.009136320756536, 0.008160512460662, 0.006234031320806, 0.003417281486418,
  -0.000140582672696,-0.004203985407577,-0.008460927434939, -0.01254030346479,
    -0.0160355731694,  -0.0185336042736, -0.01964621013305, -0.01904244446867,
   -0.01647859242042, -0.01182363839845, -0.00507764624829, 0.003618723559849,
    0.01398475687634,  0.02561077650534,  0.03797936581551,   0.0504954195521,
    0.06252304008649,  0.07342670241521,  0.08261345985954,  0.08957326774504,
    0.09391406996638,  0.09538907833652,  0.09391406996638,  0.08957326774504,
    0.08261345985954,  0.07342670241521,  0.06252304008649,   0.0504954195521,
    0.03797936581551,  0.02561077650534,  0.01398475687634, 0.003618723559849,
   -0.00507764624829, -0.01182363839845, -0.01647859242042, -0.01904244446867,
   -0.01964621013305,  -0.0185336042736,  -0.0160355731694, -0.01254030346479,
  -0.008460927434939,-0.004203985407577,-0.000140582672696, 0.003417281486418,
   0.006234031320806, 0.008160512460662, 0.009136320756536, 0.009185160264968,
   0.008403971523628, 0.006947276436672, 0.005008607037074, 0.002800560784687,
  0.0005354126982925,-0.001592186502186, -0.00341927651389,-0.004824520298617,
  -0.005733568813427,-0.006119947527137,-0.006001870323296,-0.005435571887282,
  -0.004506446727724,-0.003318413157519,-0.001983640856593,-0.0006119369920544,
  0.0006973073109746, 0.001862120287894, 0.002822144453948, 0.003540330440438,
   0.004002816277717, 0.004216556097853, 0.004205541864475, 0.004006360217194,
   0.003663165534679, 0.003222772025161, 0.002730493014036, 0.002226801945518,
   0.001744872618442, 0.001309236648182,0.0009355633241083,0.0006312539200957,
  0.0003965803319844,0.0002262888817035,0.0001360451914991
};

二、FIR c语言实现

void process(float *x,float *y,int N)
{
	int i = 0,j = 0,k=0;
	float temp; 
	for (k = 0; k < N; k++) 
	{ 
		state[0] = x[k];
		for (i = 0, temp = 0; i < FIR_FILTER_LENGTH; i++)
			temp += FIR_COFFES[i] * state[i];
		y[k] = temp;
		for (j = FIR_FILTER_LENGTH - 1; j > -1 ; j--)
		state[j+1] = state[j];
	}
}

三、VS工程项目

我的项目是用一个123阶的FIR低通滤波器滤除4k以后的信号,所以我的测试文件含有500Hz,1000Hz,2000Hz,4000Hz信号叠加。测试文件为48K采样率,32位float,小端模式,单声道。

#include <stdio.h>
#include <math.h>
#define FRAME_READ_LENGTH   (256)
#define Factor 2.0*3.1415926/48000.0
#define FIR_FILTER_LENGTH 123
float FIR_COFFES[FIR_FILTER_LENGTH]=
{  
  0.0001360451914991,0.0002262888817035,0.0003965803319844,0.0006312539200957,
  0.0009355633241083, 0.001309236648182, 0.001744872618442, 0.002226801945518,
   0.002730493014036, 0.003222772025161, 0.003663165534679, 0.004006360217194,
   0.004205541864475, 0.004216556097853, 0.004002816277717, 0.003540330440438,
   0.002822144453948, 0.001862120287894,0.0006973073109746,-0.0006119369920544,
  -0.001983640856593,-0.003318413157519,-0.004506446727724,-0.005435571887282,
  -0.006001870323296,-0.006119947527137,-0.005733568813427,-0.004824520298617,
   -0.00341927651389,-0.001592186502186,0.0005354126982925, 0.002800560784687,
   0.005008607037074, 0.006947276436672, 0.008403971523628, 0.009185160264968,
   0.009136320756536, 0.008160512460662, 0.006234031320806, 0.003417281486418,
  -0.000140582672696,-0.004203985407577,-0.008460927434939, -0.01254030346479,
    -0.0160355731694,  -0.0185336042736, -0.01964621013305, -0.01904244446867,
   -0.01647859242042, -0.01182363839845, -0.00507764624829, 0.003618723559849,
    0.01398475687634,  0.02561077650534,  0.03797936581551,   0.0504954195521,
    0.06252304008649,  0.07342670241521,  0.08261345985954,  0.08957326774504,
    0.09391406996638,  0.09538907833652,  0.09391406996638,  0.08957326774504,
    0.08261345985954,  0.07342670241521,  0.06252304008649,   0.0504954195521,
    0.03797936581551,  0.02561077650534,  0.01398475687634, 0.003618723559849,
   -0.00507764624829, -0.01182363839845, -0.01647859242042, -0.01904244446867,
   -0.01964621013305,  -0.0185336042736,  -0.0160355731694, -0.01254030346479,
  -0.008460927434939,-0.004203985407577,-0.000140582672696, 0.003417281486418,
   0.006234031320806, 0.008160512460662, 0.009136320756536, 0.009185160264968,
   0.008403971523628, 0.006947276436672, 0.005008607037074, 0.002800560784687,
  0.0005354126982925,-0.001592186502186, -0.00341927651389,-0.004824520298617,
  -0.005733568813427,-0.006119947527137,-0.006001870323296,-0.005435571887282,
  -0.004506446727724,-0.003318413157519,-0.001983640856593,-0.0006119369920544,
  0.0006973073109746, 0.001862120287894, 0.002822144453948, 0.003540330440438,
   0.004002816277717, 0.004216556097853, 0.004205541864475, 0.004006360217194,
   0.003663165534679, 0.003222772025161, 0.002730493014036, 0.002226801945518,
   0.001744872618442, 0.001309236648182,0.0009355633241083,0.0006312539200957,
  0.0003965803319844,0.0002262888817035,0.0001360451914991
};
float state[FIR_FILTER_LENGTH+1]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void process(float *x,float *y,int N)
{
	int i = 0,j = 0,k=0;
	float temp; 
	for (k = 0; k < N; k++) 
	{ 
		state[0] = x[k];
		for (i = 0, temp = 0; i < FIR_FILTER_LENGTH; i++)
			temp += FIR_COFFES[i] * state[i];
		y[k] = temp;
		for (j = FIR_FILTER_LENGTH - 1; j > -1 ; j--)
		state[j+1] = state[j];
	}
}
int main()
{
	int nReadLen = 0;
	FILE *pSrcFile = fopen("..\\sin500-1000-2000-4000.pcm","rb");
	FILE *pDstFile = fopen("..\\write.pcm","wb");
	float pReadData[FRAME_READ_LENGTH] = {0};	
	float pWriteData[FRAME_READ_LENGTH] = {0};
	#if 0//统计FIR参数之和 1.01
	int i = 0,k = 0;
	float temp; 
	for (i = 0, temp = 0; i < FIR_FILTER_LENGTH; i++)
		temp += FIR_COFFES[i];
	printf("%lf\n",temp);
	#endif
	if ((pSrcFile == NULL)||(pDstFile == NULL))
	{
			return 0 ;
	}
	nReadLen  = fread(pReadData,sizeof(float),FRAME_READ_LENGTH,pSrcFile);
	while(nReadLen==FRAME_READ_LENGTH) 
	{
		process(pReadData,pWriteData,FRAME_READ_LENGTH);
		fwrite(pWriteData,sizeof(float),FRAME_READ_LENGTH,pDstFile);
		nReadLen  = fread(pReadData,sizeof(float),FRAME_READ_LENGTH,pSrcFile);
	}
	fclose(pSrcFile);
	fclose(pDstFile);
	printf("----------finished!--------\n");
	return 0;
}

四、信号频谱图对比

滤波前:
在这里插入图片描述

滤波后:在这里插入图片描述

FIR带通滤波器是一种常见的数字滤波器,可以在频域上选择一定范围内的频率进行滤波处理。其原理是通过对输入信号的每个采样点进行加权求和的方式实现滤波效果。 在C语言实现FIR带通滤波器,可以按照以下步骤进行: 1. 定义滤波器的系数数组:根据设计要求,选择一组合适的FIR滤波器系数,可以通过一些滤波器设计工具或者使用经验公式得到。 2. 定义输入和输出的缓冲数组:根据实际应用场景的采样率和信号长度,定义输入和输出信号的缓冲数组。 3. 实现滤波器的计算过程:使用一个循环结构,对输入信号的每个采样点进行滤波计算。在每个采样点上,按照系数数组的长度,对输入信号和系数数组进行加权求和操作,得到输出信号的一个采样点。 4. 更新输入信号缓冲数组:在每次计算完一个采样点之后,需要更新输入信号缓冲数组,以便继续计算下一个采样点的输出。 5. 返回输出信号:当处理完所有输入信号的采样点之后,将输出信号返回给调用者。 需要注意的是,在实际的应用中,FIR带通滤波器的系数和输入信号的采样点可能会很大,因此需要优化算法的性能和效率,例如可以使用快速傅里叶变换(FFT)等技术来加速计算过程。 总的来说,用C语言实现FIR带通滤波器,需要定义滤波器系数、输入和输出缓冲数组,并通过循环结构对每个采样点进行滤波计算,最后返回输出信号。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值