theo này, chúng ta sẽ nghiên cứu cách sử dụng tốt nhất đáp ứng xung trong thiết kế bộ lọc IIR dùng các phương pháp Shanks.. Rõ ràng chúng ta có khả năng được chọn từ: 1.. Dùng bốn góc ph
Trang 1void bit_reversal(unsigned int *, int , int);
void WTS(float *, float *, int, int);
void FFT(float *xr, float *xi, float *, float *,int,int) ;
void transpose(FILE *, int, int);
void FFT2D(FILE *, FILE *, float *, float *, unsigned int *,
int,int,int);
void main()
{
int N,N1,m,n2,i,j,ii,jj,N2,k,norder,j1,ind,yt;
unsigned int *L;
float *wr,*wi,Do,theta,nsqrt,beta,alpha,sum1,sum2,T;
FILE *fptri,*fptro,*fptr;
float *buffi,*buffo,R2,H,nsq,win,slope,gamal,gamah;
unsigned char file_name[14], ch,ch1,file_name1[14];
clrscr() ;
printf("Freq.- response can be calculated using standard\n");
printf(" functions available to you if your reply to the\n");
printf(" following question is negative.\n");
printf("Is freq response provided in a file? (y or n) >");
while(((ch1=getche())!='y')&&(ch1!='n'));
switch(ch1)
{
case 'n':
case 'N':
printf("\nEnter # of points to be generated (e.g 32x32) >");
scanf("%d%c%d",&N1,&ch,&N1);
break;
case 'y' :
case 'Y ':
printf("\nEnter name of file storing magnitude response >");
scanf("%s",file_name1);
fptr=fopen(file_name1,"r");
fscanf(fptr,"%d %d ",&N1,&N1);
}
N=N1>>1;
yt=wherey();
again :
gotoxy(1,yt);
printf(" ");
gotoxy(1,yt);
printf("Enter file name for storing impulse response >");
scanf("%s",file_name);
Trang 2if(((stricmp("FFT.DAT",file_name))==0)||
((stricmp("TEMP.DAT",file_name))==0)||
((stricmp("IFFT.DAT",file_name))==0))
{
printf("This is a reserved file name Use some other name.");
goto again;
}
gotoxy(1,yt);
printf( " ");
ind=access(file_name,0);
while(!ind)
{
gotoxy(1,yt+1);
printf ( " ");
gotoxy(1,yt+1);
printf("File exists Wish to overwrite? (y or n) >");
while(((ch=tolower(getch()))!='y')&&(ch!='n'));
putch(ch);
switch(ch)
{
case 'y' :
ind=1 ;
break ;
case 'n' :
gotoxy(1,yt+1);
printf ( " ");
printf ( " ");
gotoxy(1,yt);
gotoxy(1,yt);
printf("Enter file name >");
scanf("%s",file_name);
ind=access(file_name,0);
}
}
fptri=fopen("FFT.DAT","wb+");
fptro=fopen("IFFT.DAT","wb+");
buffi=(float *)malloc((N1<<1)*sizeof(float));
switch(ch1)
{
case 'n' :
case 'N' :
/*Generating data for IFFT */
printf
("\nEnter cut-off freq in rad./sec ( cut-off <= n.)->");
Trang 3scanf("%f",&Do);
Do=(Do/pi)*(float)N;
printf("Enter choice (1,2,3,4 or 5):\n");
printf(" 1 Low-pass with abrupt transition.\n");
printf(" 2 High-pass with abrupt transition.\n");
printf(" 3 Low-pass Butterworth.\n");
printf(" 4 High-pass Butterworth.\n");
printf(" 5 Homomorphic characteristcs ->");
while(((ch=getche())!='l')&&(ch!='2')
&&(ch!=13)&&(ch!='4')&&(ch!='5'));
if(ch=='5')
{
printf("\nEnter gain at không freq. >");
scanf("%f",&gamah);
printf("Enter gain at high frequencies. >");
scanf("%f",&gamah);
slope=(gamah-gamal)/Do;
}
Do*=Do;
if((ch=='3')||(ch=='4'))
{
printf("\n Enter order of Butterworth >");
scanf("%d",&norder);
for(i=0;i<norder;i++)
Do*=Do;
}
printf("\n");
for(i=0;i<N1;i++)
{
ii=(i-N)*(i-N);
for(j=0;j<N1;j++)
{
R2=(float)((j-N)*(j-N)+ii);
if((ch=='3')||(ch=='4'))
{
for(j1=0;j1<norder;j1++)
R2*=R2;
}
switch(ch)
{
case '1': /* low-pass abrupt transition.*/
if(R2<Do) H=(float)1.0;
else H=(float)0.0;
break;
Trang 4case '2': /* high-pass abrupt transition*/
if(R2<Do) H=(float)0.0;
else H=(float)1.0;
break;
case '3': /* low-order Butterworth */
H=Do/(Do+0.414*R2);
break;
case '4': /* high-order Butterworth */
H=R2/(R2+0.414-Do);
break;
case '5': /* homomorphic characteristics */
if ( R2<Do)
H=slope*sqrt((double)R2)+gamal;
else
H=gamah ;
}
jj=j<<1;
buffi[jj]=H;
buffi[jj+1]=0.0;
}
fwrite(buffi,N1,2*sizeof(float),fptri);
}
break;
case 'y':
case 'Y' :
for(i=0;i<N1;i++)
{
for(j=0;j<N1;j++)
{
fscanf(fptr,"%f ",&H);
jj=j <<1 ;
buffi[jj]=H;
buffi[jj+1]=(float)0.0;
}
fwrite(buffi,N1,2*sizeof(float),fptri);
}
fclose(fptr);
}
rewind(fptri);
m=(int)(log10((double)N1)/log10((double)2));
/* Allocating memory for bit reversal LUT */
L=(unsigned int *)malloc(N1*sizeof(unsigned int));
Trang 5/* Generate Look-up table for bit reversal */
bit_reversal(L,m,N1);
/* Allocating memory for twiddle factors */
n2=N1-1;
wr=(float *)malloc(n2*sizeof(float));
wi=(float *)malloc(n2*sizeof(float));
/* Generating twiddle factor */
WTS(wr,wi,N1,1);
clrscr() ;
FFT2D(fptri,fptro,wr,wi,L,N1,m,1);
remove("FFT.DAT");
clrscr() ;
fptri=fopen("IFFT.DAT","rb");
fptro=fopen(file_name,"wb+");
nsq=(float)(N1*N1);
buffo=(float *)malloc(N1*sizeof(float));
for(i=0;i<N1;i++)
{
fread(buffi,N1,2*sizeof(float),fptri);
for(j=0;j<N1;j++)
buffo[j]=buffi[2*j]/nsq;
fwrite(buffo,N1,sizeof(float),fptro);
}
fclose(fptri);
remove("IFFT.DAT");
rewind(fptro);
printf("Enter selection of window function:");
printf("\n 1.Rectangular.");
printf("\n 2.Hann.");
printf("\n 3.Hamming.");
printf("\n 4.Blackmann.");
printf("\n 5.Kaiser.");
printf("\nEnter (1,2 etc.) >");
while(((ch=getche())!='I')&&(ch!='2')&&
(ch!='3')&&(ch!='4')&&(ch!='5'));
printf("\n");
if(ch!='1')
{
N2=N1/2 ;
theta=pi/((float)N2*sqrt((double)2.0));
for(i=0;i<N1;i++)
{
Trang 6ii=(i-N2)*(i-N2);
fread(buffo,N1,sizeof(float),fptro);
for(j=0;j<N1;j++)
{
jj=(j-N2)*(j-N2);
nsq=(float)(ii+jj);
nsqrt=sqrt((double)nsq)/sqrt((double)2.0);
switch(ch)
{
case '2':
win=0.5+0.5*cos((double)(theta*nsqrt));
buffo[j]*=win;
break;
case '3' :
win=0.54+0.46*cos((double)(theta*nsqrt));
buffo[j]*=win;
break;
case '4' :
win=0.42+0.5*cos((double)(theta*nsqrt))
+0.08*cos((double)(2.0*theta*nsqrt));
buffo[j]*=win;
break;
case '5':
if((i+j)==0)
{
printf("\n\nEnter a value for alpha (1 to 8) >");
scanf("%f",&alpha);
alpha/=2.0;
}
beta=nsqrt/(float)N2;
beta*=beta;
beta=alpha*sqrt(fabs((double)(1.0-beta)));
T=alpha;
sum1+=1.0+T*T;
for(k=2;k<11;k++)
{
T=(1.0/(float)k)*alpha*T;
sum1+=T*T;
}
T=beta;
sum2=1.0+T*T;
for(k=2;k<11;k++)
{
T=(1.0/(float)k)*alpha*T;
Trang 7sum2+=T*T;
}
win=sum2/sum1;
buffo[j]*=win;
break;
}
}
fwrite(buffo,N1,sizeof(float),fptro);
}
}
printf
("\nDo you wish to store data for 3-D plotting? (y or n) >");
while(((ch=getche())!='y')&&(ch!='n'));
switch(ch)
{
case 'n':
fclose(fptro);
exit(1);
case 'y':
rewind(fptro);
}
printf("\nEnter file name for storing data for 3-D plotting ->");
scanf("%s",file_name);
fptri=fopen(file_name,"w");
fprintf(fptri,"%d %d\n",N1,N1);
fprintf(fptri,"%e",(float)0.0);
for(i=0;i<N1;i++)
fprintf(fptri,"%e",(float)i);
for(i=0;i<N1;i++)
{
fprintf(fptri,"\n");
fread(buffo,N1,sizeof(float),fptro);
fprintf(fptri,"%e",(float)i);
for(j=0;j<N1;j++)
fprintf(fptri," %e",buffo[j]);
}
fclose(fptri);
fclose(fptro);
}
9.5 Thiết kế bộ lọc IIR
Hình 9.3 biểu diễn miền không gian của đáp ứng xung Vòng tròn xẫm màu
nằm ở trung tâm chứa những biên độ lớn nhất của h d (m,n) Trong phần tiếp
Trang 8theo này, chúng ta sẽ nghiên cứu cách sử dụng tốt nhất đáp ứng xung trong thiết kế bộ lọc IIR dùng các phương pháp Shanks Rõ ràng chúng ta có khả năng được chọn từ:
1 Dùng bốn góc phần tư của đáp ứng xung với điểm (0,0) nằm ở tại trung tâm của miền
2 Dịch chuyển các trục để (0,0) nằm ở góc cao bên trái (Hình 9.3a)
3 Tính đáp ứng xung từ góc phần tư nằm ở bên phải phía dưới (Hình 9.3a)
4 Dịch chuyển các trục một đoạn đủ lớn để bao khối lớn nhất của đáp ứng xung (Hình 9.3b)
Đáp ứng xung mong muốn được trích ra từ miền gạch chéo trong hình 9.3b Lựa chọn đầu tiên yêu cầu chúng ta phải chuyển hàm truyền đạt dưới dạng :
Hình 9.3 (a) Chọn một phần tư hay góc phần tư thứ tư (b) Chọn miền lớn hơn
bao gồm những giá trị trội trong đáp ứng xung
j i ij N
N j
N
N i
j i ij N
N j
N
N i
z z b
z z a z
z H
2 1
2 1 2
1 , )
Chú ý rằng nếu bạn nhân biểu thức (9.24)với z 1 N z 2 N, chúng ta sẽ chuyển hàm truyền đạt thành một hệ thống nhân quả Dù thế nào đi chăng nữa tính không nhân quả có nghĩa là điều kiện khởi đầu khác 0 và điều này cũng chỉ ra
(0,0)
Một phần tư mặt phẳng
M
offset
m’
m
n’ n
(a)
n’ n
m
(b) offset