FIR数字滤波器 C语言频域实现 matlab设计FIR参数


本文主要介绍用C语言实现频域FIR。

一、FIR实现步骤

1、FIR参数做FFT

2、输入数据做FFT

3、FIR做复数乘积

4、将复数乘积结果做IFFT输出

二、FIR代码实现

1、FIR参数的生成

FIR的系数用matlab的FDA工具生成,设计参数:
FS:48000Hz
Fpass:2000Hz
Fstop:2500Hz
滤波器:低通 FIR
FIR阶数:511
Density Factor:20
参数设置如下图:
在这里插入图片描述

2、FIR系数做FFT计算

void FIRCoffesCal(void *processor)
{
	FFT_ELEM *fft = (FFT_ELEM *)processor;
	int i = 0,j = 0;
	memset(fft->overlap   ,0,sizeof(float)*(FFT_LENGTH<<1));
	memset(fft->FIR_CoffesIn,0,sizeof(float)*(FFT_LENGTH<<1));
	for(i=0; i< FIR_ORDER; i++)
	{
		fft->FIR_CoffesIn[i<<1]	= FIR_COFFES[i] ;//* fft->win[i]; //实部
	}
	DSPF_sp_fftSPxSP_cn(FFT_LENGTH, fft->FIR_CoffesIn,  fft->tw , fft->FIR_CoffesOut,fft->base, 0,FFT_LENGTH);
 
}

3、输入数据做overlap

   for(i=0; i< FFT_LENGTH-FRAME_LEN; i++)
	{
		fft->frameIn[i]   = fft->frameIn[i+FRAME_LEN] ;
	}
	for(i=0; i< FRAME_LEN; i++)
	{
		fft->frameIn[FFT_LENGTH-FRAME_LEN+i]   = x[i] ;
	}

4、输入数据做FFT

    for(i=0; i< FFT_LENGTH; i++)
	{
		fft->FFT_InData[i<<1]   = fft->frameIn[i] ;//* fft->win[i]; //实部
		fft->FFT_InData[(i<<1)+1] = 0 ;			   //虚部赋0
	}
	DSPF_sp_fftSPxSP_cn(FFT_LENGTH, fft->FFT_InData,  fft->tw , fft->FFT_outData,fft->base, 0,FFT_LENGTH);

5、数据做复数乘积

/*
struct Complex MUL(struct Complex a,struct Complex b)//定义复乘
{
   struct Complex c;
   c.real=a.real*b.real-a.imag*b.imag;
   c.imag=a.real*b.imag+a.imag*b.real;
   return(c);
}
*/
    fft->FIR_InData[0] = fft->FFT_outData[0]*fft->FIR_CoffesOut[0] - fft->FFT_outData[1]*fft->FIR_CoffesOut[1];//8.569;//
	fft->FIR_InData[1] = fft->FFT_outData[0]*fft->FIR_CoffesOut[1] + fft->FFT_outData[1]*fft->FIR_CoffesOut[0];
	fft->FIR_InData[FFT_LENGTH] = fft->FFT_outData[FFT_LENGTH]*fft->FIR_CoffesOut[FFT_LENGTH] - fft->FFT_outData[FFT_LENGTH+1]*fft->FIR_CoffesOut[FFT_LENGTH+1];
	fft->FIR_InData[FFT_LENGTH+1] = fft->FFT_outData[FFT_LENGTH]*fft->FIR_CoffesOut[FFT_LENGTH+1] + fft->FFT_outData[FFT_LENGTH+1]*fft->FIR_CoffesOut[FFT_LENGTH];

	for(i=2;i<FFT_LENGTH;i+=2)
	{
		fft->FIR_InData[i]   = fft->FFT_outData[i]*fft->FIR_CoffesOut[i]   - fft->FFT_outData[i+1]*fft->FIR_CoffesOut[i+1];
		fft->FIR_InData[i+1] = fft->FFT_outData[i]*fft->FIR_CoffesOut[i+1] + fft->FFT_outData[i+1]*fft->FIR_CoffesOut[i];
		fft->FIR_InData[FFT_LENGTH*2-i]   =   fft->FIR_InData[i];
		fft->FIR_InData[FFT_LENGTH*2-i+1] =  -fft->FIR_InData[i+1];
	}

6、数据做IFFT并输出

DSPF_sp_ifftSPxSP_cn(FFT_LENGTH, fft->FIR_InData,  fft->tw , fft->FIR_OutData,fft->base, 0,FFT_LENGTH);

	for(j=0;j<FRAME_LEN;j++)
	{
		y[j] = fft->FIR_OutData[(FFT_LENGTH>>1)+j<<1];//取后半部分
	}

三、代码说明以及待完善

1、说明

代码实现了频域FIR,针对overlap有两种方案,一种是FFT前做,一种是IFFT后做。代码未贴出,读写文件操作,以
及FFT和IFFT的实现,这个实现网上应该有大把。其中最关键的地方就是FIR复数乘积计算。尤其注意数据对称问题。

2、待完善

代码暂时支持的滤波器阶数必须小于FFT的长度,所以FFT长度做了一个特殊处理。后续完成滤波器长度大于FFT长度的实现。

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值