Các biểu thức từ 6.29 đến 6.36 cho kết quả trong bước thứ ba của thuật thể chia tiếp thành hai phần tử nữa và bước này tạo thành sơ đồ cuối cùng bước đầu tiên trong lưu đồ... Hình 6.3 Bư
Trang 1
(n) F W (n) F (n)
(n) F W -(n) F 2) (n
k
0
1
( ) ( )
k
0
3
( ) ( )
., vv
Các biểu thức từ (6.29) đến (6.36) cho kết quả trong bước thứ ba của thuật
thể chia tiếp thành hai phần tử nữa và bước này tạo thành sơ đồ cuối cùng
(bước đầu tiên) trong lưu đồ
0
1
2
3
0
1
2
3
0
1
2
3
0
1
2
3
4
5
6
7
0
1
2
3
0
F20(n)
2
F21(n)
4
6
F22(n)
F 10 (n)
F (n)
X(k)
Hệ số xoay n=0 đến 3
Trang 2Hình 6.3 Bước thứ hai sau bước cuối cùng trong thuật toán FFT
Trang 3Hình 6.4 Bước đầu tiên của lưu đồ FFT
Hình 6.5 giới thiệu sơ đồ thuật toán FFT cho N = 16 Chú ý rằng do yêu cầu ban đầu của chương trình mà dãy vào được sắp xếp lại và chứa ở X(k), ví
dụ
X(k)x(q) k = 0 đến 15
0
0
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
F 30 (n)
F 31 (n)
F 32 (n)
F 33 (n)
F 34 (n)
F35(n)
F 36 (n)
F37(n)
X(k) X(k)
Dãy
đầu
vào
đã
được
sắp
xếp
lại
Trang 4Xem xét trường hợp N = 1024 = 210 Số phép nhân cần dùng cho FFT là
(N/2).10 = 1024 5 = 5120 so với 1 triệu phép nhân cho tính trực tiếp biến
đổi DFT, đây là phương pháp tiết kiệm thực sự cho tính toán
Bây giờ, chúng ta sẽ vạch ra thuật toán FFT Đó không đơn thuần chỉ là
sự phát triển một chương trình từ lưu đồ Tuy nhiên, chúng ta có thể nghiên cứu lưu đồ và vạch ra các bước có thể dùng để phát triển một chương trình
Từ lưu đồ của hình 6.5 chúng ta có thể viết:
Bước thứ nhất Trong bước này ta có tám bướm với trọng lượng (hệ số
for (j=0 đến 15 với bước tăng 2)
{
T=X(j+1);
X(j+1)=X(j) - T;
X(j)=X(j) + T;
}
Bước thứ hai Chúng ta có:
1.Bốn bướm với trọng lượng bằng 1
for (j=0 đến 15 với bước tăng 4)
{
T=X(j);
X(j+2)=X(j) - T;
X(j)=X(j) + T;
}
2 Bốn bướm với trọng lượng W4 = W(3) Chú ý rằng chúng ta coi rằng
W(6)
for (j=0 đến 15 với bước tăng 4)
{
T=X(j)W(3);X(j+2)=X(j) - T;
X(j)=X(j) + T;
}
Bước thứ ba Chúng ta có :
Trang 51 Hai bướm với trọng lượng bằng 1
for (j=0 đến 15 với bước tăng 8)
{
T=X(j);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}
0 1 2 3 4 5 6
0 2 4
0 2 4 6
0 4
0 4
0 4
0
0
0
0
0
0
0
0
0
8
4
12
2
10
6
14
1
9
5
13
3
11
7
0000
1000
0100
1100
0010
1010
0110
1110
0001
1001
0101
1101
0011
1011
0111
0 8 4 12 2 10 6 14 1 9 5 13 3 11 7
0 4 8 12 2 6 12 14 1 5 9 13 3 7 11
0 2 4 6 8 10 12 14 1 3 5 7 9 11 13
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110
n=0 n=0 đến 1 n=0 đến 3 n=0 đến 7
n
Trang 62 Hai bướm với trọng lượng bằng W(1) = W2
for (j=1 đến 15 với bước tăng 8)
{
T=X(j)W(1);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}
for (j=2 đến 15 với bước tăng 8)
{
T=X(j)W(3);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}
Hình 6.6 (a) Bướm cho thuật toán phân chia miền tần số;(b) Một bướm đơn
giản
for (j=3 đến 15 với bước tăng 8)
{
T=X(j)W(5);
X(j+4)=X(j) - T;
F(2n)
F(2n+1)
)
(
10 k
f
)
(
11 k
f
(a)
F(2n)
F(2n+1)
) (
10 k f
) (
11 k f
(b)
Trang 7X(j)=X(j) + T;
}
Bước thứ tư và là bước cuối cùng
1.Một bướm với trọng lượng bằng 1
T = X(0)
X(8)= X(0) - T
X(0) = X(8) +T
T = X(1)W(0)
X(1+8)= X(1) - T
X(1) = X(1) +T
T = X(1)W(1)
X(2+8)= X(0) - T
X(2) = X(2) +T
T = X(7)W(6)
X(7+8)= X(7)-T
X(7) = X(7) +T
Trang 8{
i = j + ip T = X(j) X(i) = X(j) - T X(j) = X(j) +T nếu (iter không bằng 0) thì {
cho k=1 đến ip-1 trong các bước của 1 {
r = k*kk - 1 cho j=k đến 15 trong các bước của 15 {
i=j+ip T=X(i)*W(r) X(i)=X(j)-1 X(j)=X(j)+T
}
}
}
kk=kk/2 ip= ip*2 inc=inc*2 }
Thuật toán trên có thể dễ dàng mở rộng cho tất cả các trường hợp của N Chỉ có một lĩnh vực còn lại cần phải giải thích là sự sắp xếp lại các dãy dữ liệu đầu vào Điều này có thể tạo ra dễ dàng nếu chúng ta tạo ra một bảng (LUT) L(i), L(i) là các giá trị đảo ngược bit của i Nếu dữ liệu được đọc từ một file thì tất cả các việc mà chúng ta phải làm là chuyển địa chỉ vùng của chúng trong file qua bảng LUT và lưu các dữ liệu này trong địa chỉ chứa kết quả trong dãy đầu vào, X Bước này có thể chuyển sang ngôn ngữ C như sau: for (i=0; i<N; i++) fscanf (fptr, “ %f ”, &X[L[i]]);
Kết quả của LUT được chuyển thẳng và được cung cấp với chương trình của thuật toán tính FFT trong Listing 6.1 dưới dạng modun con dưới tên “ bit_reversal( )”
Trang 9Chương trình 6.1 FFTDT.C FFT 1-D Thập phân trong miền thời gian
/***********************************
* ver 1.0 1992 *
* @ 1994 *
*********************************/
/* FFT - Decimation-in-time routine with examplemain
programing proper usage */
#define pi 3.141592654
#include <stdio.h>
#include <math.h>
#include <alloc.h>
#include <stdlib.h>
void bit_reversal(unsigned int *, int , int);
void WTS(float *, float *, int, int);
void FFT(float *xr, float *xi, float *, float *,
int , int);
void main()
{
int i,k,m,N,n2,sign;
unsigned int *L;
float *wr,*wi,*xr,*xi;
char file_name[14];
Trang 10}
printf("Enter # of data points to be read >");
scanf("%d",&N);
m=(int)(log10((double)N)/log10((double)2.0));
k=1;
for(i=0;i<m;i++)
k<<=1 ;
if (k!=N)
{
printf("n Length of file has to be multiples of 2 ");
exit(1);
}
/* Allocating memory for bit reversal LUT */
L=(unsigned int *)malloc(N*sizeof(unsigned int));
/* Generate Look-up table for bit reversal */
bit_reversal(L,m,N);
/* Allocating memory for FFT arrays ( real and imag.) */
xr=(float *)malloc(N*sizeof(float));
xi=(float *)malloc(N*sizeof(float));
/* Setting-up the data in real and imag arrays.*/
for(i=0;i<N;i++)
{
k=L[i] ;
xr[k]=(float)getc(fptr);
xi[k]=0.0 ;
}
fclose(fptr);
/* Allocating memory for twiddle factors */
n2=(N>>1)-1;
wr=(float *)malloc(n2*sizeof(float));
wi=(float *)malloc(n2*sizeof(float));
/*Generating LUT for
twiddle factors */
WTS(wr,wi,N,-1);