天天看點

FIR數字濾波器 C語言頻域實作 matlab設計FIR參數一、FIR實作步驟二、FIR代碼實作三、代碼說明以及待完善

FIR數字濾波器 C語言頻域實作 matlab設計FIR參數

  • 一、FIR實作步驟
    • 1、FIR參數做FFT
    • 2、輸入資料做FFT
    • 3、FIR做複數乘積
    • 4、将複數乘積結果做IFFT輸出
  • 二、FIR代碼實作
    • 1、FIR參數的生成
    • 2、FIR系數做FFT計算
    • 3、輸入資料做overlap
    • 4、輸入資料做FFT
    • 5、資料做複數乘積
    • 6、資料做IFFT并輸出
  • 三、代碼說明以及待完善
    • 1、說明
    • 2、待完善

本文主要介紹用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

參數設定如下圖:

FIR數字濾波器 C語言頻域實作 matlab設計FIR參數一、FIR實作步驟二、FIR代碼實作三、代碼說明以及待完善

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長度的實作。

繼續閱讀