不利用模拟滤波器,直接进行数字滤波器的设计的方法,称为直接设计。回忆之前所说的IIR滤波器的直接设计,我们首先设计了巴特沃斯模拟滤波器,然后进行双线性变换,得到数字滤波器。我所使用的是巴特沃斯低通滤波器作为原型滤波器,其振幅特性如下所示。
N = Ceil(0.5*( log10 ( pow (10, IIR_Filter.Stopband_attenuation/10) - 1) / log10 (IIR_Filter.Stopband/IIR_Filter.Cotoff)));
poles_1.Real_part = (0.5)*Cotoff*cos((k+dk)*(pi/N)); poles_1.Imag_Part= (0.5)*Cotoff*sin((k+dk)*(pi/N));
for(k = 0;k <= ((2*N)-1) ; k++) { poles_1.Real_part = (0.5)*Cotoff*cos((k+dk)*(pi/N)); poles_1.Imag_Part= (0.5)*Cotoff*sin((k+dk)*(pi/N)); poles_2.Real_part = 1 - poles_1.Real_part ; poles_2.Imag_Part= -poles_1.Imag_Part; poles_1.Real_part = poles_1.Real_part + 1; poles_1.Real_part = poles_1.Real_part; Complex_Division(poles_1,poles_2, &poles[count].Real_part, &poles[count].Imag_Part); if(Complex_Abs(poles[count])<1) { poles[count].Real_part = -poles[count].Real_part; poles[count].Imag_Part= -poles[count].Imag_Part; count++; if (count == N) break; } }这里的计算,用到了复数的乘法与绝对值。
int Complex_Division(COMPLEX a,COMPLEX b, double *Res_Real,double *Res_Imag) { *(Res_Real) = ((a.Real_part)*(b.Real_part) + (a.Imag_Part)*(b.Imag_Part))/ ((b.Real_part)*(b.Real_part) + (b.Imag_Part)*(b.Imag_Part)); *(Res_Imag)= ((a.Real_part)*(b.Imag_Part) - (a.Imag_Part)*(b.Real_part))/ ((b.Real_part)*(b.Real_part) + (b.Imag_Part)*(b.Imag_Part)); return (int)1; } double Complex_Abs(COMPLEX a) { return (double)(sqrt((a.Real_part)*(a.Real_part) + (a.Imag_Part)*(a.Imag_Part))); }还有就是K的计算。
double K_z = 0.0; for(count = 0;count <= N;count++) {K_z += *(az+count);} K_z = (K_z/pow ((double)2,N));最后,使用之前在IIR的间接设计的乘开算法,我们就可以得到一个模拟滤波器的系数了。
#include <stdio.h> #include <math.h> #include <malloc.h> #include <string.h> #define pi ((double)3.1415926) typedef struct { double Real_part; double Imag_Part; } COMPLEX; struct DESIGN_SPECIFICATION { double Cotoff; double Stopband; double Stopband_attenuation; }; int Ceil(double input) { if(input != (double)((int)input)) return ((int)input) +1; else return ((int)input); } int Complex_Multiple(COMPLEX a,COMPLEX b, double *Res_Real,double *Res_Imag) { *(Res_Real) = (a.Real_part)*(b.Real_part) - (a.Imag_Part)*(b.Imag_Part); *(Res_Imag)= (a.Imag_Part)*(b.Real_part) + (a.Real_part)*(b.Imag_Part); return (int)1; } int Complex_Division(COMPLEX a,COMPLEX b, double *Res_Real,double *Res_Imag) { *(Res_Real) = ((a.Real_part)*(b.Real_part) + (a.Imag_Part)*(b.Imag_Part))/ ((b.Real_part)*(b.Real_part) + (b.Imag_Part)*(b.Imag_Part)); *(Res_Imag)= ((a.Real_part)*(b.Imag_Part) - (a.Imag_Part)*(b.Real_part))/ ((b.Real_part)*(b.Real_part) + (b.Imag_Part)*(b.Imag_Part)); return (int)1; } double Complex_Abs(COMPLEX a) { return (double)(sqrt((a.Real_part)*(a.Real_part) + (a.Imag_Part)*(a.Imag_Part))); } double IIRFilter (double *a, int Lenth_a, double *b, int Lenth_b, double Input_Data, double *Memory_Buffer) { int Count; double Output_Data = 0; int Memory_Lenth = 0; if(Lenth_a >= Lenth_b) Memory_Lenth = Lenth_a; else Memory_Lenth = Lenth_b; Output_Data += (*a) * Input_Data; //a(0)*x(n) for(Count = 1; Count < Lenth_a ;Count++) { Output_Data -= (*(a + Count)) * (*(Memory_Buffer + (Memory_Lenth - 1) - Count)); } //------------------------save data--------------------------// *(Memory_Buffer + Memory_Lenth - 1) = Output_Data; Output_Data = 0; //----------------------------------------------------------// for(Count = 0; Count < Lenth_b ;Count++) { Output_Data += (*(b + Count)) * (*(Memory_Buffer + (Memory_Lenth - 1) - Count)); } //------------------------move data--------------------------// for(Count = 0 ; Count < Memory_Lenth -1 ; Count++) { *(Memory_Buffer + Count) = *(Memory_Buffer + Count + 1); } *(Memory_Buffer + Memory_Lenth - 1) = 0; //-----------------------------------------------------------// return (double)Output_Data; } int Direct( double Cotoff, double Stopband, double Stopband_attenuation, int N, double *az,double *bz) { printf("Wc = %lf [rad/sec] \n" ,Cotoff); printf("Ws = %lf [rad/sec] \n" ,Stopband); printf("As = %lf [dB] \n" ,Stopband_attenuation); printf("--------------------------------------------------------\n" ); printf("N: %d \n" ,N); printf("--------------------------------------------------------\n" ); COMPLEX poles[N],poles_1,poles_2; double dk = 0; int k = 0; int count = 0,count_1 = 0;; if((N%2) == 0) dk = 0.5; else dk = 0; for(k = 0;k <= ((2*N)-1) ; k++) { poles_1.Real_part = (0.5)*Cotoff*cos((k+dk)*(pi/N)); poles_1.Imag_Part= (0.5)*Cotoff*sin((k+dk)*(pi/N)); poles_2.Real_part = 1 - poles_1.Real_part ; poles_2.Imag_Part= -poles_1.Imag_Part; poles_1.Real_part = poles_1.Real_part + 1; poles_1.Real_part = poles_1.Real_part; Complex_Division(poles_1,poles_2, &poles[count].Real_part, &poles[count].Imag_Part); if(Complex_Abs(poles[count])<1) { poles[count].Real_part = -poles[count].Real_part; poles[count].Imag_Part= -poles[count].Imag_Part; count++; if (count == N) break; } } printf("pk = \n" ); for(count = 0;count < N ;count++) { printf("(%lf) + (%lf i) \n" ,-poles[count].Real_part ,-poles[count].Imag_Part); } printf("--------------------------------------------------------\n" ); COMPLEX Res[N+1],Res_Save[N+1]; Res[0].Real_part = poles[0].Real_part; Res[0].Imag_Part= poles[0].Imag_Part; Res[1].Real_part = 1; Res[1].Imag_Part= 0; for(count_1 = 0;count_1 < N-1;count_1++) { for(count = 0;count <= count_1 + 2;count++) { if(0 == count) { Complex_Multiple(Res[count], poles[count_1+1], &(Res_Save[count].Real_part), &(Res_Save[count].Imag_Part)); } else if((count_1 + 2) == count) { Res_Save[count].Real_part += Res[count - 1].Real_part; Res_Save[count].Imag_Part += Res[count - 1].Imag_Part; } else { Complex_Multiple(Res[count], poles[count_1+1], &(Res_Save[count].Real_part), &(Res_Save[count].Imag_Part)); Res_Save[count].Real_part += Res[count - 1].Real_part; Res_Save[count].Imag_Part += Res[count - 1].Imag_Part; } } for(count = 0;count <= N;count++) { Res[count].Real_part = Res_Save[count].Real_part; Res[count].Imag_Part= Res_Save[count].Imag_Part; *(az + N - count) = Res[count].Real_part; } } double K_z = 0.0; for(count = 0;count <= N;count++) {K_z += *(az+count);} K_z = (K_z/pow ((double)2,N)); printf("K = %lf \n" , K_z); for(count = 0;count <= N;count++) { Res[count].Real_part = 0; Res[count].Imag_Part= 0; Res_Save[count].Real_part = 0; Res_Save[count].Imag_Part= 0; } COMPLEX zero; zero.Real_part = 1; zero.Imag_Part = 0; Res[0].Real_part = 1; Res[0].Imag_Part= 0; Res[1].Real_part = 1; Res[1].Imag_Part= 0; for(count_1 = 0;count_1 < N-1;count_1++) { for(count = 0;count <= count_1 + 2;count++) { if(0 == count) { Complex_Multiple(Res[count], zero, &(Res_Save[count].Real_part), &(Res_Save[count].Imag_Part)); } else if((count_1 + 2) == count) { Res_Save[count].Real_part += Res[count - 1].Real_part; Res_Save[count].Imag_Part += Res[count - 1].Imag_Part; } else { Complex_Multiple(Res[count],zero, &(Res_Save[count].Real_part), &(Res_Save[count].Imag_Part)); Res_Save[count].Real_part += Res[count - 1].Real_part; Res_Save[count].Imag_Part += Res[count - 1].Imag_Part; } } for(count = 0;count <= N;count++) { Res[count].Real_part = Res_Save[count].Real_part; Res[count].Imag_Part= Res_Save[count].Imag_Part; *(bz + N - count) = Res[count].Real_part; } } for(count = 0;count <= N;count++) { *(bz + N - count) = *(bz + N - count) * K_z; } //------------------------display---------------------------------// printf("bz = [" ); for(count= 0;count <= N ;count++) { printf("%lf ", *(bz+count)); } printf(" ] \n" ); printf("az = [" ); for(count= 0;count <= N ;count++) { printf("%lf ", *(az+count)); } printf(" ] \n" ); printf("--------------------------------------------------------\n" ); return (int)1; } int main(void) { int count; struct DESIGN_SPECIFICATION IIR_Filter; IIR_Filter.Cotoff = (double)(pi/4); //[red] IIR_Filter.Stopband = (double)((pi*3)/4); //[red] IIR_Filter.Stopband_attenuation = 30; //[dB] int N; IIR_Filter.Cotoff = 2 * tan((IIR_Filter.Cotoff)/2); //[red/sec] IIR_Filter.Stopband = 2 * tan((IIR_Filter.Stopband)/2); //[red/sec] N = Ceil(0.5*( log10 ( pow (10, IIR_Filter.Stopband_attenuation/10) - 1) / log10 (IIR_Filter.Stopband/IIR_Filter.Cotoff))); double az[N+1] , bz[N+1]; Direct(IIR_Filter.Cotoff, IIR_Filter.Stopband, IIR_Filter.Stopband_attenuation, N, az,bz); double *Memory_Buffer; Memory_Buffer = (double *) malloc(sizeof(double)*(N+1)); memset(Memory_Buffer, 0, sizeof(double)*(N+1)); FILE* Input_Data; FILE* Output_Data; double Input = 0 ; double Output = 0; Input_Data = fopen("input.dat","r"); Output_Data = fopen("output.txt","w"); while(1) { if(fscanf(Input_Data, "%lf", &Input) == EOF) break; Output = IIRFilter( az, (N+1), bz, (N+1), Input, Memory_Buffer ); fprintf(Output_Data,"%lf,",Output); } printf("Finish \n" ); return (int)0; }